rbkb-http 0.2.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.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/History.txt +4 -0
- data/LICENSE +22 -0
- data/README.rdoc +18 -0
- data/Rakefile +59 -0
- data/VERSION +1 -0
- data/lib/rbkb/http/base.rb +179 -0
- data/lib/rbkb/http/body.rb +220 -0
- data/lib/rbkb/http/common.rb +74 -0
- data/lib/rbkb/http/headers.rb +406 -0
- data/lib/rbkb/http/parameters.rb +220 -0
- data/lib/rbkb/http/request.rb +76 -0
- data/lib/rbkb/http/response.rb +86 -0
- data/lib/rbkb/http.rb +22 -0
- data/rbkb-http.gemspec +74 -0
- data/spec/rbkb-http_spec.rb +7 -0
- data/spec/spec_helper.rb +9 -0
- data/test/test_helper.rb +9 -0
- data/test/test_http.rb +27 -0
- data/test/test_http_helper.rb +59 -0
- data/test/test_http_request.rb +136 -0
- data/test/test_http_response.rb +222 -0
- metadata +103 -0
@@ -0,0 +1,86 @@
|
|
1
|
+
|
2
|
+
module Rbkb::Http
|
3
|
+
# A Response encapsulates all the entities in a HTTP response,
|
4
|
+
# including the status header, general headers, and body.
|
5
|
+
class Response < Base
|
6
|
+
attr_accessor :status
|
7
|
+
|
8
|
+
alias first_entity status
|
9
|
+
alias first_entity= status=
|
10
|
+
|
11
|
+
# Returns a raw HTTP response for this instance. Must have a status
|
12
|
+
# element defined at a bare minimum.
|
13
|
+
def to_raw(raw_body=nil)
|
14
|
+
raise "this response has no status" unless first_entity()
|
15
|
+
self.headers ||= default_headers_obj()
|
16
|
+
self.body = raw_body if raw_body
|
17
|
+
|
18
|
+
if do_chunked_encoding?(@headers)
|
19
|
+
unless @body.is_a? ChunkedBody
|
20
|
+
@body = ChunkedBody.new(@body, @body.opts)
|
21
|
+
end
|
22
|
+
@headers.delete_header("Content-Length")
|
23
|
+
elsif not opts[:ignore_content_length]
|
24
|
+
unless @body.is_a? BoundBody
|
25
|
+
@body = BoundBody.new(@body, @body.opts)
|
26
|
+
end
|
27
|
+
@headers.delete_header("Transfer-Encoding")
|
28
|
+
else
|
29
|
+
@body = Body.new(@body, @body.opts)
|
30
|
+
end
|
31
|
+
@body.base = self
|
32
|
+
|
33
|
+
yield(self) if block_given?
|
34
|
+
|
35
|
+
bstr = @body.to_raw
|
36
|
+
hdrs = @headers.to_raw_array.unshift(self.first_entity.to_raw)
|
37
|
+
return "#{hdrs.join("\r\n")}\r\n\r\n#{bstr}"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Parses a raw HTTP response and captures data into the current instance.
|
41
|
+
def capture(str)
|
42
|
+
raise "arg 0 must be a string" unless String === str
|
43
|
+
hstr, bstr = str.split(/\s*\r?\n\r?\n/, 2)
|
44
|
+
|
45
|
+
capture_headers(hstr)
|
46
|
+
|
47
|
+
yield(self, bstr) if block_given?
|
48
|
+
|
49
|
+
unless @body and @body.capture_complete?
|
50
|
+
@body =
|
51
|
+
if do_chunked_encoding?
|
52
|
+
ChunkedBody.new {|b| b.base = self }
|
53
|
+
elsif content_length()
|
54
|
+
BoundBody.new {|b| b.base = self }
|
55
|
+
else
|
56
|
+
Body.new {|b| b.base = self }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
capture_body(bstr)
|
61
|
+
|
62
|
+
return self
|
63
|
+
end
|
64
|
+
|
65
|
+
# Indicates whether to use chunked encoding based on presence of
|
66
|
+
# the "Transfer-Encoding: chunked" header or the :ignore_chunked_encoding
|
67
|
+
# opts parameter.
|
68
|
+
def do_chunked_encoding?(hdrs=@headers)
|
69
|
+
( (not @opts[:ignore_chunked_encoding]) and
|
70
|
+
(hdrs.get_header_value("Transfer-Encoding").to_s =~ /(?:^|\W)chunked(?:\W|$)/) )
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns a new Headers object extended as ResponseHeaders. This is the
|
74
|
+
# default object which will be used when composing fresh Response header
|
75
|
+
# entities.
|
76
|
+
def default_headers_obj(*args)
|
77
|
+
Headers.new(*args).extend(ResponseHeaders)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a new BoundBody object. This is the default object which will
|
81
|
+
# be used when composing fresh Response body entities.
|
82
|
+
def default_body_obj(*args)
|
83
|
+
BoundBody.new(*args)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/rbkb/http.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
begin ; require 'rubygems' ; rescue LoadError ; end
|
2
|
+
|
3
|
+
require 'rbkb'
|
4
|
+
|
5
|
+
# ???Why???? would anyone create their own HTTP implementation in ruby with
|
6
|
+
# so many options out there? Short answer: Net::HTTP and others just don't cut
|
7
|
+
# it in lots of edge cases. I needed something I could control completely.
|
8
|
+
|
9
|
+
module Rbkb::Http
|
10
|
+
# nop
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'time' # gives us Time.httpdate parser and output methods
|
14
|
+
|
15
|
+
require "rbkb/http/common.rb"
|
16
|
+
require "rbkb/http/base.rb"
|
17
|
+
require "rbkb/http/request.rb"
|
18
|
+
require "rbkb/http/response.rb"
|
19
|
+
require "rbkb/http/headers.rb"
|
20
|
+
require "rbkb/http/body.rb"
|
21
|
+
require "rbkb/http/parameters.rb"
|
22
|
+
|
data/rbkb-http.gemspec
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{rbkb-http}
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Eric Monti"]
|
12
|
+
s.date = %q{2009-11-12}
|
13
|
+
s.description = %q{HTTP libraries and tools based on and complementary to Ruby BlackBag}
|
14
|
+
s.email = %q{emonti@matasano.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"History.txt",
|
23
|
+
"LICENSE",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"lib/rbkb/http.rb",
|
28
|
+
"lib/rbkb/http/base.rb",
|
29
|
+
"lib/rbkb/http/body.rb",
|
30
|
+
"lib/rbkb/http/common.rb",
|
31
|
+
"lib/rbkb/http/headers.rb",
|
32
|
+
"lib/rbkb/http/parameters.rb",
|
33
|
+
"lib/rbkb/http/request.rb",
|
34
|
+
"lib/rbkb/http/response.rb",
|
35
|
+
"rbkb-http.gemspec",
|
36
|
+
"spec/rbkb-http_spec.rb",
|
37
|
+
"spec/spec_helper.rb",
|
38
|
+
"test/test_helper.rb",
|
39
|
+
"test/test_http.rb",
|
40
|
+
"test/test_http_helper.rb",
|
41
|
+
"test/test_http_request.rb",
|
42
|
+
"test/test_http_response.rb"
|
43
|
+
]
|
44
|
+
s.homepage = %q{http://github.com/emonti/rbkb-http}
|
45
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
46
|
+
s.require_paths = ["lib"]
|
47
|
+
s.rubygems_version = %q{1.3.5}
|
48
|
+
s.summary = %q{HTTP protocol add-ons for Ruby BlackBag}
|
49
|
+
s.test_files = [
|
50
|
+
"spec/rbkb-http_spec.rb",
|
51
|
+
"spec/spec_helper.rb",
|
52
|
+
"test/test_helper.rb",
|
53
|
+
"test/test_http.rb",
|
54
|
+
"test/test_http_helper.rb",
|
55
|
+
"test/test_http_request.rb",
|
56
|
+
"test/test_http_response.rb"
|
57
|
+
]
|
58
|
+
|
59
|
+
if s.respond_to? :specification_version then
|
60
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
61
|
+
s.specification_version = 3
|
62
|
+
|
63
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
64
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
65
|
+
s.add_runtime_dependency(%q<rbkb>, [">= 0"])
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
68
|
+
s.add_dependency(%q<rbkb>, [">= 0"])
|
69
|
+
end
|
70
|
+
else
|
71
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
72
|
+
s.add_dependency(%q<rbkb>, [">= 0"])
|
73
|
+
end
|
74
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/test/test_helper.rb
ADDED
data/test/test_http.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_http_helper.rb'
|
2
|
+
|
3
|
+
class TestHttp < Test::Unit::TestCase
|
4
|
+
include Rbkb::Http
|
5
|
+
|
6
|
+
def test_names
|
7
|
+
assert_equal CommonInterface, Rbkb::Http::CommonInterface
|
8
|
+
assert_equal Base, Rbkb::Http::Base
|
9
|
+
|
10
|
+
assert_equal Response, Rbkb::Http::Response
|
11
|
+
assert_equal Request, Rbkb::Http::Request
|
12
|
+
assert_equal Parameters, Rbkb::Http::Parameters
|
13
|
+
assert_equal FormUrlencodedParams, Rbkb::Http::FormUrlencodedParams
|
14
|
+
|
15
|
+
assert_equal Headers, Rbkb::Http::Headers
|
16
|
+
assert_equal RequestHeaders, Rbkb::Http::RequestHeaders
|
17
|
+
assert_equal RequestAction, Rbkb::Http::RequestAction
|
18
|
+
assert_equal ResponseHeaders, Rbkb::Http::ResponseHeaders
|
19
|
+
assert_equal ResponseStatus, Rbkb::Http::ResponseStatus
|
20
|
+
|
21
|
+
assert_equal Body, Rbkb::Http::Body
|
22
|
+
assert_equal BoundBody, Rbkb::Http::BoundBody
|
23
|
+
assert_equal ChunkedBody, Rbkb::Http::ChunkedBody
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper.rb')
|
2
|
+
|
3
|
+
module HttpTestHelper
|
4
|
+
# contains various test cases to test common interface features
|
5
|
+
module CommonInterfaceTests
|
6
|
+
|
7
|
+
def setup()
|
8
|
+
raise "Helper stub called. Override setup() in TestCase"
|
9
|
+
end
|
10
|
+
|
11
|
+
def do_type_tests(x)
|
12
|
+
raise "Helper stub called. Override do_type_tests() in TestCase"
|
13
|
+
end
|
14
|
+
|
15
|
+
def do_type_tests(x)
|
16
|
+
raise "Helper stub called. Override do_capture_value_tests() in TestCase"
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_init_parse
|
20
|
+
req = @obj_klass.new(@rawdat, @obj_opts)
|
21
|
+
do_capture_value_tests(req)
|
22
|
+
do_type_tests(req)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_parse
|
26
|
+
req = @obj_klass.parse(@rawdat, @obj_opts)
|
27
|
+
do_capture_value_tests(req)
|
28
|
+
do_type_tests(req)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_capture
|
32
|
+
req = @obj.capture(@rawdat)
|
33
|
+
do_capture_value_tests(req)
|
34
|
+
do_type_tests(req)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_back_to_raw
|
38
|
+
req = @obj.capture(@rawdat)
|
39
|
+
assert_equal @rawdat_crlf, req.to_raw
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_capture_and_reuse_nondestructive
|
43
|
+
@obj.capture(@rawdat_crlf)
|
44
|
+
@obj.reset_capture
|
45
|
+
@obj.capture(@rawdat_crlf)
|
46
|
+
do_capture_value_tests(@obj)
|
47
|
+
do_type_tests(@obj)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_capture_and_reuse_destructive
|
51
|
+
@obj.capture(@rawdat_crlf)
|
52
|
+
@obj.reset_capture!
|
53
|
+
@obj.capture(@rawdat_crlf)
|
54
|
+
do_capture_value_tests(@obj)
|
55
|
+
do_type_tests(@obj)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_http_helper.rb'
|
2
|
+
|
3
|
+
class TestHttpRequest < Test::Unit::TestCase
|
4
|
+
include HttpTestHelper::CommonInterfaceTests
|
5
|
+
|
6
|
+
include Rbkb::Http
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@obj_klass = Request
|
10
|
+
@obj = @obj_klass.new
|
11
|
+
|
12
|
+
@rawdat =<<_EOF_
|
13
|
+
GET /csi?v=3&s=webhp&action=&tran=undefined HTTP/1.1
|
14
|
+
Host: www.google.com
|
15
|
+
User-Agent: Mozilla/5.0
|
16
|
+
Accept: image/png,image/*;q=0.8,*/*;q=0.5
|
17
|
+
Accept-Language: en-us,en;q=0.5
|
18
|
+
Accept-Encoding: gzip,deflate
|
19
|
+
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
20
|
+
Keep-Alive: 300
|
21
|
+
Proxy-Connection: keep-alive
|
22
|
+
Referer: http://www.google.com/
|
23
|
+
Cookie: PREFID=NNNN:LM=1237996892:S=YYYYY; NID=111
|
24
|
+
|
25
|
+
_EOF_
|
26
|
+
|
27
|
+
@hstr, @body = @rawdat.split(/^\n/, 2)
|
28
|
+
@rawdat_crlf = @hstr.gsub("\n", "\r\n") + "\r\n" + @body
|
29
|
+
|
30
|
+
@verb = "GET"
|
31
|
+
@uri = "/csi?v=3&s=webhp&action=&tran=undefined"
|
32
|
+
@path, @query = @uri.split('?',2)
|
33
|
+
@req_parameters = [
|
34
|
+
["v", "3"],
|
35
|
+
["s", "webhp"],
|
36
|
+
["action", ""],
|
37
|
+
["tran", "undefined"]
|
38
|
+
]
|
39
|
+
@version = "HTTP/1.1"
|
40
|
+
|
41
|
+
@headers = [
|
42
|
+
["Host", "www.google.com"],
|
43
|
+
["User-Agent", "Mozilla/5.0"],
|
44
|
+
["Accept", "image/png,image/*;q=0.8,*/*;q=0.5"],
|
45
|
+
["Accept-Language", "en-us,en;q=0.5"],
|
46
|
+
["Accept-Encoding", "gzip,deflate"],
|
47
|
+
["Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7"],
|
48
|
+
["Keep-Alive", "300"],
|
49
|
+
["Proxy-Connection", "keep-alive"],
|
50
|
+
["Referer", "http://www.google.com/"],
|
51
|
+
["Cookie", "PREFID=NNNN:LM=1237996892:S=YYYYY; NID=111"],
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
def do_type_tests(req)
|
56
|
+
assert_kind_of Request, req
|
57
|
+
assert_kind_of Headers, req.headers
|
58
|
+
assert_kind_of Body, req.body
|
59
|
+
assert_kind_of RequestAction, req.action
|
60
|
+
assert_kind_of RequestHeaders, req.headers
|
61
|
+
end
|
62
|
+
|
63
|
+
def do_capture_value_tests(req)
|
64
|
+
assert_equal @headers, req.headers
|
65
|
+
assert_equal @body, req.body.to_s
|
66
|
+
assert_equal @uri, req.action.uri.to_s
|
67
|
+
assert_equal @path, req.action.uri.path
|
68
|
+
assert_equal @query, req.action.uri.query
|
69
|
+
assert_equal @verb, req.action.verb
|
70
|
+
assert_equal @version, req.action.version
|
71
|
+
assert_equal @req_parameters, req.action_parameters
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_capture_crlf_headers
|
75
|
+
req = @obj.capture(@rawdat_crlf)
|
76
|
+
do_capture_value_tests(req)
|
77
|
+
do_type_tests(req)
|
78
|
+
assert_equal @rawdat_crlf, req.to_raw
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_captured_body_type
|
82
|
+
@obj.capture(@rawdat)
|
83
|
+
assert_kind_of Body, @obj.body
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
class TestHttpPostRequest < TestHttpRequest
|
90
|
+
|
91
|
+
def setup
|
92
|
+
@obj_klass = Request
|
93
|
+
@obj = @obj_klass.new
|
94
|
+
|
95
|
+
@rawdat =<<_EOF_
|
96
|
+
POST /path/script.cgi?qtype=foo HTTP/1.0
|
97
|
+
From: frog@jmarshall.com
|
98
|
+
HasColon: this_has_a_colon:yikes
|
99
|
+
User-Agent: HTTPTool/1.0
|
100
|
+
Content-Type: application/x-www-form-urlencoded
|
101
|
+
Content-Length: 32
|
102
|
+
|
103
|
+
home=Cosby&favorite+flavor=flies
|
104
|
+
_EOF_
|
105
|
+
@rawdat.chomp!
|
106
|
+
|
107
|
+
@hstr, @body = @rawdat.split(/^\n/, 2)
|
108
|
+
@rawdat_crlf = @hstr.gsub("\n", "\r\n") + "\r\n" + @body
|
109
|
+
|
110
|
+
@verb = "POST"
|
111
|
+
@uri = "/path/script.cgi?qtype=foo"
|
112
|
+
@path, @query = @uri.split('?',2)
|
113
|
+
@req_parameters = [
|
114
|
+
["qtype", "foo"],
|
115
|
+
]
|
116
|
+
@version = "HTTP/1.0"
|
117
|
+
|
118
|
+
@headers = [
|
119
|
+
["From", "frog@jmarshall.com"],
|
120
|
+
["HasColon", "this_has_a_colon:yikes"],
|
121
|
+
["User-Agent", "HTTPTool/1.0"],
|
122
|
+
["Content-Type", "application/x-www-form-urlencoded"],
|
123
|
+
["Content-Length", "32"],
|
124
|
+
]
|
125
|
+
|
126
|
+
@post_parameters = [["home", "Cosby"], ["favorite+flavor", "flies"]]
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_captured_body_type
|
130
|
+
@obj.capture(@rawdat)
|
131
|
+
assert_kind_of BoundBody, @obj.body
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
end
|
136
|
+
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_http_helper.rb'
|
2
|
+
|
3
|
+
class TestHttpResponse < Test::Unit::TestCase
|
4
|
+
include HttpTestHelper::CommonInterfaceTests
|
5
|
+
|
6
|
+
include Rbkb::Http
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@obj_klass = Response
|
10
|
+
@obj_opts = nil
|
11
|
+
@obj = @obj_klass.new(nil, @obj_opts)
|
12
|
+
|
13
|
+
@rawdat =<<_EOF_
|
14
|
+
HTTP/1.0 404 Not Found
|
15
|
+
Date: Thu, 26 Mar 2009 01:18:52 GMT
|
16
|
+
Server: Apache
|
17
|
+
Content-Type: text/html; charset=iso-8859-1
|
18
|
+
Content-Length: 190
|
19
|
+
Connection: Keep-Alive
|
20
|
+
|
21
|
+
<html><head>
|
22
|
+
<title>Error report</title></head>
|
23
|
+
<body><h1>HTTP Status 404</h1><HR size="1" noshade><p><u>The requested resource is not available.</u></p><HR size="1" noshade>
|
24
|
+
</body></html>
|
25
|
+
_EOF_
|
26
|
+
|
27
|
+
@hstr, @body = @rawdat.split(/^\n/, 2)
|
28
|
+
@rawdat_crlf = @hstr.gsub("\n", "\r\n") + "\r\n" + @body
|
29
|
+
|
30
|
+
@code = 404
|
31
|
+
@text = "Not Found"
|
32
|
+
@version = "HTTP/1.0"
|
33
|
+
|
34
|
+
@headers = [
|
35
|
+
["Date", "Thu, 26 Mar 2009 01:18:52 GMT"],
|
36
|
+
["Server", "Apache"],
|
37
|
+
["Content-Type", "text/html; charset=iso-8859-1"],
|
38
|
+
["Content-Length", "190"],
|
39
|
+
["Connection", "Keep-Alive"]
|
40
|
+
]
|
41
|
+
|
42
|
+
@content_length = 190
|
43
|
+
end
|
44
|
+
|
45
|
+
def do_type_tests(rsp)
|
46
|
+
assert_kind_of Response, rsp
|
47
|
+
assert_kind_of Headers, rsp.headers
|
48
|
+
assert_kind_of Body, rsp.body
|
49
|
+
assert_kind_of ResponseStatus, rsp.status
|
50
|
+
assert_kind_of ResponseHeaders, rsp.headers
|
51
|
+
end
|
52
|
+
|
53
|
+
def do_capture_value_tests(rsp)
|
54
|
+
assert_equal @headers, rsp.headers
|
55
|
+
assert_equal @body, rsp.body
|
56
|
+
assert_equal @code, rsp.status.code
|
57
|
+
assert_equal @text, rsp.status.text
|
58
|
+
assert_equal @version, rsp.status.version
|
59
|
+
assert_equal @content_length, rsp.content_length
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_capture_crlf_headers
|
63
|
+
@obj.capture(@rawdat_crlf)
|
64
|
+
do_capture_value_tests(@obj)
|
65
|
+
do_type_tests(@obj)
|
66
|
+
assert_equal @rawdat_crlf, @obj.to_raw
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_captured_body_type
|
70
|
+
@obj.capture(@rawdat)
|
71
|
+
assert_kind_of BoundBody, @obj.body
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
class TestHttpResponseChunked < TestHttpResponse
|
77
|
+
include Rbkb::Http
|
78
|
+
|
79
|
+
def setup
|
80
|
+
@obj_klass = Response
|
81
|
+
@obj_opts = {}
|
82
|
+
@obj = @obj_klass.new
|
83
|
+
|
84
|
+
@rawdat =<<_EOF_
|
85
|
+
HTTP/1.1 200 OK
|
86
|
+
Date: Thu, 26 Mar 2009 01:18:52 GMT
|
87
|
+
Server: Apache
|
88
|
+
Content-Type: text/html; charset=iso-8859-1
|
89
|
+
Transfer-Encoding: chunked
|
90
|
+
Connection: Keep-Alive
|
91
|
+
|
92
|
+
20
|
93
|
+
This is a test of a chunked-enco
|
94
|
+
|
95
|
+
10
|
96
|
+
ded HTTP request
|
97
|
+
|
98
|
+
0
|
99
|
+
_EOF_
|
100
|
+
|
101
|
+
@hstr, @rawbody = @rawdat.split(/^\n/, 2)
|
102
|
+
@rawdat_crlf = @rawdat.gsub("\n", "\r\n")
|
103
|
+
@hdrs_crlf = @hstr.gsub("\n", "\r\n")
|
104
|
+
|
105
|
+
@body = "This is a test of a chunked-encoded HTTP request"
|
106
|
+
|
107
|
+
@code = 200
|
108
|
+
@text = "OK"
|
109
|
+
@version = "HTTP/1.1"
|
110
|
+
|
111
|
+
@headers = [
|
112
|
+
["Date", "Thu, 26 Mar 2009 01:18:52 GMT"],
|
113
|
+
["Server", "Apache"],
|
114
|
+
["Content-Type", "text/html; charset=iso-8859-1"],
|
115
|
+
["Transfer-Encoding", "chunked"],
|
116
|
+
["Connection", "Keep-Alive"]
|
117
|
+
]
|
118
|
+
|
119
|
+
@content_length = nil
|
120
|
+
@tc_chunk_size = 0x20
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_captured_body_type
|
124
|
+
@obj.capture(@rawdat)
|
125
|
+
assert_kind_of ChunkedBody, @obj.body
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_back_to_raw
|
129
|
+
@obj.capture(@rawdat)
|
130
|
+
do_capture_value_tests(@obj)
|
131
|
+
do_type_tests(@obj)
|
132
|
+
@obj.body.opts[:output_chunk_size] = @tc_chunk_size
|
133
|
+
assert_equal @rawdat_crlf, @obj.to_raw
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_capture_crlf_headers
|
137
|
+
@obj.capture(@rawdat_crlf)
|
138
|
+
do_capture_value_tests(@obj)
|
139
|
+
do_type_tests(@obj)
|
140
|
+
@obj.body.opts[:output_chunk_size] = @tc_chunk_size
|
141
|
+
assert_equal @rawdat_crlf, @obj.to_raw
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_default_chunk_size
|
145
|
+
if @body.size > ChunkedBody::DEFAULT_CHUNK_SIZE
|
146
|
+
assert "TESTCASE ERROR!!!", "make the setup() @body < DEFAULT_CHUNK_SIZE"
|
147
|
+
end
|
148
|
+
raw_tc = "#{@hdrs_crlf}\r\n#{@body.size.to_s(16)}\r\n#{@body}\r\n\r\n0\r\n"
|
149
|
+
@obj.capture(@rawdat_crlf)
|
150
|
+
do_capture_value_tests(@obj)
|
151
|
+
do_type_tests(@obj)
|
152
|
+
assert_equal raw_tc, @obj.to_raw
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# This test-case simulates a HTTP response to a HEAD request. This type of
|
157
|
+
# response is special since it returns Content-Length: NNN or
|
158
|
+
# Transfer-Encoding: chunked headers without any actual body data.
|
159
|
+
# To handle this special situation, we use the 'ignore_content_length' and
|
160
|
+
# 'ignore_chunked_encoding' options.
|
161
|
+
class TestHttpResponseToHead < TestHttpResponse
|
162
|
+
def setup
|
163
|
+
@obj_klass = Response
|
164
|
+
|
165
|
+
# Technically, a server should only respond to HEAD with one of
|
166
|
+
# content length *or* chunked encoding. However, we ignore them both.
|
167
|
+
@obj_opts = {
|
168
|
+
:ignore_content_length => true,
|
169
|
+
:ignore_chunked_encoding => true
|
170
|
+
}
|
171
|
+
@obj = @obj_klass.new(nil, @obj_opts)
|
172
|
+
|
173
|
+
# Note, our test-case includes both content length and chunked encoding.
|
174
|
+
# A real server probably wouldn't do this, but we want to make sure
|
175
|
+
# we handle both.
|
176
|
+
@rawdat =<<_EOF_
|
177
|
+
HTTP/1.1 200 OK
|
178
|
+
Cache-Control: private, max-age=0
|
179
|
+
Date: Fri, 27 Mar 2009 04:27:27 GMT
|
180
|
+
Expires: -1
|
181
|
+
Content-Length: 9140
|
182
|
+
Content-Type: text/html; charset=ISO-8859-1
|
183
|
+
Server: Booble
|
184
|
+
Transfer-Encoding: chunked
|
185
|
+
|
186
|
+
_EOF_
|
187
|
+
|
188
|
+
@hstr, @body = @rawdat.split(/^\n/, 2)
|
189
|
+
@rawdat_crlf = @hstr.gsub("\n", "\r\n") + "\r\n" + @body
|
190
|
+
|
191
|
+
@code = 200
|
192
|
+
@text = "OK"
|
193
|
+
@version = "HTTP/1.1"
|
194
|
+
|
195
|
+
@headers = [
|
196
|
+
["Cache-Control", "private, max-age=0"],
|
197
|
+
["Date", "Fri, 27 Mar 2009 04:27:27 GMT"],
|
198
|
+
["Expires", "-1"],
|
199
|
+
["Content-Length", "9140"],
|
200
|
+
["Content-Type", "text/html; charset=ISO-8859-1"],
|
201
|
+
["Server", "Booble"],
|
202
|
+
["Transfer-Encoding", "chunked"]
|
203
|
+
]
|
204
|
+
|
205
|
+
# Content length should get ignored
|
206
|
+
@content_length = nil
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_capture_crlf_headers
|
210
|
+
@obj.capture(@rawdat_crlf)
|
211
|
+
do_capture_value_tests(@obj)
|
212
|
+
do_type_tests(@obj)
|
213
|
+
assert_equal @rawdat_crlf, @obj.to_raw
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_captured_body_type
|
217
|
+
@obj.capture(@rawdat)
|
218
|
+
assert_kind_of Body, @obj.body
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
|