rubylet-rack 2.0.0.pre1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Common Ground Publishing
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.0.0.pre1
@@ -0,0 +1,5 @@
1
+ require 'rubylet/rack/dechunking_body'
2
+ require 'rubylet/rack/errors'
3
+ require 'rubylet/rack/ext'
4
+ require 'rubylet/rack/rewindable_io'
5
+ require 'rubylet/rack/session/container_store'
@@ -0,0 +1,45 @@
1
+ module Rubylet
2
+ module Rack
3
+ # Rails and possibly others manually set 'Transfer-Encoding:
4
+ # chunked' and then send the body as chunks. Java servlet
5
+ # environment expects the server to handle chunking as needed
6
+ # (e.g. when a response overflows the buffer and must be flushed to
7
+ # the client before the servlet has closed the stream).
8
+ #
9
+ # This class makes the rather large assumption that {body#each}
10
+ # iterates through the chunks, so we don't actually do much parsing.
11
+ #
12
+ # FIXME: ignores encoding?
13
+ class DechunkingBody
14
+ EOL = "\r\n".freeze
15
+
16
+ CHUNK_START = Regexp.compile /^((\h+)#{Regexp.quote(EOL)})/
17
+
18
+ def initialize(body)
19
+ @body = body
20
+ end
21
+
22
+ def each
23
+ @body.each do |chunk|
24
+ yield chunk_to_part(chunk)
25
+ end
26
+ end
27
+
28
+ def close
29
+ @body.close
30
+ end
31
+
32
+ private
33
+
34
+ def chunk_to_part(chunk)
35
+ if chunk =~ CHUNK_START
36
+ chunk_start = $1.bytesize
37
+ chunk_length = $2.to_i(16)
38
+ chunk.byteslice(chunk_start, chunk_length)
39
+ else
40
+ chunk
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ # Implements the rack.errors interface, logging everything via
2
+ # ServletContext#log
3
+ module Rubylet
4
+ module Rack
5
+ class Errors
6
+ def initialize(context)
7
+ @context = context
8
+ end
9
+
10
+ def puts(obj)
11
+ write(obj.to_s)
12
+ end
13
+
14
+ def write(str)
15
+ @context.log(str)
16
+ end
17
+
18
+ # A no-op for ServletContext#log
19
+ def flush; end
20
+
21
+ # Spec says this must never be called
22
+ def close; end
23
+ end
24
+ end
25
+ end
Binary file
@@ -0,0 +1,40 @@
1
+ require 'rubylet/rack/errors'
2
+
3
+ # TODO: should this wrap slf4j or something? Or is it typically overridden
4
+ # by the rack application?
5
+ module Rubylet
6
+ module Rack
7
+ class Logger < Rubylet::Errors
8
+
9
+ def info(message = nil, &block)
10
+ log(:info, message, &block)
11
+ end
12
+
13
+ def debug(message = nil, &block)
14
+ log(:debug, message, &block)
15
+ end
16
+
17
+ def warn(message = nil, &block)
18
+ log(:warn, message, &block)
19
+ end
20
+
21
+ def error(message = nil, &block)
22
+ log(:error, message, &block)
23
+ end
24
+
25
+ def fatal(message = nil, &block)
26
+ log(:fatal, message, &block)
27
+ end
28
+
29
+ def log(level, message = nil, &block)
30
+ msg = if message
31
+ message
32
+ elsif block_given?
33
+ yield
34
+ end
35
+
36
+ write("#{level.to_s.upcase}: #{msg}")
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,80 @@
1
+ require 'tempfile'
2
+
3
+ # A memory/file IO buffer. Data will be written to a memory buffer up
4
+ # to a limit, after which a file buffer is used. Supports Rack input
5
+ # stream operations. Not threadsafe.
6
+ module Rubylet::Rack
7
+ class MemFileIO
8
+ DEFAULT_LIMIT = 4096 * 4
9
+
10
+ # @param [Integer] limit the max size of the first (memory) buffer
11
+ def initialize(limit = DEFAULT_LIMIT)
12
+ @limit = limit
13
+ @mem = StringIO.new
14
+ @file = nil
15
+ end
16
+
17
+ def puts(str)
18
+ for_write(str.size + $/.size).puts(str)
19
+ end
20
+
21
+ def write(str)
22
+ for_write(str.size).write(str)
23
+ end
24
+
25
+ def gets
26
+ for_read.gets
27
+ end
28
+
29
+ def read(length = nil, buffer = nil)
30
+ if buffer
31
+ for_read.read(length, buffer)
32
+ else
33
+ for_read.read(length)
34
+ end
35
+ end
36
+
37
+ def each(&block)
38
+ for_read.each(&block)
39
+ end
40
+
41
+ def rewind
42
+ for_read.rewind
43
+ end
44
+
45
+ def close
46
+ for_read.close
47
+ end
48
+
49
+ private
50
+
51
+ def for_read
52
+ @mem || @file
53
+ end
54
+
55
+ def switch_to_file
56
+ mem = @mem
57
+ @mem = nil
58
+ mem.rewind
59
+ @file = make_file(mem.read)
60
+ end
61
+
62
+ def for_write(size)
63
+ if @file
64
+ @file
65
+ elsif (@mem.size + size) <= @limit
66
+ @mem
67
+ else
68
+ switch_to_file
69
+ @file
70
+ end
71
+ end
72
+
73
+ def make_file(data)
74
+ file = Tempfile.new('MemFileBacking')
75
+ file.unlink
76
+ file.write(data)
77
+ file
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,66 @@
1
+ require 'rubylet/rack/tee_io'
2
+ require 'rubylet/rack/mem_file_io'
3
+ require 'stringio'
4
+
5
+ # Wraps an IO with a memory and file backed buffer to support Rack's
6
+ # required #rewind.
7
+ #
8
+ # Only some IO methods are supported.
9
+ module Rubylet::Rack
10
+ class RewindableIO
11
+ def initialize(io, limit = MemFileIO::DEFAULT_LIMIT)
12
+ @buf = MemFileIO.new(limit)
13
+ @io = TeeIO.new(io, @buf)
14
+ end
15
+
16
+ def gets
17
+ str = @buf.gets
18
+ if str.nil? # end of buffer
19
+ @io.gets
20
+ elsif str.end_with?($/) # good, we got a whole line
21
+ str
22
+ else # partial line
23
+ str + (@io.gets || '')
24
+ end
25
+ end
26
+
27
+ def read(length = nil, buffer = nil)
28
+ if length.nil? && buffer.nil?
29
+ @buf.read + @io.read
30
+ elsif length.nil?
31
+ @buf.read(nil, buffer)
32
+ @io.read(nil, buffer)
33
+ elsif buffer.nil?
34
+ str = ''
35
+ @buf.read(length, str)
36
+ if (str.size == length)
37
+ @io.read(length - str.size, str)
38
+ end
39
+ str
40
+ else # both non-nil
41
+ size0 = buffer.size
42
+ @buf.read(length, buffer)
43
+ from_buf = buffer.size - size0
44
+ if (from_buf < length)
45
+ @io.read(length - from_buf, buffer)
46
+ end
47
+ buffer
48
+ end
49
+ end
50
+
51
+ def each
52
+ while s = gets
53
+ yield s
54
+ end
55
+ end
56
+
57
+ def rewind
58
+ @buf.rewind
59
+ end
60
+
61
+ def close
62
+ @buf.close
63
+ @io.close
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,63 @@
1
+ # A Rack compatible session object that forwards to an underlying
2
+ # +javax.servlet.http.HttpSession+.
3
+ module Rubylet; module Rack
4
+ class Session
5
+ # @param [javax.servlet.http.HttpServletRequest] req
6
+ # @param [Hash] options
7
+ # @option options [Integer] :expire_after The max inactive interval, in seconds
8
+ def initialize(req, options={})
9
+ @javaSession = req.getSession
10
+
11
+ if @javaSession.isNew
12
+ if exp = options[:expire_after]
13
+ req.setMaxInactiveInterval exp.to_i
14
+ end
15
+ end
16
+ end
17
+
18
+ def store(key, value)
19
+ @javaSession.setAttribute(key, value)
20
+ end
21
+ alias_method :[]=, :store
22
+
23
+ def fetch(key, default = nil)
24
+ @javaSession.getAttribute(key) || default
25
+ end
26
+ alias_method :[], :fetch
27
+
28
+ def delete(key)
29
+ @javaSession.removeAttribute(key)
30
+ end
31
+
32
+ def clear
33
+ @javaSession.getAttributeNames.each {|key| delete(key) }
34
+ end
35
+
36
+ # This method is not required by the Rack SPEC for session
37
+ # objects, but Rails calls it anyway in +actionpack (3.2.9)
38
+ # lib/action_dispatch/middleware/flash.rb:258:in `call'+
39
+ def has_key?(key)
40
+ !(fetch(key).nil?)
41
+ end
42
+ alias_method :include?, :has_key?
43
+ alias_method :key?, :has_key?
44
+ alias_method :member?, :has_key?
45
+
46
+ # Used by Rails but not required by Rack.
47
+ def destroy
48
+ @javaSession.invalidate
49
+ end
50
+
51
+ def to_hash
52
+ hash = {}
53
+ @javaSession.getAttributeNames.each do
54
+ |key| hash[key] = @javaSession.getAttribute(key)
55
+ end
56
+ hash
57
+ end
58
+
59
+ def inspect
60
+ to_hash.inspect
61
+ end
62
+ end
63
+ end; end
@@ -0,0 +1,29 @@
1
+ require 'rubylet/rack/session'
2
+
3
+ # Rack middleware to make the servlet container's sessions available to ruby.
4
+ module Rubylet
5
+ module Rack
6
+ class Session
7
+ class ContainerStore
8
+ def initialize(app, options={})
9
+ @app = app
10
+ @options = options
11
+ end
12
+
13
+ def call(env)
14
+ context(env)
15
+ end
16
+
17
+ # For Rack::Util::Context
18
+ def context(env, app=@app)
19
+ if req = env['java.servlet_request']
20
+ env['rack.session'] = Session.new(req, @options)
21
+ else
22
+ env['rack.errors'].puts 'java.servlet_request not found; cannot make session'
23
+ end
24
+ app.call(env)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ # All reads on +io+ are copied to +out+. Only supports IO methods
2
+ # specified by Rack Input Stream spec.
3
+ module Rubylet::Rack
4
+ class TeeIO
5
+ def initialize(io, out)
6
+ @io = io
7
+ @out = out
8
+ end
9
+
10
+ # Does not support custom separator per Rack spec
11
+ def gets
12
+ str = @io.gets
13
+ @out.write(str) if str
14
+ str
15
+ end
16
+
17
+ def read(length = nil, buffer = nil)
18
+ str = ''
19
+ ret = @io.read(length, str)
20
+ @out.write(str)
21
+ if buffer
22
+ buffer << str
23
+ if ret.object_id == str.object_id
24
+ buffer
25
+ else
26
+ ret
27
+ end
28
+ else
29
+ ret
30
+ end
31
+ end
32
+
33
+ def each
34
+ while s = gets
35
+ yield s
36
+ end
37
+ end
38
+
39
+ def close
40
+ @io.close
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'rubylet/rack/dechunking_body'
3
+
4
+ module Rubylet::Rack
5
+ describe DechunkingBody do
6
+ def chunk(strs)
7
+ strs.map do |str|
8
+ str.bytesize.to_s(16) + "\r\n" + str + "\r\n"
9
+ end + ["0\r\n\r\n"]
10
+ end
11
+
12
+ def dechunk(body)
13
+ ''.tap do |str|
14
+ DechunkingBody.new(body).each { |part| str << part }
15
+ end
16
+ end
17
+
18
+ it 'de-chunks a chunked body' do
19
+ data = ["some", "data", "\n in chunks."]
20
+ expected = data.join
21
+ assert_equal expected, dechunk(chunk(data))
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+ require 'rubylet/rack/mem_file_io'
3
+
4
+ module Rubylet::Rack
5
+
6
+ describe MemFileIO do
7
+
8
+ it 'writes data with puts' do
9
+ @io = MemFileIO.new
10
+ @io.puts('hello')
11
+ @io.rewind
12
+ @io.read.must_equal "hello#{$/}"
13
+ end
14
+
15
+ it 'writes data with write' do
16
+ @io = MemFileIO.new
17
+ @io.write('hello')
18
+ @io.rewind
19
+ @io.read.must_equal 'hello'
20
+ end
21
+
22
+ it 'allows multiple rewind' do
23
+ @io = MemFileIO.new
24
+
25
+ @io.write('hello')
26
+ @io.rewind
27
+ @io.read.must_equal 'hello'
28
+
29
+ @io.write('hello')
30
+ @io.rewind
31
+ @io.read.must_equal 'hellohello'
32
+ end
33
+
34
+ it 'overwrites? (FIXME: is this correct?)' do
35
+ @io = MemFileIO.new
36
+
37
+ @io.write('hello')
38
+ @io.rewind
39
+ @io.read.must_equal 'hello'
40
+
41
+ @io.rewind
42
+ @io.write('***')
43
+ @io.rewind
44
+ @io.read.must_equal '***lo'
45
+ end
46
+
47
+ it 'switches to backing file' do
48
+ @io = MemFileIO.new(4)
49
+ @io.write('1234')
50
+ @io.write('5678')
51
+ @io.rewind
52
+ @io.read.must_equal '12345678'
53
+ end
54
+
55
+ it 'returns nil on EOF' do
56
+ @io = MemFileIO.new
57
+ @io.read
58
+ @io.read(1).must_equal nil
59
+ end
60
+
61
+ it 'returns empty string on EOF' do
62
+ @io = MemFileIO.new
63
+ @io.read
64
+ @io.read.must_equal ''
65
+ end
66
+ end
67
+
68
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+ require 'rubylet/rack/rewindable_io'
3
+ require 'stringio'
4
+
5
+ module Rubylet::Rack
6
+
7
+ describe RewindableIO do
8
+
9
+ data = "some data\nwith newlines\nanother line"
10
+
11
+ before :each do
12
+ @io = StringIO.new
13
+ @io.write(data)
14
+ @io.rewind
15
+
16
+ @reio = RewindableIO.new(@io)
17
+ end
18
+
19
+ it 'rewinds' do
20
+ @reio.read.must_equal data
21
+ @reio.rewind
22
+ @reio.read.must_equal data
23
+ end
24
+
25
+ it 'rewinds with file spill over' do
26
+ expected = ''
27
+ 10.times do
28
+ @io.write(data)
29
+ expected << data
30
+ end
31
+ @io.rewind
32
+
33
+ @reio = RewindableIO.new(@io, 32)
34
+ @reio.read.must_equal expected
35
+ @reio.rewind
36
+ @reio.read.must_equal expected
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+ require 'rubylet/rack/tee_io'
3
+ require 'stringio'
4
+
5
+ module Rubylet::Rack
6
+
7
+ describe TeeIO do
8
+
9
+ DATA = "some data\nwith newlines\nanother line"
10
+
11
+ before :each do
12
+ @io = StringIO.new
13
+ @io.write(DATA)
14
+ @io.rewind
15
+
16
+ @out = StringIO.new
17
+
18
+ @tee = TeeIO.new(@io, @out)
19
+ end
20
+
21
+ it 'copies data on read' do
22
+ @tee.read
23
+ @out.rewind
24
+ @out.read.must_equal DATA
25
+ end
26
+
27
+ describe '#gets' do
28
+ it 'copies data on gets' do
29
+ @tee.gets
30
+ @out.rewind
31
+ @out.read.must_equal "some data\n"
32
+ end
33
+
34
+ it 'returns nil on EOF' do
35
+ @tee.read
36
+ @tee.gets.must_equal nil
37
+ end
38
+ end
39
+
40
+ it 'copies data on each' do
41
+ @tee.each {}
42
+ @out.rewind
43
+ @out.read.must_equal DATA
44
+ end
45
+
46
+ it 'copies data byte by byte' do
47
+ @tee.read(1)
48
+ @tee.read(1)
49
+ @out.rewind
50
+ @out.read.must_equal 'so'
51
+ end
52
+
53
+ it 'reads data into a given buffer' do
54
+ buf = String.new
55
+ ret = @tee.read nil, buf
56
+
57
+ ret.object_id.must_equal buf.object_id
58
+
59
+ buf.must_equal DATA
60
+ @out.rewind
61
+ @out.read.must_equal DATA
62
+ end
63
+
64
+ it 'returns nil on EOF' do
65
+ @tee.read
66
+ @tee.read(1).must_equal nil
67
+ end
68
+
69
+ it 'returns empty string on EOF' do
70
+ @tee.read
71
+ @tee.read.must_equal ''
72
+ end
73
+ end
74
+
75
+ end
@@ -0,0 +1,5 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ require 'minitest/matchers'
4
+
5
+ module Rubylet; module Rack; end; end;
metadata ADDED
@@ -0,0 +1,191 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubylet-rack
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: 6
5
+ version: 2.0.0.pre1
6
+ platform: java
7
+ authors:
8
+ - Patrick Mahoney
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: !binary |-
21
+ MA==
22
+ none: false
23
+ requirement: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: !binary |-
28
+ MA==
29
+ none: false
30
+ prerelease: false
31
+ type: :runtime
32
+ - !ruby/object:Gem::Dependency
33
+ name: mechanize
34
+ version_requirements: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: !binary |-
39
+ MA==
40
+ none: false
41
+ requirement: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: !binary |-
46
+ MA==
47
+ none: false
48
+ prerelease: false
49
+ type: :development
50
+ - !ruby/object:Gem::Dependency
51
+ name: mini_aether
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: !binary |-
57
+ MA==
58
+ none: false
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: !binary |-
64
+ MA==
65
+ none: false
66
+ prerelease: false
67
+ type: :development
68
+ - !ruby/object:Gem::Dependency
69
+ name: minitest-matchers
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: !binary |-
75
+ MA==
76
+ none: false
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: !binary |-
82
+ MA==
83
+ none: false
84
+ prerelease: false
85
+ type: :development
86
+ - !ruby/object:Gem::Dependency
87
+ name: rake
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: !binary |-
93
+ MA==
94
+ none: false
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: !binary |-
100
+ MA==
101
+ none: false
102
+ prerelease: false
103
+ type: :development
104
+ - !ruby/object:Gem::Dependency
105
+ name: unf
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "<="
109
+ - !ruby/object:Gem::Version
110
+ version: 0.0.5
111
+ none: false
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "<="
115
+ - !ruby/object:Gem::Version
116
+ version: 0.0.5
117
+ none: false
118
+ prerelease: false
119
+ type: :development
120
+ - !ruby/object:Gem::Dependency
121
+ name: version
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - "~>"
125
+ - !ruby/object:Gem::Version
126
+ version: !binary |-
127
+ MQ==
128
+ none: false
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - "~>"
132
+ - !ruby/object:Gem::Version
133
+ version: !binary |-
134
+ MQ==
135
+ none: false
136
+ prerelease: false
137
+ type: :development
138
+ description: Java Servlet implementation that forwards to Rack application
139
+ email:
140
+ - pat@polycrystal.org
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - VERSION
146
+ - MIT-LICENSE
147
+ - lib/rubylet/rack/ext.jar
148
+ - lib/rubylet/rack.rb
149
+ - lib/rubylet/rack/dechunking_body.rb
150
+ - lib/rubylet/rack/errors.rb
151
+ - lib/rubylet/rack/logger.rb
152
+ - lib/rubylet/rack/mem_file_io.rb
153
+ - lib/rubylet/rack/rewindable_io.rb
154
+ - lib/rubylet/rack/session.rb
155
+ - lib/rubylet/rack/tee_io.rb
156
+ - lib/rubylet/rack/session/container_store.rb
157
+ - spec/spec_helper.rb
158
+ - spec/rubylet/rack/dechunking_body_spec.rb
159
+ - spec/rubylet/rack/mem_file_io_spec.rb
160
+ - spec/rubylet/rack/rewindable_io_spec.rb
161
+ - spec/rubylet/rack/tee_io_spec.rb
162
+ homepage:
163
+ licenses: []
164
+ post_install_message:
165
+ rdoc_options: []
166
+ require_paths:
167
+ - lib
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ segments:
173
+ - 0
174
+ hash: 2
175
+ version: !binary |-
176
+ MA==
177
+ none: false
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - !binary |-
181
+ Pg==
182
+ - !ruby/object:Gem::Version
183
+ version: 1.3.1
184
+ none: false
185
+ requirements: []
186
+ rubyforge_project:
187
+ rubygems_version: 1.8.24
188
+ signing_key:
189
+ specification_version: 3
190
+ summary: Java Servlet implementation that forwards to Rack application
191
+ test_files: []