ht2p 0.0.6 → 0.0.7
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/LICENSE +1 -1
- data/README.rdoc +1 -1
- data/VERSION +1 -1
- data/ht2p.gemspec +2 -2
- data/lib/ht2p/client.rb +13 -25
- data/lib/ht2p/client/request.rb +12 -11
- data/lib/ht2p/client/response.rb +16 -10
- data/lib/ht2p/header.rb +10 -6
- data/spec/ht2p_spec.rb +29 -20
- metadata +2 -2
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.7
|
data/ht2p.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ht2p}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jun Kikuchi"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-01-16}
|
13
13
|
s.description = %q{ht2p}
|
14
14
|
s.email = %q{kikuchi@bonnou.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/ht2p/client.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'socket'
|
3
3
|
require 'openssl'
|
4
|
+
require 'forwardable'
|
4
5
|
|
5
6
|
class HT2P::Client
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@socket, :write, :read, :gets, :flush
|
9
|
+
|
6
10
|
attr_reader :uri, :request
|
7
11
|
|
8
12
|
def initialize(uri, params={}, &block)
|
@@ -13,8 +17,16 @@ class HT2P::Client
|
|
13
17
|
|
14
18
|
TCPSocket.open(ip, @uri.port) do |socket|
|
15
19
|
if @uri.scheme == 'https'
|
20
|
+
context = OpenSSL::SSL::SSLContext.new
|
21
|
+
context.ca_file = params[:ca_file]
|
22
|
+
context.ca_path = params[:ca_path] || OpenSSL::X509::DEFAULT_CERT_DIR
|
23
|
+
context.timeout = params[:timeout]
|
24
|
+
context.verify_depth = params[:verify_depth]
|
25
|
+
context.verify_mode = OpenSSL::SSL.const_get\
|
26
|
+
"VERIFY_#{(params[:verify_mode] || 'PEER').to_s.upcase}"
|
27
|
+
|
16
28
|
begin
|
17
|
-
@socket = OpenSSL::SSL::SSLSocket.new(socket)
|
29
|
+
@socket = OpenSSL::SSL::SSLSocket.new(socket, context)
|
18
30
|
@socket.connect
|
19
31
|
@request = HT2P::Client::Request.new(self, params)
|
20
32
|
block.call @request
|
@@ -29,30 +41,6 @@ class HT2P::Client
|
|
29
41
|
end
|
30
42
|
end
|
31
43
|
|
32
|
-
def request_header(method, header)
|
33
|
-
@socket.write header.format(method, @uri)
|
34
|
-
end
|
35
|
-
|
36
|
-
def response_header
|
37
|
-
HT2P::Header.load @socket
|
38
|
-
end
|
39
|
-
|
40
|
-
def write(val)
|
41
|
-
@socket.write val.to_s
|
42
|
-
end
|
43
|
-
|
44
|
-
def read(length=nil)
|
45
|
-
@socket.read length
|
46
|
-
end
|
47
|
-
|
48
|
-
def gets
|
49
|
-
@socket.gets
|
50
|
-
end
|
51
|
-
|
52
|
-
def flush
|
53
|
-
@socket.flush
|
54
|
-
end
|
55
|
-
|
56
44
|
autoload :Request, 'ht2p/client/request'
|
57
45
|
autoload :Response, 'ht2p/client/response'
|
58
46
|
end
|
data/lib/ht2p/client/request.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
class HT2P::Client::Request
|
2
|
-
|
2
|
+
extend Forwardable
|
3
|
+
def_delegators :@client, :uri, :write
|
4
|
+
def_delegators :@header, :[], :[]=
|
5
|
+
|
6
|
+
attr_accessor :method, :header
|
3
7
|
|
4
|
-
|
8
|
+
alias :headers :header
|
5
9
|
|
6
10
|
def initialize(client, params)
|
7
11
|
@client = client
|
@@ -11,18 +15,15 @@ class HT2P::Client::Request
|
|
11
15
|
|
12
16
|
def send(body=nil, &block)
|
13
17
|
@header['content-length'] = body.to_s.size if body
|
14
|
-
@client.
|
15
|
-
@client.write
|
16
|
-
block.call
|
18
|
+
@client.write @header.format(@method, @client.uri)
|
19
|
+
@client.write body if body
|
20
|
+
block.call self if block_given?
|
17
21
|
@client.flush
|
18
|
-
HT2P::Client::Response.new
|
22
|
+
HT2P::Client::Response.new @client
|
19
23
|
end
|
20
24
|
|
25
|
+
METHODS = %w'get head post put delete options trace connect'
|
21
26
|
METHODS.each do |val|
|
22
|
-
define_method
|
23
|
-
end
|
24
|
-
|
25
|
-
def write(val)
|
26
|
-
@client.write(val)
|
27
|
+
define_method val, instance_method(:send)
|
27
28
|
end
|
28
29
|
end
|
data/lib/ht2p/client/response.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
class HT2P::Client::Response
|
2
|
+
extend Forwardable
|
3
|
+
def_delegators :@header, :[], :[]=
|
4
|
+
|
2
5
|
attr_reader :code, :header
|
3
6
|
|
7
|
+
alias :headers :header
|
8
|
+
|
4
9
|
HAS_BODY = [:get, :post, :put, :delete, :trace]
|
5
10
|
|
6
11
|
def initialize(client)
|
7
|
-
@client, @code, @header = client, *client
|
12
|
+
@client, @code, @header = client, *HT2P::Header.load(client)
|
8
13
|
|
9
14
|
@body = if HAS_BODY.include? @client.request.method.to_s.downcase.to_sym
|
10
15
|
if @header['transfer-encoding'].to_s.downcase == 'chunked'
|
11
|
-
Chunked.new
|
16
|
+
Chunked.new @client
|
12
17
|
else
|
13
|
-
Transfer.new
|
18
|
+
Transfer.new @client, @header['content-length'].to_i
|
14
19
|
end
|
15
20
|
else
|
16
21
|
Empty.new
|
@@ -19,14 +24,14 @@ class HT2P::Client::Response
|
|
19
24
|
|
20
25
|
def receive(&block)
|
21
26
|
if block_given?
|
22
|
-
block.call
|
27
|
+
block.call self
|
23
28
|
else
|
24
29
|
read
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
28
33
|
def read(length=nil)
|
29
|
-
@body.read
|
34
|
+
@body.read length
|
30
35
|
end
|
31
36
|
|
32
37
|
class Transfer
|
@@ -36,13 +41,13 @@ class HT2P::Client::Response
|
|
36
41
|
|
37
42
|
def read(length=nil)
|
38
43
|
if @size.nil?
|
39
|
-
@client.read
|
44
|
+
@client.read length
|
40
45
|
elsif @size > 0
|
41
46
|
length ||= @size
|
42
47
|
length = @size if @size < length
|
43
48
|
@size -= length
|
44
49
|
|
45
|
-
@client.read
|
50
|
+
@client.read length
|
46
51
|
else
|
47
52
|
nil
|
48
53
|
end
|
@@ -51,18 +56,19 @@ class HT2P::Client::Response
|
|
51
56
|
|
52
57
|
class Chunked < Transfer
|
53
58
|
def initialize(client)
|
54
|
-
super
|
59
|
+
super client, nil
|
55
60
|
parse_size
|
56
61
|
end
|
57
62
|
|
58
63
|
def read(length=nil)
|
59
|
-
parse_size
|
60
|
-
super
|
64
|
+
parse_size if @size <= 0
|
65
|
+
super length
|
61
66
|
end
|
62
67
|
|
63
68
|
def parse_size
|
64
69
|
@size = @client.gets.chop!.hex
|
65
70
|
end
|
71
|
+
private :parse_size
|
66
72
|
end
|
67
73
|
|
68
74
|
class Empty
|
data/lib/ht2p/header.rb
CHANGED
@@ -12,24 +12,28 @@ class HT2P::Header < Hash
|
|
12
12
|
code = md[1].to_i
|
13
13
|
elsif md = /(.+?):\s*(.*)/.match(line)
|
14
14
|
key, val = md[1].downcase, md[2]
|
15
|
-
header
|
15
|
+
if header.key? key
|
16
|
+
header.add key, val
|
17
|
+
else
|
18
|
+
header[key] = val
|
19
|
+
end
|
16
20
|
elsif md = /\s+(.*)/.match(line)
|
17
|
-
header.append
|
21
|
+
header.append key, md[1]
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
21
25
|
[code, header]
|
22
26
|
end
|
23
27
|
|
24
|
-
def
|
25
|
-
if
|
28
|
+
def add(key, val)
|
29
|
+
if key? key
|
26
30
|
if self[key].is_a? Array
|
27
31
|
self[key] << val
|
28
32
|
else
|
29
|
-
|
33
|
+
self[key] = [self[key], val]
|
30
34
|
end
|
31
35
|
else
|
32
|
-
|
36
|
+
self[key] = [val]
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
data/spec/ht2p_spec.rb
CHANGED
@@ -42,29 +42,16 @@ describe HT2P::Header do
|
|
42
42
|
@header = HT2P::Header.new
|
43
43
|
end
|
44
44
|
|
45
|
-
it '
|
45
|
+
it '見た目は Hash として動作' do
|
46
46
|
@header['a'] = 'A'
|
47
47
|
@header['a'].should == 'A'
|
48
|
-
end
|
49
48
|
|
50
|
-
|
51
|
-
@header['a'] = 'A'
|
49
|
+
@header['a'] = 'a'
|
52
50
|
@header['a'] = 'A'
|
53
|
-
@header['a'].should ==
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'should perform `append` to append the value' do
|
57
|
-
@header['a'] = 'A'
|
58
|
-
@header.append('a', 'A')
|
59
|
-
@header['a'].should == 'AA'
|
60
|
-
|
61
|
-
@header['b'] = 'B'
|
62
|
-
@header['b'] = 'B'
|
63
|
-
@header.append('b', 'B')
|
64
|
-
@header['b'].should == ['B', 'BB']
|
51
|
+
@header['a'].should == 'A'
|
65
52
|
end
|
66
53
|
|
67
|
-
it '
|
54
|
+
it 'class メソッドの load は HTTP ヘッダーを読み込む' do
|
68
55
|
s =<<END
|
69
56
|
HTTP/1.1 100 continue
|
70
57
|
HTTP/1.1 200 ok
|
@@ -85,7 +72,7 @@ END
|
|
85
72
|
header['d'].should == ['D', 'DD']
|
86
73
|
end
|
87
74
|
|
88
|
-
it '
|
75
|
+
it 'format メソッドは HTTP ヘッダー文字列を返す' do
|
89
76
|
uri = URI.parse('http://example.com/')
|
90
77
|
s =<<END
|
91
78
|
GET / HTTP/1.1
|
@@ -101,6 +88,17 @@ GET / HTTP/1.1
|
|
101
88
|
Host: example.com
|
102
89
|
a: A
|
103
90
|
|
91
|
+
END
|
92
|
+
@header.format(:get, uri).should == s.gsub("\n", "\r\n")
|
93
|
+
|
94
|
+
@header['b'] = 'b'
|
95
|
+
uri = URI.parse('http://example.com/')
|
96
|
+
s =<<END
|
97
|
+
GET / HTTP/1.1
|
98
|
+
Host: example.com
|
99
|
+
a: A
|
100
|
+
b: b
|
101
|
+
|
104
102
|
END
|
105
103
|
@header.format(:get, uri).should == s.gsub("\n", "\r\n")
|
106
104
|
|
@@ -115,14 +113,25 @@ b: B
|
|
115
113
|
END
|
116
114
|
@header.format(:get, uri).should == s.gsub("\n", "\r\n")
|
117
115
|
|
118
|
-
@header
|
116
|
+
@header.add('b', 'B')
|
119
117
|
uri = URI.parse('http://example.com/')
|
120
118
|
s =<<END
|
121
119
|
GET / HTTP/1.1
|
122
120
|
Host: example.com
|
123
121
|
a: A
|
124
122
|
b: B
|
125
|
-
b:
|
123
|
+
b: B
|
124
|
+
|
125
|
+
END
|
126
|
+
@header.format(:get, uri).should == s.gsub("\n", "\r\n")
|
127
|
+
|
128
|
+
@header['b'] = 'b'
|
129
|
+
uri = URI.parse('http://example.com/')
|
130
|
+
s =<<END
|
131
|
+
GET / HTTP/1.1
|
132
|
+
Host: example.com
|
133
|
+
a: A
|
134
|
+
b: b
|
126
135
|
|
127
136
|
END
|
128
137
|
@header.format(:get, uri).should == s.gsub("\n", "\r\n")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ht2p
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jun Kikuchi
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-16 00:00:00 +09:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|