rack-proxy 0.8.2 → 1.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +172 -0
- data/LICENSE +1 -1
- data/README.md +136 -59
- data/SECURITY.md +52 -0
- data/lib/rack/http_streaming_response.rb +137 -17
- data/lib/rack/proxy/version.rb +7 -0
- data/lib/rack/proxy.rb +239 -63
- data/lib/rack-proxy.rb +3 -1
- data/rack-proxy.gemspec +20 -16
- metadata +24 -27
- data/.github/FUNDING.yml +0 -3
- data/.gitignore +0 -3
- data/.travis.yml +0 -18
- data/Gemfile +0 -6
- data/Gemfile.lock +0 -31
- data/Rakefile +0 -14
- data/lib/net_http_hacked.rb +0 -90
- data/lib/rack_proxy_examples/example_service_proxy.rb +0 -40
- data/lib/rack_proxy_examples/forward_host.rb +0 -24
- data/lib/rack_proxy_examples/rack_php_proxy.rb +0 -37
- data/lib/rack_proxy_examples/trusting_proxy.rb +0 -25
- data/test/http_streaming_response_test.rb +0 -50
- data/test/net_http_hacked_test.rb +0 -36
- data/test/rack_proxy_test.rb +0 -321
- data/test/test_helper.rb +0 -11
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rack-proxy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jacek Becela
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: bin
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-07-23 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: rack
|
|
@@ -15,14 +16,20 @@ dependencies:
|
|
|
15
16
|
requirements:
|
|
16
17
|
- - ">="
|
|
17
18
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0'
|
|
19
|
+
version: '2.0'
|
|
20
|
+
- - "<"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: '4'
|
|
19
23
|
type: :runtime
|
|
20
24
|
prerelease: false
|
|
21
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
26
|
requirements:
|
|
23
27
|
- - ">="
|
|
24
28
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '0'
|
|
29
|
+
version: '2.0'
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '4'
|
|
26
33
|
- !ruby/object:Gem::Dependency
|
|
27
34
|
name: rack-test
|
|
28
35
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -73,31 +80,24 @@ executables: []
|
|
|
73
80
|
extensions: []
|
|
74
81
|
extra_rdoc_files: []
|
|
75
82
|
files:
|
|
76
|
-
-
|
|
77
|
-
- ".gitignore"
|
|
78
|
-
- ".travis.yml"
|
|
79
|
-
- Gemfile
|
|
80
|
-
- Gemfile.lock
|
|
83
|
+
- CHANGELOG.md
|
|
81
84
|
- LICENSE
|
|
82
85
|
- README.md
|
|
83
|
-
-
|
|
84
|
-
- lib/net_http_hacked.rb
|
|
86
|
+
- SECURITY.md
|
|
85
87
|
- lib/rack-proxy.rb
|
|
86
88
|
- lib/rack/http_streaming_response.rb
|
|
87
89
|
- lib/rack/proxy.rb
|
|
88
|
-
- lib/
|
|
89
|
-
- lib/rack_proxy_examples/forward_host.rb
|
|
90
|
-
- lib/rack_proxy_examples/rack_php_proxy.rb
|
|
91
|
-
- lib/rack_proxy_examples/trusting_proxy.rb
|
|
90
|
+
- lib/rack/proxy/version.rb
|
|
92
91
|
- rack-proxy.gemspec
|
|
93
|
-
- test/http_streaming_response_test.rb
|
|
94
|
-
- test/net_http_hacked_test.rb
|
|
95
|
-
- test/rack_proxy_test.rb
|
|
96
|
-
- test/test_helper.rb
|
|
97
92
|
homepage: https://github.com/ncr/rack-proxy
|
|
98
93
|
licenses:
|
|
99
94
|
- MIT
|
|
100
|
-
metadata:
|
|
95
|
+
metadata:
|
|
96
|
+
source_code_uri: https://github.com/ncr/rack-proxy
|
|
97
|
+
changelog_uri: https://github.com/ncr/rack-proxy/blob/master/CHANGELOG.md
|
|
98
|
+
bug_tracker_uri: https://github.com/ncr/rack-proxy/issues
|
|
99
|
+
rubygems_mfa_required: 'true'
|
|
100
|
+
post_install_message:
|
|
101
101
|
rdoc_options: []
|
|
102
102
|
require_paths:
|
|
103
103
|
- lib
|
|
@@ -105,18 +105,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
105
105
|
requirements:
|
|
106
106
|
- - ">="
|
|
107
107
|
- !ruby/object:Gem::Version
|
|
108
|
-
version: '
|
|
108
|
+
version: '3.0'
|
|
109
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
110
|
requirements:
|
|
111
111
|
- - ">="
|
|
112
112
|
- !ruby/object:Gem::Version
|
|
113
113
|
version: '0'
|
|
114
114
|
requirements: []
|
|
115
|
-
rubygems_version: 3.
|
|
115
|
+
rubygems_version: 3.5.22
|
|
116
|
+
signing_key:
|
|
116
117
|
specification_version: 4
|
|
117
118
|
summary: A request/response rewriting HTTP proxy. A Rack app.
|
|
118
|
-
test_files:
|
|
119
|
-
- test/http_streaming_response_test.rb
|
|
120
|
-
- test/net_http_hacked_test.rb
|
|
121
|
-
- test/rack_proxy_test.rb
|
|
122
|
-
- test/test_helper.rb
|
|
119
|
+
test_files: []
|
data/.github/FUNDING.yml
DELETED
data/.gitignore
DELETED
data/.travis.yml
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
cache: bundler
|
|
2
|
-
language: ruby
|
|
3
|
-
before_install:
|
|
4
|
-
- "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
|
|
5
|
-
- gem install bundler
|
|
6
|
-
- gem update bundler
|
|
7
|
-
script: bundle exec rake test
|
|
8
|
-
rvm:
|
|
9
|
-
- 2.0.0
|
|
10
|
-
- 2.1.5
|
|
11
|
-
- 2.2.2
|
|
12
|
-
- 2.2.3
|
|
13
|
-
- 2.3.0
|
|
14
|
-
- 2.3.1
|
|
15
|
-
env:
|
|
16
|
-
- RAILS_ENV=test RACK_ENV=test
|
|
17
|
-
notifications:
|
|
18
|
-
email: false
|
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
rack-proxy (0.8.2)
|
|
5
|
-
rack
|
|
6
|
-
|
|
7
|
-
GEM
|
|
8
|
-
remote: https://rubygems.org/
|
|
9
|
-
specs:
|
|
10
|
-
power_assert (2.0.3)
|
|
11
|
-
rack (3.2.6)
|
|
12
|
-
rack-test (2.1.0)
|
|
13
|
-
rack (>= 1.3)
|
|
14
|
-
rake (13.0.6)
|
|
15
|
-
test-unit (3.6.1)
|
|
16
|
-
power_assert
|
|
17
|
-
webrick (1.9.2)
|
|
18
|
-
|
|
19
|
-
PLATFORMS
|
|
20
|
-
arm64-darwin-22
|
|
21
|
-
x86_64-linux
|
|
22
|
-
|
|
23
|
-
DEPENDENCIES
|
|
24
|
-
rack-proxy!
|
|
25
|
-
rack-test
|
|
26
|
-
rake
|
|
27
|
-
test-unit
|
|
28
|
-
webrick
|
|
29
|
-
|
|
30
|
-
BUNDLED WITH
|
|
31
|
-
2.4.17
|
data/Rakefile
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
require 'rubygems'
|
|
2
|
-
require 'bundler'
|
|
3
|
-
Bundler::GemHelper.install_tasks
|
|
4
|
-
|
|
5
|
-
require "rake/testtask"
|
|
6
|
-
task :test do
|
|
7
|
-
Rake::TestTask.new do |t|
|
|
8
|
-
t.libs << "test"
|
|
9
|
-
t.test_files = FileList['test/*_test.rb']
|
|
10
|
-
t.verbose = true
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
task :default => :test
|
data/lib/net_http_hacked.rb
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# We are hacking net/http to change semantics of streaming handling
|
|
2
|
-
# from "block" semantics to regular "return" semantics.
|
|
3
|
-
# We need it to construct a streamable rack triplet:
|
|
4
|
-
#
|
|
5
|
-
# [status, headers, streamable_body]
|
|
6
|
-
#
|
|
7
|
-
# See http://github.com/zerowidth/rack-streaming-proxy
|
|
8
|
-
# for alternative that uses additional process.
|
|
9
|
-
#
|
|
10
|
-
# BTW I don't like monkey patching either
|
|
11
|
-
# but this is not real monkey patching.
|
|
12
|
-
# I just added some methods and named them very uniquely
|
|
13
|
-
# to avoid eventual conflicts. You're safe. Trust me.
|
|
14
|
-
#
|
|
15
|
-
# Also, in Ruby 1.9.2 you could use Fibers to avoid hacking net/http.
|
|
16
|
-
|
|
17
|
-
require 'net/https'
|
|
18
|
-
|
|
19
|
-
class Net::HTTP
|
|
20
|
-
# Original #request with block semantics.
|
|
21
|
-
#
|
|
22
|
-
# def request(req, body = nil, &block)
|
|
23
|
-
# unless started?
|
|
24
|
-
# start {
|
|
25
|
-
# req['connection'] ||= 'close'
|
|
26
|
-
# return request(req, body, &block)
|
|
27
|
-
# }
|
|
28
|
-
# end
|
|
29
|
-
# if proxy_user()
|
|
30
|
-
# unless use_ssl?
|
|
31
|
-
# req.proxy_basic_auth proxy_user(), proxy_pass()
|
|
32
|
-
# end
|
|
33
|
-
# end
|
|
34
|
-
#
|
|
35
|
-
# req.set_body_internal body
|
|
36
|
-
# begin_transport req
|
|
37
|
-
# req.exec @socket, @curr_http_version, edit_path(req.path)
|
|
38
|
-
# begin
|
|
39
|
-
# res = HTTPResponse.read_new(@socket)
|
|
40
|
-
# end while res.kind_of?(HTTPContinue)
|
|
41
|
-
# res.reading_body(@socket, req.response_body_permitted?) {
|
|
42
|
-
# yield res if block_given?
|
|
43
|
-
# }
|
|
44
|
-
# end_transport req, res
|
|
45
|
-
#
|
|
46
|
-
# res
|
|
47
|
-
# end
|
|
48
|
-
|
|
49
|
-
def begin_request_hacked(req)
|
|
50
|
-
begin_transport req
|
|
51
|
-
req.exec @socket, @curr_http_version, edit_path(req.path)
|
|
52
|
-
begin
|
|
53
|
-
res = Net::HTTPResponse.read_new(@socket)
|
|
54
|
-
end while res.kind_of?(Net::HTTPContinue)
|
|
55
|
-
res.begin_reading_body_hacked(@socket, req.response_body_permitted?)
|
|
56
|
-
@req_hacked, @res_hacked = req, res
|
|
57
|
-
@res_hacked
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def end_request_hacked
|
|
61
|
-
@res_hacked.end_reading_body_hacked
|
|
62
|
-
end_transport @req_hacked, @res_hacked
|
|
63
|
-
@res_hacked
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
class Net::HTTPResponse
|
|
68
|
-
# Original #reading_body with block semantics
|
|
69
|
-
#
|
|
70
|
-
# def reading_body(sock, reqmethodallowbody) #:nodoc: internal use only
|
|
71
|
-
# @socket = sock
|
|
72
|
-
# @body_exist = reqmethodallowbody && self.class.body_permitted?
|
|
73
|
-
# begin
|
|
74
|
-
# yield
|
|
75
|
-
# self.body # ensure to read body
|
|
76
|
-
# ensure
|
|
77
|
-
# @socket = nil
|
|
78
|
-
# end
|
|
79
|
-
# end
|
|
80
|
-
|
|
81
|
-
def begin_reading_body_hacked(sock, reqmethodallowbody)
|
|
82
|
-
@socket = sock
|
|
83
|
-
@body_exist = reqmethodallowbody && self.class.body_permitted?
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def end_reading_body_hacked
|
|
87
|
-
self.body
|
|
88
|
-
@socket = nil
|
|
89
|
-
end
|
|
90
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
###
|
|
2
|
-
# This is an example of how to use Rack-Proxy in a Rails application.
|
|
3
|
-
#
|
|
4
|
-
# Setup:
|
|
5
|
-
# 1. rails new test_app
|
|
6
|
-
# 2. cd test_app
|
|
7
|
-
# 3. install Rack-Proxy in `Gemfile`
|
|
8
|
-
# a. `gem 'rack-proxy', '~> 0.7.7'`
|
|
9
|
-
# 4. install gem: `bundle install`
|
|
10
|
-
# 5. create `config/initializers/proxy.rb` adding this line `require 'rack_proxy_examples/example_service_proxy'`
|
|
11
|
-
# 6. run: `SERVICE_URL=http://guides.rubyonrails.org rails server`
|
|
12
|
-
# 7. open in browser: `http://localhost:3000/example_service`
|
|
13
|
-
#
|
|
14
|
-
###
|
|
15
|
-
ENV['SERVICE_URL'] ||= 'http://guides.rubyonrails.org'
|
|
16
|
-
|
|
17
|
-
class ExampleServiceProxy < Rack::Proxy
|
|
18
|
-
def perform_request(env)
|
|
19
|
-
request = Rack::Request.new(env)
|
|
20
|
-
|
|
21
|
-
# use rack proxy for anything hitting our host app at /example_service
|
|
22
|
-
if request.path =~ %r{^/example_service}
|
|
23
|
-
backend = URI(ENV['SERVICE_URL'])
|
|
24
|
-
# most backends required host set properly, but rack-proxy doesn't set this for you automatically
|
|
25
|
-
# even when a backend host is passed in via the options
|
|
26
|
-
env["HTTP_HOST"] = backend.host
|
|
27
|
-
|
|
28
|
-
# This is the only path that needs to be set currently on Rails 5 & greater
|
|
29
|
-
env['PATH_INFO'] = ENV['SERVICE_PATH'] || '/configuring.html'
|
|
30
|
-
|
|
31
|
-
# don't send your sites cookies to target service, unless it is a trusted internal service that can parse all your cookies
|
|
32
|
-
env['HTTP_COOKIE'] = ''
|
|
33
|
-
super(env)
|
|
34
|
-
else
|
|
35
|
-
@app.call(env)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
Rails.application.config.middleware.use ExampleServiceProxy, backend: ENV['SERVICE_URL'], streaming: false
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
class ForwardHost < Rack::Proxy
|
|
2
|
-
|
|
3
|
-
def rewrite_env(env)
|
|
4
|
-
env["HTTP_HOST"] = "example.com"
|
|
5
|
-
env
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def rewrite_response(triplet)
|
|
9
|
-
status, headers, body = triplet
|
|
10
|
-
|
|
11
|
-
# example of inserting an additional header
|
|
12
|
-
headers["X-Foo"] = "Bar"
|
|
13
|
-
|
|
14
|
-
# if you rewrite env, it appears that content-length isn't calculated correctly
|
|
15
|
-
# resulting in only partial responses being sent to users
|
|
16
|
-
# you can remove it or recalculate it here
|
|
17
|
-
headers["content-length"] = nil
|
|
18
|
-
|
|
19
|
-
triplet
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
Rails.application.config.middleware.use ForwardHost, backend: 'http://example.com', streaming: false
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
###
|
|
2
|
-
# Open http://localhost:3000/test.php to trigger proxy
|
|
3
|
-
###
|
|
4
|
-
class RackPhpProxy < Rack::Proxy
|
|
5
|
-
|
|
6
|
-
def perform_request(env)
|
|
7
|
-
request = Rack::Request.new(env)
|
|
8
|
-
if request.path =~ %r{\.php}
|
|
9
|
-
env["HTTP_HOST"] = ENV["HTTP_HOST"] ? URI(ENV["HTTP_HOST"]).host : "localhost"
|
|
10
|
-
ENV["PHP_PATH"] ||= '/manual/en/tutorial.firstpage.php'
|
|
11
|
-
|
|
12
|
-
# Rails 3 & 4
|
|
13
|
-
env["REQUEST_PATH"] = ENV["PHP_PATH"] || "/php/#{request.fullpath}"
|
|
14
|
-
# Rails 5 and above
|
|
15
|
-
env['PATH_INFO'] = ENV["PHP_PATH"] || "/php/#{request.fullpath}"
|
|
16
|
-
|
|
17
|
-
env['content-length'] = nil
|
|
18
|
-
|
|
19
|
-
super(env)
|
|
20
|
-
else
|
|
21
|
-
@app.call(env)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def rewrite_response(triplet)
|
|
26
|
-
status, headers, body = triplet
|
|
27
|
-
|
|
28
|
-
# if you proxy depending on the backend, it appears that content-length isn't calculated correctly
|
|
29
|
-
# resulting in only partial responses being sent to users
|
|
30
|
-
# you can remove it or recalculate it here
|
|
31
|
-
headers["content-length"] = nil
|
|
32
|
-
|
|
33
|
-
triplet
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
Rails.application.config.middleware.use RackPhpProxy, backend: ENV["HTTP_HOST"]='http://php.net', streaming: false
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
class TrustingProxy < Rack::Proxy
|
|
2
|
-
|
|
3
|
-
def rewrite_env(env)
|
|
4
|
-
env["HTTP_HOST"] = "self-signed.badssl.com"
|
|
5
|
-
env
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def rewrite_response(triplet)
|
|
9
|
-
status, headers, body = triplet
|
|
10
|
-
|
|
11
|
-
# if you rewrite env, it appears that content-length isn't calculated correctly
|
|
12
|
-
# resulting in only partial responses being sent to users
|
|
13
|
-
# you can remove it or recalculate it here
|
|
14
|
-
headers["content-length"] = nil
|
|
15
|
-
|
|
16
|
-
triplet
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Pass ssl_verify_none: true to skip TLS certificate verification.
|
|
22
|
-
Rails.application.config.middleware.use TrustingProxy,
|
|
23
|
-
backend: 'https://self-signed.badssl.com',
|
|
24
|
-
streaming: false,
|
|
25
|
-
ssl_verify_none: true
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
require "test_helper"
|
|
2
|
-
require "rack/http_streaming_response"
|
|
3
|
-
|
|
4
|
-
class HttpStreamingResponseTest < Test::Unit::TestCase
|
|
5
|
-
|
|
6
|
-
def setup
|
|
7
|
-
host, req = "example.com", Net::HTTP::Get.new("/")
|
|
8
|
-
@response = Rack::HttpStreamingResponse.new(req, host, 443)
|
|
9
|
-
@response.use_ssl = true
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def test_streaming
|
|
13
|
-
# Response status
|
|
14
|
-
assert_equal 200, @response.status
|
|
15
|
-
assert_equal 200, @response.status
|
|
16
|
-
|
|
17
|
-
# Headers
|
|
18
|
-
headers = @response.headers
|
|
19
|
-
|
|
20
|
-
assert headers.size.positive?
|
|
21
|
-
|
|
22
|
-
assert_match %r{text/html}, headers["content-type"].first.downcase
|
|
23
|
-
assert_equal headers["content-type"], headers["CoNtEnT-TyPe"]
|
|
24
|
-
|
|
25
|
-
# Body
|
|
26
|
-
chunks = []
|
|
27
|
-
@response.body.each do |chunk|
|
|
28
|
-
chunks << chunk
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
assert chunks.size.positive?
|
|
32
|
-
chunks.each do |chunk|
|
|
33
|
-
assert chunk.is_a?(String)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def test_to_s
|
|
39
|
-
body_string = @response.body.to_s
|
|
40
|
-
assert body_string.bytesize.positive?
|
|
41
|
-
content_length = @response.headers["Content-Length"]
|
|
42
|
-
assert_equal content_length.first.to_i, body_string.bytesize if content_length
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def test_to_s_called_twice
|
|
46
|
-
body = @response.body
|
|
47
|
-
assert_equal body.to_s, body.to_s
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
end
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
require "test_helper"
|
|
2
|
-
require "net_http_hacked"
|
|
3
|
-
|
|
4
|
-
class NetHttpHackedTest < Test::Unit::TestCase
|
|
5
|
-
|
|
6
|
-
def test_net_http_hacked
|
|
7
|
-
req = Net::HTTP::Get.new("/")
|
|
8
|
-
http = Net::HTTP.start("www.iana.org", "80")
|
|
9
|
-
|
|
10
|
-
# Response code
|
|
11
|
-
res = http.begin_request_hacked(req)
|
|
12
|
-
assert res.code == "200"
|
|
13
|
-
|
|
14
|
-
# Headers
|
|
15
|
-
headers = {}
|
|
16
|
-
res.each_header { |k, v| headers[k] = v }
|
|
17
|
-
|
|
18
|
-
assert headers.size > 0
|
|
19
|
-
assert headers["content-type"] == "text/html; charset=UTF-8"
|
|
20
|
-
assert !headers["date"].nil?
|
|
21
|
-
|
|
22
|
-
# Body
|
|
23
|
-
chunks = []
|
|
24
|
-
res.read_body do |chunk|
|
|
25
|
-
chunks << chunk
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
assert chunks.size > 0
|
|
29
|
-
chunks.each do |chunk|
|
|
30
|
-
assert chunk.is_a?(String)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
http.end_request_hacked
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
end
|