net-http-pipeline 0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ '75
2
+ �Vq�א�D�r}���
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
@@ -0,0 +1,6 @@
1
+ === 0.0 / 2010-12-07
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
@@ -0,0 +1,8 @@
1
+ .autotest
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ lib/net/http/pipeline.rb
7
+ sample/two_get.rb
8
+ test/test_net_http_pipeline.rb
@@ -0,0 +1,60 @@
1
+ = net-http-pipeline
2
+
3
+ * http://seattlerb.rubyforge.org/net-http-pipeline
4
+ * http://github.com/drbrain/net-http-pipeline
5
+
6
+ == DESCRIPTION:
7
+
8
+ An HTTP/1.1 pipelining implementation atop Net::HTTP. This is an experimental
9
+ proof of concept.
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ * Provides HTTP/1.1 pipelining
14
+ * Does not implement request wrangling per RFC 2616 8.1.2.2
15
+ * Does not handle errors
16
+ * May not work on Ruby 1.8, untested
17
+
18
+ == SYNOPSIS:
19
+
20
+ require 'net/http/pipeline'
21
+
22
+ Net::HTTP.start 'localhost' do |http|
23
+ req1 = Net::HTTP::Get.new '/'
24
+ req2 = Net::HTTP::Get.new '/'
25
+
26
+ http.pipeline req1, req2 do |res|
27
+ puts res.code
28
+ puts res.body[0..60].inspect
29
+ puts
30
+ end
31
+ end
32
+
33
+ == INSTALL:
34
+
35
+ gem install net-http-pipeline
36
+
37
+ == LICENSE:
38
+
39
+ (The MIT License)
40
+
41
+ Copyright (c) 2010 Eric Hodel
42
+
43
+ Permission is hereby granted, free of charge, to any person obtaining
44
+ a copy of this software and associated documentation files (the
45
+ 'Software'), to deal in the Software without restriction, including
46
+ without limitation the rights to use, copy, modify, merge, publish,
47
+ distribute, sublicense, and/or sell copies of the Software, and to
48
+ permit persons to whom the Software is furnished to do so, subject to
49
+ the following conditions:
50
+
51
+ The above copyright notice and this permission notice shall be
52
+ included in all copies or substantial portions of the Software.
53
+
54
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
55
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
56
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
57
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
58
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
59
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
60
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,14 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.plugin :git
7
+ Hoe.plugin :minitest
8
+ Hoe.plugins.delete :rubyforge
9
+
10
+ Hoe.spec 'net-http-pipeline' do
11
+ developer 'Eric Hodel', 'drbrain@segment7.net'
12
+ end
13
+
14
+ # vim: syntax=Ruby
@@ -0,0 +1,103 @@
1
+ require 'net/http'
2
+
3
+ ##
4
+ # An HTTP/1.1 pipelining implementation atop Net::HTTP. Currently this is not
5
+ # compliant with RFC 2616 8.1.2.2.
6
+ #
7
+ # Pipeline allows pou to create a bunch of requests then pipeline them to an
8
+ # HTTP/1.1 server.
9
+ #
10
+ # = Example
11
+ #
12
+ # require 'net/http/pipeline'
13
+ #
14
+ # Net::HTTP.start 'localhost' do |http|
15
+ # req1 = Net::HTTP::Get.new '/'
16
+ # req2 = Net::HTTP::Get.new '/'
17
+ #
18
+ # http.pipeline req1, req2 do |res|
19
+ # puts res.code
20
+ # puts res.body[0..60].inspect
21
+ # puts
22
+ # end
23
+ # end
24
+
25
+ module Net::HTTP::Pipeline
26
+
27
+ VERSION = '0.0'
28
+
29
+ ##
30
+ # Pipeline error class
31
+
32
+ class Error < RuntimeError
33
+ end
34
+
35
+ ##
36
+ # Pipelines +requests+ to the HTTP server yielding responses if a block is
37
+ # given. Returns all responses recieved.
38
+ #
39
+ # Raises an exception if the connection is not pipelining-capable or if the
40
+ # HTTP session has not been started.
41
+
42
+ def pipeline *requests
43
+ raise Error, 'pipelining requires HTTP/1.1 or newer' unless
44
+ @curr_http_version >= '1.1'
45
+ raise Error, 'Net::HTTP not started' unless started?
46
+
47
+ requests.each do |req|
48
+ begin_transport req
49
+ req.exec @socket, @curr_http_version, edit_path(req.path)
50
+ end
51
+
52
+ responses = []
53
+
54
+ requests.each do |req|
55
+ begin
56
+ res = Net::HTTPResponse.read_new @socket
57
+ end while res.kind_of? Net::HTTPContinue
58
+
59
+ res.reading_body @socket, req.response_body_permitted? do
60
+ responses << res
61
+ yield res if block_given?
62
+ end
63
+
64
+ pipeline_end_transport res
65
+ end
66
+
67
+ responses
68
+ end
69
+
70
+ ##
71
+ # Updates the HTTP version and ensures the connection has keep-alive.
72
+
73
+ def pipeline_end_transport res
74
+ @curr_http_version = res.http_version
75
+
76
+ if @socket.closed? then
77
+ D 'Conn socket closed on pipeline'
78
+ elsif pipeline_keep_alive? res then
79
+ D 'Conn pipeline keep-alive'
80
+ else
81
+ D 'Conn close on pipeline'
82
+ @socket.close
83
+ end
84
+ end
85
+
86
+ ##
87
+ # Checks for an connection close header
88
+
89
+ def pipeline_keep_alive? res
90
+ not res.connection_close?
91
+ end
92
+
93
+ end
94
+
95
+ class Net::HTTP
96
+
97
+ ##
98
+ # Adds pipeline support to Net::HTTP
99
+
100
+ include Pipeline
101
+
102
+ end
103
+
@@ -0,0 +1,12 @@
1
+ require 'net/http/pipeline'
2
+
3
+ Net::HTTP.start 'localhost' do |http|
4
+ req1 = Net::HTTP::Get.new '/'
5
+ req2 = Net::HTTP::Get.new '/'
6
+
7
+ http.pipeline req1, req2 do |res|
8
+ puts res.code
9
+ puts res.body[0..60].inspect
10
+ puts
11
+ end
12
+ end
@@ -0,0 +1,200 @@
1
+ require "test/unit"
2
+ require 'net/http/pipeline'
3
+ require 'stringio'
4
+
5
+ class TestNetHttpPipeline < Test::Unit::TestCase
6
+
7
+ ##
8
+ # Net::BufferedIO stub
9
+
10
+ class Buffer
11
+ attr_accessor :read_io, :write_io
12
+ def initialize
13
+ @read_io = StringIO.new
14
+ @write_io = StringIO.new
15
+ @closed = false
16
+ end
17
+
18
+ def close
19
+ @closed = true
20
+ end
21
+
22
+ def closed?
23
+ @closed
24
+ end
25
+
26
+ def finish
27
+ @write_io.rewind
28
+ end
29
+
30
+ def read bytes, dest = '', ignored = nil
31
+ @read_io.read bytes, dest
32
+
33
+ dest
34
+ end
35
+
36
+ def readline
37
+ @read_io.readline.chomp "\r\n"
38
+ end
39
+
40
+ def readuntil terminator, ignored
41
+ @read_io.gets terminator
42
+ end
43
+
44
+ def start
45
+ @read_io.rewind
46
+ end
47
+
48
+ def write data
49
+ @write_io.write data
50
+ end
51
+ end
52
+
53
+ include Net::HTTP::Pipeline
54
+
55
+ attr_writer :started
56
+
57
+ def setup
58
+ @curr_http_version = '1.1'
59
+ @started = true
60
+ end
61
+
62
+ def D(*) end
63
+
64
+ def begin_transport req
65
+ end
66
+
67
+ def edit_path path
68
+ path
69
+ end
70
+
71
+ def http_response body, *extra_header
72
+ http_response = []
73
+ http_response << 'HTTP/1.1 200 OK'
74
+ http_response << "Content-Length: #{body.bytesize}"
75
+ http_response.push(*extra_header)
76
+ http_response.push nil, nil # Array chomps on #join
77
+
78
+ http_response.join("\r\n") << body
79
+ end
80
+
81
+ def response
82
+ r = Net::HTTPResponse.allocate
83
+ def r.http_version() Net::HTTP::HTTPVersion end
84
+ def r.read_body() true end
85
+
86
+ r.instance_variable_set :@header, {}
87
+ def r.header() @header end
88
+ r
89
+ end
90
+
91
+ def started?() @started end
92
+
93
+ def test_pipeline
94
+ @socket = Buffer.new
95
+
96
+ @socket.read_io.write http_response('Worked 1!')
97
+ @socket.read_io.write http_response('Worked 2!')
98
+
99
+ req1 = Net::HTTP::Get.new '/'
100
+ req2 = Net::HTTP::Get.new '/'
101
+
102
+ @socket.start
103
+
104
+ responses = pipeline req1, req2
105
+
106
+ @socket.finish
107
+
108
+ expected = <<-EXPECTED
109
+ GET / HTTP/1.1\r
110
+ Accept: */*\r
111
+ User-Agent: Ruby\r
112
+ \r
113
+ GET / HTTP/1.1\r
114
+ Accept: */*\r
115
+ User-Agent: Ruby\r
116
+ \r
117
+ EXPECTED
118
+
119
+ assert_equal expected, @socket.write_io.read
120
+ refute @socket.closed?
121
+
122
+ assert_equal 'Worked 1!', responses.first.body
123
+ assert_equal 'Worked 2!', responses.last.body
124
+ end
125
+
126
+ def test_pipeline_connection_close
127
+ @socket = Buffer.new
128
+
129
+ @socket.read_io.write http_response('Worked 1!', 'Connection: close')
130
+
131
+ req1 = Net::HTTP::Get.new '/'
132
+
133
+ @socket.start
134
+
135
+ pipeline req1
136
+
137
+ @socket.finish
138
+
139
+ assert @socket.closed?
140
+ end
141
+
142
+ def test_pipeline_http_1_0
143
+ @curr_http_version = '1.0'
144
+
145
+ e = assert_raises Net::HTTP::Pipeline::Error do
146
+ pipeline
147
+ end
148
+
149
+ assert_equal 'pipelining requires HTTP/1.1 or newer', e.message
150
+ end
151
+
152
+ def test_pipeline_not_started
153
+ @started = false
154
+
155
+ e = assert_raises Net::HTTP::Pipeline::Error do
156
+ pipeline
157
+ end
158
+
159
+ assert_equal 'Net::HTTP not started', e.message
160
+ end
161
+
162
+ def test_pipeline_end_transport
163
+ @curr_http_version = nil
164
+
165
+ res = response
166
+
167
+ @socket = StringIO.new
168
+
169
+ pipeline_end_transport res
170
+
171
+ refute @socket.closed?
172
+ assert_equal '1.1', @curr_http_version
173
+ end
174
+
175
+ def test_pipeline_end_transport_no_keep_alive
176
+ @curr_http_version = nil
177
+
178
+ res = response
179
+ res.header['connection'] = ['close']
180
+
181
+ @socket = StringIO.new
182
+
183
+ pipeline_end_transport res
184
+
185
+ assert @socket.closed?
186
+ assert_equal '1.1', @curr_http_version
187
+ end
188
+
189
+ def test_pipeline_keep_alive_eh
190
+ res = response
191
+
192
+ assert pipeline_keep_alive? res
193
+
194
+ res.header['connection'] = ['close']
195
+
196
+ refute pipeline_keep_alive? res
197
+ end
198
+
199
+ end
200
+
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: net-http-pipeline
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ version: "0.0"
9
+ platform: ruby
10
+ authors:
11
+ - Eric Hodel
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain:
15
+ - |
16
+ -----BEGIN CERTIFICATE-----
17
+ MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
18
+ YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu
19
+ ZXQwHhcNMDcxMjIxMDIwNDE0WhcNMDgxMjIwMDIwNDE0WjBBMRAwDgYDVQQDDAdk
20
+ cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ
21
+ FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76
22
+ LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J
23
+ U5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm
24
+ Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY
25
+ mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd
26
+ g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh
27
+ sCANiQ8BAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
28
+ BBS5k4Z75VSpdM0AclG2UvzFA/VW5DANBgkqhkiG9w0BAQUFAAOCAQEAHagT4lfX
29
+ kP/hDaiwGct7XPuVGbrOsKRVD59FF5kETBxEc9UQ1clKWngf8JoVuEoKD774dW19
30
+ bU0GOVWO+J6FMmT/Cp7nuFJ79egMf/gy4gfUfQMuvfcr6DvZUPIs9P/TlK59iMYF
31
+ DIOQ3DxdF3rMzztNUCizN4taVscEsjCcgW6WkUJnGdqlu3OHWpQxZBJkBTjPCoc6
32
+ UW6on70SFPmAy/5Cq0OJNGEWBfgD9q7rrs/X8GGwUWqXb85RXnUVi/P8Up75E0ag
33
+ 14jEc90kN+C7oI/AGCBN0j6JnEtYIEJZibjjDJTSMWlUKKkj30kq7hlUC2CepJ4v
34
+ x52qPcexcYZR7w==
35
+ -----END CERTIFICATE-----
36
+
37
+ date: 2010-12-07 00:00:00 -08:00
38
+ default_executable:
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: minitest
42
+ prerelease: false
43
+ requirement: &id001 !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ segments:
49
+ - 2
50
+ - 0
51
+ - 0
52
+ version: 2.0.0
53
+ type: :development
54
+ version_requirements: *id001
55
+ - !ruby/object:Gem::Dependency
56
+ name: hoe
57
+ prerelease: false
58
+ requirement: &id002 !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 2
65
+ - 6
66
+ - 0
67
+ version: 2.6.0
68
+ type: :development
69
+ version_requirements: *id002
70
+ description: |-
71
+ An HTTP/1.1 pipelining implementation atop Net::HTTP. This is an experimental
72
+ proof of concept.
73
+ email:
74
+ - drbrain@segment7.net
75
+ executables: []
76
+
77
+ extensions: []
78
+
79
+ extra_rdoc_files:
80
+ - History.txt
81
+ - Manifest.txt
82
+ - README.txt
83
+ files:
84
+ - .autotest
85
+ - History.txt
86
+ - Manifest.txt
87
+ - README.txt
88
+ - Rakefile
89
+ - lib/net/http/pipeline.rb
90
+ - sample/two_get.rb
91
+ - test/test_net_http_pipeline.rb
92
+ has_rdoc: true
93
+ homepage: http://seattlerb.rubyforge.org/net-http-pipeline
94
+ licenses: []
95
+
96
+ post_install_message:
97
+ rdoc_options:
98
+ - --main
99
+ - README.txt
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ segments:
116
+ - 0
117
+ version: "0"
118
+ requirements: []
119
+
120
+ rubyforge_project: net-http-pipeline
121
+ rubygems_version: 1.3.7
122
+ signing_key:
123
+ specification_version: 3
124
+ summary: An HTTP/1.1 pipelining implementation atop Net::HTTP
125
+ test_files:
126
+ - test/test_net_http_pipeline.rb
@@ -0,0 +1,3 @@
1
+ 0�@�
2
+ ��c� 8TU�Mׅ�Ͻ�����\9��=�W����}l����_$����� �Q��}JBV*��4�`��Rʴ0u�uzw�]����^}'¦#�I^(U`�0��q|�����?0�t�P �Iz%ѵ��H�;=�����Hfw: �O��Iחn�\A�F��J�w* �h=��4L4g�NI�>y�� m�o��?�7����y��et2�,-��-�AL"_;I�<b�P�)���K�
3
+ R��ˍ�r5��x�x