astro-em-http-request 0.1.6 → 0.1.12
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +5 -3
- data/Rakefile +4 -0
- data/em-http-request.gemspec +7 -5
- data/ext/http11_client/http11_parser.c +140 -125
- data/ext/http11_client/http11_parser.rl +2 -5
- data/lib/em-http/client.rb +103 -31
- data/lib/em-http/decoders.rb +1 -2
- data/lib/em-http/request.rb +16 -4
- data/test/stallion.rb +19 -2
- data/test/stub_server.rb +22 -0
- data/test/{hash.rb → test_hash.rb} +6 -4
- data/test/test_multi.rb +1 -6
- data/test/test_request.rb +115 -15
- metadata +21 -7
data/README.rdoc
CHANGED
@@ -6,6 +6,9 @@ EventMachine based HTTP Request interface. Supports streaming response processin
|
|
6
6
|
- Basic-Auth support
|
7
7
|
- Custom timeouts
|
8
8
|
|
9
|
+
Screencast / Demo of using EM-HTTP-Request:
|
10
|
+
- http://everburning.com/news/eventmachine-screencast-em-http-request/
|
11
|
+
|
9
12
|
== Simple client example
|
10
13
|
|
11
14
|
EventMachine.run {
|
@@ -61,9 +64,8 @@ EventMachine based HTTP Request interface. Supports streaming response processin
|
|
61
64
|
|
62
65
|
== Streaming body processing
|
63
66
|
EventMachine.run {
|
64
|
-
|
65
|
-
|
66
|
-
http = EventMachine::HttpRequest.new('http://www.website.com/').get :on_response => on_body
|
67
|
+
http = EventMachine::HttpRequest.new('http://www.website.com/').get
|
68
|
+
http.stream { |chunk| print chunk }
|
67
69
|
|
68
70
|
# ...
|
69
71
|
}
|
data/Rakefile
CHANGED
data/em-http-request.gemspec
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
spec = Gem::Specification.new do |s|
|
2
2
|
s.name = 'em-http-request'
|
3
|
-
s.version = '0.1.
|
4
|
-
s.date = '2009-
|
3
|
+
s.version = '0.1.9'
|
4
|
+
s.date = '2009-10-17'
|
5
5
|
s.summary = 'EventMachine based HTTP Request interface'
|
6
6
|
s.description = s.summary
|
7
7
|
s.email = 'ilya@igvita.com'
|
8
8
|
s.homepage = "http://github.com/igrigorik/em-http-request"
|
9
9
|
s.has_rdoc = true
|
10
10
|
s.authors = ["Ilya Grigorik"]
|
11
|
-
s.add_dependency('eventmachine', '>= 0.12.
|
11
|
+
s.add_dependency('eventmachine', '>= 0.12.9')
|
12
|
+
s.add_dependency('addressable', '>= 2.0.0')
|
12
13
|
s.extensions = ["ext/buffer/extconf.rb" , "ext/http11_client/extconf.rb"]
|
13
14
|
s.rubyforge_project = "em-http-request"
|
14
|
-
|
15
|
+
|
15
16
|
# ruby -rpp -e' pp `git ls-files`.split("\n") '
|
16
17
|
s.files = [
|
17
18
|
".autotest",
|
@@ -34,9 +35,10 @@ spec = Gem::Specification.new do |s|
|
|
34
35
|
"lib/em-http/decoders.rb",
|
35
36
|
"lib/em-http/multi.rb",
|
36
37
|
"lib/em-http/request.rb",
|
37
|
-
"test/
|
38
|
+
"test/test_hash.rb",
|
38
39
|
"test/helper.rb",
|
39
40
|
"test/stallion.rb",
|
41
|
+
"test/stub_server.rb",
|
40
42
|
"test/test_multi.rb",
|
41
43
|
"test/test_request.rb"]
|
42
44
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
#line 1 "http11_parser.rl"
|
2
3
|
/**
|
3
4
|
* Copyright (c) 2005 Zed A. Shaw
|
@@ -18,166 +19,183 @@
|
|
18
19
|
|
19
20
|
|
20
21
|
/** machine **/
|
22
|
+
|
21
23
|
#line 95 "http11_parser.rl"
|
22
24
|
|
23
25
|
|
24
26
|
/** Data **/
|
25
27
|
|
26
|
-
#line
|
28
|
+
#line 29 "http11_parser.c"
|
27
29
|
static const char _httpclient_parser_actions[] = {
|
28
30
|
0, 1, 0, 1, 1, 1, 2, 1,
|
29
31
|
3, 1, 4, 1, 5, 1, 7, 1,
|
30
|
-
8, 1, 10, 2,
|
31
|
-
|
32
|
-
|
32
|
+
8, 1, 10, 2, 0, 5, 2, 2,
|
33
|
+
3, 2, 3, 4, 2, 4, 10, 2,
|
34
|
+
6, 0, 2, 8, 10, 2, 9, 10,
|
35
|
+
2, 10, 9, 3, 2, 3, 4, 3,
|
36
|
+
4, 9, 10, 3, 4, 10, 9, 3,
|
37
|
+
6, 0, 5, 3, 8, 10, 9, 4,
|
38
|
+
2, 3, 4, 10, 5, 2, 3, 4,
|
39
|
+
9, 10, 5, 2, 3, 4, 10, 9
|
40
|
+
|
33
41
|
};
|
34
42
|
|
35
43
|
static const short _httpclient_parser_key_offsets[] = {
|
36
|
-
0,
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
44
|
+
0, 0, 11, 12, 24, 29, 30, 31,
|
45
|
+
43, 58, 80, 95, 116, 131, 153, 168,
|
46
|
+
189, 204, 223, 238, 256, 257, 258, 259,
|
47
|
+
260, 262, 265, 267, 270, 272, 274, 276,
|
48
|
+
279, 281, 298, 314, 317, 319, 320, 322
|
41
49
|
};
|
42
50
|
|
43
51
|
static const char _httpclient_parser_trans_keys[] = {
|
44
|
-
13, 48, 59, 72, 49, 57, 65,
|
45
|
-
97, 102, 10, 13, 32, 59,
|
46
|
-
48, 57, 65, 70, 97, 102,
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
48, 57, 65, 90, 94, 122, 13, 32,
|
51
|
-
33, 59, 61, 124, 126, 9, 12, 35,
|
52
|
-
39, 42, 43, 45, 46, 48, 57, 65,
|
53
|
-
90, 94, 122, 33, 124, 126, 35, 39,
|
54
|
-
42, 43, 45, 46, 48, 57, 65, 90,
|
55
|
-
94, 122, 13, 32, 33, 59, 124, 126,
|
56
|
-
9, 12, 35, 39, 42, 43, 45, 46,
|
57
|
-
48, 57, 65, 90, 94, 122, 33, 124,
|
58
|
-
126, 35, 39, 42, 43, 45, 46, 48,
|
59
|
-
57, 65, 90, 94, 122, 13, 32, 33,
|
60
|
-
59, 61, 124, 126, 9, 12, 35, 39,
|
52
|
+
10, 13, 48, 59, 72, 49, 57, 65,
|
53
|
+
70, 97, 102, 10, 10, 13, 32, 59,
|
54
|
+
9, 12, 48, 57, 65, 70, 97, 102,
|
55
|
+
10, 13, 32, 9, 12, 10, 10, 10,
|
56
|
+
13, 32, 59, 9, 12, 48, 57, 65,
|
57
|
+
70, 97, 102, 33, 124, 126, 35, 39,
|
61
58
|
42, 43, 45, 46, 48, 57, 65, 90,
|
62
|
-
94, 122,
|
59
|
+
94, 122, 10, 13, 32, 33, 59, 61,
|
60
|
+
124, 126, 9, 12, 35, 39, 42, 43,
|
61
|
+
45, 46, 48, 57, 65, 90, 94, 122,
|
62
|
+
33, 124, 126, 35, 39, 42, 43, 45,
|
63
|
+
46, 48, 57, 65, 90, 94, 122, 10,
|
64
|
+
13, 32, 33, 59, 124, 126, 9, 12,
|
65
|
+
35, 39, 42, 43, 45, 46, 48, 57,
|
66
|
+
65, 90, 94, 122, 33, 124, 126, 35,
|
67
|
+
39, 42, 43, 45, 46, 48, 57, 65,
|
68
|
+
90, 94, 122, 10, 13, 32, 33, 59,
|
69
|
+
61, 124, 126, 9, 12, 35, 39, 42,
|
63
70
|
43, 45, 46, 48, 57, 65, 90, 94,
|
64
|
-
122,
|
71
|
+
122, 33, 124, 126, 35, 39, 42, 43,
|
72
|
+
45, 46, 48, 57, 65, 90, 94, 122,
|
73
|
+
10, 13, 32, 33, 59, 124, 126, 9,
|
65
74
|
12, 35, 39, 42, 43, 45, 46, 48,
|
66
75
|
57, 65, 90, 94, 122, 33, 124, 126,
|
67
76
|
35, 39, 42, 43, 45, 46, 48, 57,
|
68
|
-
65, 90, 94, 122, 13, 33, 59,
|
69
|
-
124, 126, 35, 39, 42, 43, 45,
|
70
|
-
48, 57, 65, 90, 94, 122, 33,
|
71
|
-
126, 35, 39, 42, 43, 45, 46, 48,
|
72
|
-
57, 65, 90, 94, 122, 13, 33, 59,
|
73
|
-
124, 126, 35, 39, 42, 43, 45, 46,
|
74
|
-
48, 57, 65, 90, 94, 122, 84, 84,
|
75
|
-
80, 47, 48, 57, 46, 48, 57, 48,
|
76
|
-
57, 32, 48, 57, 48, 57, 48, 57,
|
77
|
-
48, 57, 13, 32, 13, 10, 13, 33,
|
78
|
-
124, 126, 35, 39, 42, 43, 45, 46,
|
79
|
-
48, 57, 65, 90, 94, 122, 33, 58,
|
77
|
+
65, 90, 94, 122, 10, 13, 33, 59,
|
78
|
+
61, 124, 126, 35, 39, 42, 43, 45,
|
79
|
+
46, 48, 57, 65, 90, 94, 122, 33,
|
80
80
|
124, 126, 35, 39, 42, 43, 45, 46,
|
81
|
-
48, 57, 65, 90, 94, 122,
|
82
|
-
|
81
|
+
48, 57, 65, 90, 94, 122, 10, 13,
|
82
|
+
33, 59, 124, 126, 35, 39, 42, 43,
|
83
|
+
45, 46, 48, 57, 65, 90, 94, 122,
|
84
|
+
84, 84, 80, 47, 48, 57, 46, 48,
|
85
|
+
57, 48, 57, 32, 48, 57, 48, 57,
|
86
|
+
48, 57, 48, 57, 10, 13, 32, 10,
|
87
|
+
13, 10, 13, 33, 124, 126, 35, 39,
|
88
|
+
42, 43, 45, 46, 48, 57, 65, 90,
|
89
|
+
94, 122, 33, 58, 124, 126, 35, 39,
|
90
|
+
42, 43, 45, 46, 48, 57, 65, 90,
|
91
|
+
94, 122, 10, 13, 32, 10, 13, 10,
|
92
|
+
10, 13, 0
|
83
93
|
};
|
84
94
|
|
85
95
|
static const char _httpclient_parser_single_lengths[] = {
|
86
|
-
|
87
|
-
3,
|
88
|
-
3,
|
89
|
-
0, 1, 0, 1, 0, 0, 0,
|
90
|
-
|
96
|
+
0, 5, 1, 4, 3, 1, 1, 4,
|
97
|
+
3, 8, 3, 7, 3, 8, 3, 7,
|
98
|
+
3, 7, 3, 6, 1, 1, 1, 1,
|
99
|
+
0, 1, 0, 1, 0, 0, 0, 3,
|
100
|
+
2, 5, 4, 3, 2, 1, 2, 0
|
91
101
|
};
|
92
102
|
|
93
103
|
static const char _httpclient_parser_range_lengths[] = {
|
94
|
-
|
104
|
+
0, 3, 0, 4, 1, 0, 0, 4,
|
95
105
|
6, 7, 6, 7, 6, 7, 6, 7,
|
96
106
|
6, 6, 6, 6, 0, 0, 0, 0,
|
97
107
|
1, 1, 1, 1, 1, 1, 1, 0,
|
98
|
-
0,
|
108
|
+
0, 6, 6, 0, 0, 0, 0, 0
|
99
109
|
};
|
100
110
|
|
101
|
-
static const
|
102
|
-
0,
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
111
|
+
static const short _httpclient_parser_index_offsets[] = {
|
112
|
+
0, 0, 9, 11, 20, 25, 27, 29,
|
113
|
+
38, 48, 64, 74, 89, 99, 115, 125,
|
114
|
+
140, 150, 164, 174, 187, 189, 191, 193,
|
115
|
+
195, 197, 200, 202, 205, 207, 209, 211,
|
116
|
+
215, 218, 230, 241, 245, 248, 250, 253
|
107
117
|
};
|
108
118
|
|
109
119
|
static const char _httpclient_parser_indicies[] = {
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
120
|
+
0, 2, 3, 5, 6, 4, 4, 4,
|
121
|
+
1, 0, 1, 8, 9, 7, 11, 7,
|
122
|
+
10, 10, 10, 1, 13, 14, 12, 12,
|
123
|
+
1, 13, 1, 15, 1, 16, 17, 7,
|
124
|
+
18, 7, 10, 10, 10, 1, 19, 19,
|
125
|
+
19, 19, 19, 19, 19, 19, 19, 1,
|
126
|
+
21, 22, 20, 23, 24, 25, 23, 23,
|
127
|
+
20, 23, 23, 23, 23, 23, 23, 1,
|
128
|
+
26, 26, 26, 26, 26, 26, 26, 26,
|
129
|
+
26, 1, 28, 29, 27, 30, 31, 30,
|
130
|
+
30, 27, 30, 30, 30, 30, 30, 30,
|
131
|
+
1, 32, 32, 32, 32, 32, 32, 32,
|
132
|
+
32, 32, 1, 33, 34, 20, 35, 36,
|
133
|
+
37, 35, 35, 20, 35, 35, 35, 35,
|
134
|
+
35, 35, 1, 38, 38, 38, 38, 38,
|
135
|
+
38, 38, 38, 38, 1, 39, 40, 27,
|
136
|
+
41, 42, 41, 41, 27, 41, 41, 41,
|
137
|
+
41, 41, 41, 1, 43, 43, 43, 43,
|
138
|
+
43, 43, 43, 43, 43, 1, 44, 45,
|
139
|
+
46, 47, 48, 46, 46, 46, 46, 46,
|
140
|
+
46, 46, 46, 1, 49, 49, 49, 49,
|
141
|
+
49, 49, 49, 49, 49, 1, 50, 51,
|
142
|
+
52, 53, 52, 52, 52, 52, 52, 52,
|
143
|
+
52, 52, 1, 54, 1, 55, 1, 56,
|
144
|
+
1, 57, 1, 58, 1, 59, 58, 1,
|
145
|
+
60, 1, 61, 60, 1, 62, 1, 63,
|
146
|
+
1, 64, 1, 66, 67, 68, 65, 70,
|
147
|
+
71, 69, 13, 14, 72, 72, 72, 72,
|
148
|
+
72, 72, 72, 72, 72, 1, 73, 74,
|
149
|
+
73, 73, 73, 73, 73, 73, 73, 73,
|
150
|
+
1, 76, 77, 78, 75, 80, 81, 79,
|
151
|
+
82, 1, 84, 85, 83, 1, 0
|
140
152
|
};
|
141
153
|
|
142
|
-
static const char
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
154
|
+
static const char _httpclient_parser_trans_targs[] = {
|
155
|
+
39, 0, 2, 3, 7, 16, 20, 4,
|
156
|
+
39, 6, 7, 12, 4, 39, 5, 39,
|
157
|
+
39, 5, 8, 9, 4, 39, 5, 9,
|
158
|
+
8, 10, 11, 4, 39, 5, 11, 8,
|
159
|
+
13, 39, 6, 13, 12, 14, 15, 39,
|
160
|
+
6, 15, 12, 17, 39, 2, 17, 16,
|
161
|
+
18, 19, 39, 2, 19, 16, 21, 22,
|
162
|
+
23, 24, 25, 26, 27, 28, 29, 30,
|
163
|
+
31, 32, 33, 37, 38, 32, 33, 37,
|
164
|
+
34, 34, 35, 36, 33, 37, 35, 36,
|
165
|
+
33, 37, 33, 32, 33, 37
|
152
166
|
};
|
153
167
|
|
154
|
-
static const char
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
0, 0,
|
163
|
-
|
168
|
+
static const char _httpclient_parser_trans_actions[] = {
|
169
|
+
37, 0, 0, 1, 1, 0, 1, 15,
|
170
|
+
59, 15, 0, 15, 0, 17, 0, 40,
|
171
|
+
34, 15, 15, 3, 43, 63, 43, 0,
|
172
|
+
43, 22, 7, 9, 28, 9, 0, 9,
|
173
|
+
3, 74, 43, 0, 43, 22, 7, 51,
|
174
|
+
9, 0, 9, 3, 68, 43, 0, 43,
|
175
|
+
22, 7, 47, 9, 0, 9, 0, 0,
|
176
|
+
0, 0, 0, 0, 0, 13, 1, 0,
|
177
|
+
0, 31, 55, 55, 31, 0, 11, 11,
|
178
|
+
3, 0, 5, 7, 25, 25, 7, 0,
|
179
|
+
9, 9, 0, 1, 19, 19
|
164
180
|
};
|
165
181
|
|
166
|
-
static const int httpclient_parser_start =
|
167
|
-
|
182
|
+
static const int httpclient_parser_start = 1;
|
168
183
|
static const int httpclient_parser_first_final = 39;
|
184
|
+
static const int httpclient_parser_error = 0;
|
185
|
+
|
186
|
+
static const int httpclient_parser_en_main = 1;
|
169
187
|
|
170
|
-
static const int httpclient_parser_error = 1;
|
171
188
|
|
172
189
|
#line 99 "http11_parser.rl"
|
173
190
|
|
174
191
|
int httpclient_parser_init(httpclient_parser *parser) {
|
175
192
|
int cs = 0;
|
176
193
|
|
177
|
-
#line
|
194
|
+
#line 195 "http11_parser.c"
|
178
195
|
{
|
179
196
|
cs = httpclient_parser_start;
|
180
197
|
}
|
198
|
+
|
181
199
|
#line 103 "http11_parser.rl"
|
182
200
|
parser->cs = cs;
|
183
201
|
parser->body_start = 0;
|
@@ -206,7 +224,7 @@ size_t httpclient_parser_execute(httpclient_parser *parser, const char *buffer,
|
|
206
224
|
|
207
225
|
|
208
226
|
|
209
|
-
#line
|
227
|
+
#line 228 "http11_parser.c"
|
210
228
|
{
|
211
229
|
int _klen;
|
212
230
|
unsigned int _trans;
|
@@ -215,10 +233,10 @@ size_t httpclient_parser_execute(httpclient_parser *parser, const char *buffer,
|
|
215
233
|
const char *_keys;
|
216
234
|
|
217
235
|
if ( p == pe )
|
236
|
+
goto _test_eof;
|
237
|
+
if ( cs == 0 )
|
218
238
|
goto _out;
|
219
239
|
_resume:
|
220
|
-
if ( cs == 1 )
|
221
|
-
goto _out;
|
222
240
|
_keys = _httpclient_parser_trans_keys + _httpclient_parser_key_offsets[cs];
|
223
241
|
_trans = _httpclient_parser_index_offsets[cs];
|
224
242
|
|
@@ -269,12 +287,12 @@ _resume:
|
|
269
287
|
|
270
288
|
_match:
|
271
289
|
_trans = _httpclient_parser_indicies[_trans];
|
272
|
-
cs =
|
290
|
+
cs = _httpclient_parser_trans_targs[_trans];
|
273
291
|
|
274
|
-
if (
|
292
|
+
if ( _httpclient_parser_trans_actions[_trans] == 0 )
|
275
293
|
goto _again;
|
276
294
|
|
277
|
-
_acts = _httpclient_parser_actions +
|
295
|
+
_acts = _httpclient_parser_actions + _httpclient_parser_trans_actions[_trans];
|
278
296
|
_nacts = (unsigned int) *_acts++;
|
279
297
|
while ( _nacts-- > 0 )
|
280
298
|
{
|
@@ -340,18 +358,22 @@ _match:
|
|
340
358
|
parser->body_start = p - buffer + 1;
|
341
359
|
if(parser->header_done != NULL)
|
342
360
|
parser->header_done(parser->data, p + 1, pe - p - 1);
|
343
|
-
goto _out;
|
361
|
+
{p++; goto _out; }
|
344
362
|
}
|
345
363
|
break;
|
346
|
-
#line
|
364
|
+
#line 365 "http11_parser.c"
|
347
365
|
}
|
348
366
|
}
|
349
367
|
|
350
368
|
_again:
|
369
|
+
if ( cs == 0 )
|
370
|
+
goto _out;
|
351
371
|
if ( ++p != pe )
|
352
372
|
goto _resume;
|
373
|
+
_test_eof: {}
|
353
374
|
_out: {}
|
354
375
|
}
|
376
|
+
|
355
377
|
#line 130 "http11_parser.rl"
|
356
378
|
|
357
379
|
parser->cs = cs;
|
@@ -366,10 +388,7 @@ _again:
|
|
366
388
|
|
367
389
|
if(parser->body_start) {
|
368
390
|
/* final \r\n combo encountered so stop right here */
|
369
|
-
|
370
|
-
#line 371 "http11_parser.c"
|
371
|
-
#line 144 "http11_parser.rl"
|
372
|
-
parser->nread++;
|
391
|
+
parser->nread = parser->body_start;
|
373
392
|
}
|
374
393
|
|
375
394
|
return(parser->nread);
|
@@ -379,10 +398,6 @@ int httpclient_parser_finish(httpclient_parser *parser)
|
|
379
398
|
{
|
380
399
|
int cs = parser->cs;
|
381
400
|
|
382
|
-
|
383
|
-
#line 384 "http11_parser.c"
|
384
|
-
#line 155 "http11_parser.rl"
|
385
|
-
|
386
401
|
parser->cs = cs;
|
387
402
|
|
388
403
|
if (httpclient_parser_has_error(parser) ) {
|
@@ -62,7 +62,7 @@
|
|
62
62
|
}
|
63
63
|
|
64
64
|
# line endings
|
65
|
-
CRLF = "\r\n";
|
65
|
+
CRLF = ("\r\n" | "\n");
|
66
66
|
|
67
67
|
# character types
|
68
68
|
CTL = (cntrl | 127);
|
@@ -140,8 +140,7 @@ size_t httpclient_parser_execute(httpclient_parser *parser, const char *buffer,
|
|
140
140
|
|
141
141
|
if(parser->body_start) {
|
142
142
|
/* final \r\n combo encountered so stop right here */
|
143
|
-
|
144
|
-
parser->nread++;
|
143
|
+
parser->nread = parser->body_start;
|
145
144
|
}
|
146
145
|
|
147
146
|
return(parser->nread);
|
@@ -151,8 +150,6 @@ int httpclient_parser_finish(httpclient_parser *parser)
|
|
151
150
|
{
|
152
151
|
int cs = parser->cs;
|
153
152
|
|
154
|
-
%%write eof;
|
155
|
-
|
156
153
|
parser->cs = cs;
|
157
154
|
|
158
155
|
if (httpclient_parser_has_error(parser) ) {
|
data/lib/em-http/client.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- coding: undecided -*-
|
2
1
|
# #--
|
3
2
|
# Copyright (C)2008 Ilya Grigorik
|
4
3
|
#
|
@@ -21,6 +20,16 @@ module EventMachine
|
|
21
20
|
|
22
21
|
# The status code (as a string!)
|
23
22
|
attr_accessor :http_status
|
23
|
+
|
24
|
+
# E-Tag
|
25
|
+
def etag
|
26
|
+
self["ETag"]
|
27
|
+
end
|
28
|
+
|
29
|
+
def last_modified
|
30
|
+
time = self["Last-Modified"]
|
31
|
+
Time.parse(time) if time
|
32
|
+
end
|
24
33
|
|
25
34
|
# HTTP response status as an integer
|
26
35
|
def status
|
@@ -32,6 +41,11 @@ module EventMachine
|
|
32
41
|
Integer(self[HttpClient::CONTENT_LENGTH]) rescue nil
|
33
42
|
end
|
34
43
|
|
44
|
+
# Cookie header from the server
|
45
|
+
def cookie
|
46
|
+
self[HttpClient::SET_COOKIE]
|
47
|
+
end
|
48
|
+
|
35
49
|
# Is the transfer encoding chunked?
|
36
50
|
def chunked_encoding?
|
37
51
|
/chunked/i === self[HttpClient::TRANSFER_ENCODING]
|
@@ -44,6 +58,10 @@ module EventMachine
|
|
44
58
|
def compressed?
|
45
59
|
/gzip|compressed|deflate/i === self[HttpClient::CONTENT_ENCODING]
|
46
60
|
end
|
61
|
+
|
62
|
+
def location
|
63
|
+
self[HttpClient::LOCATION]
|
64
|
+
end
|
47
65
|
end
|
48
66
|
|
49
67
|
class HttpChunkHeader < Hash
|
@@ -86,7 +104,7 @@ module EventMachine
|
|
86
104
|
# you include port 80 then further redirects will tack on the :80 which is
|
87
105
|
# annoying.
|
88
106
|
def encode_host
|
89
|
-
@uri.host + (@uri.port
|
107
|
+
@uri.host + (@uri.port != 80 ? ":#{@uri.port}" : "")
|
90
108
|
end
|
91
109
|
|
92
110
|
def encode_request(method, path, query)
|
@@ -94,12 +112,16 @@ module EventMachine
|
|
94
112
|
end
|
95
113
|
|
96
114
|
def encode_query(path, query)
|
97
|
-
|
98
|
-
|
99
|
-
return "#{path}?#{query}"
|
115
|
+
encoded_query = if query.kind_of?(Hash)
|
116
|
+
query.map { |k, v| encode_param(k, v) }.join('&')
|
100
117
|
else
|
101
|
-
|
118
|
+
query.to_s
|
119
|
+
end
|
120
|
+
if !@uri.query.to_s.empty?
|
121
|
+
encoded_query = [encoded_query, @uri.query].reject {|part| part.empty?}.join("&")
|
102
122
|
end
|
123
|
+
return path if encoded_query.to_s.empty?
|
124
|
+
"#{path}?#{encoded_query}"
|
103
125
|
end
|
104
126
|
|
105
127
|
# URL encodes query parameters:
|
@@ -134,8 +156,12 @@ module EventMachine
|
|
134
156
|
end
|
135
157
|
end
|
136
158
|
|
137
|
-
def
|
138
|
-
|
159
|
+
def encode_cookie(cookie)
|
160
|
+
if cookie.is_a? Hash
|
161
|
+
cookie.inject('') { |result, (k, v)| result << encode_param(k, v) + ";" }
|
162
|
+
else
|
163
|
+
cookie
|
164
|
+
end
|
139
165
|
end
|
140
166
|
end
|
141
167
|
|
@@ -164,17 +190,20 @@ module EventMachine
|
|
164
190
|
@state = :response_header
|
165
191
|
@parser_nbytes = 0
|
166
192
|
@response = ''
|
167
|
-
@inflate = []
|
168
193
|
@errors = ''
|
169
194
|
@content_decoder = nil
|
195
|
+
@stream = nil
|
170
196
|
end
|
171
197
|
|
172
198
|
# start HTTP request once we establish connection to host
|
173
199
|
def connection_completed
|
200
|
+
ssl = @options[:tls] || @options[:ssl] || {}
|
201
|
+
start_tls(ssl) if @uri.scheme == "https" #or @uri.port == 443 # A user might not want https even on port 443.
|
202
|
+
|
174
203
|
send_request_header
|
175
204
|
send_request_body
|
176
205
|
end
|
177
|
-
|
206
|
+
|
178
207
|
# request is done, invoke the callback
|
179
208
|
def on_request_complete
|
180
209
|
begin
|
@@ -184,17 +213,33 @@ module EventMachine
|
|
184
213
|
end
|
185
214
|
unbind
|
186
215
|
end
|
187
|
-
|
216
|
+
|
188
217
|
# request failed, invoke errback
|
189
|
-
def on_error(msg)
|
218
|
+
def on_error(msg, dns_error = false)
|
190
219
|
@errors = msg
|
191
|
-
|
220
|
+
|
221
|
+
# no connection signature on DNS failures
|
222
|
+
# fail the connection directly
|
223
|
+
dns_error == true ? fail : unbind
|
224
|
+
end
|
225
|
+
|
226
|
+
# assign a stream processing block
|
227
|
+
def stream(&blk)
|
228
|
+
@stream = blk
|
229
|
+
end
|
230
|
+
|
231
|
+
def normalize_body
|
232
|
+
if @options[:body].is_a? Hash
|
233
|
+
@options[:body].to_params
|
234
|
+
else
|
235
|
+
@options[:body]
|
236
|
+
end
|
192
237
|
end
|
193
238
|
|
194
239
|
def send_request_header
|
195
240
|
query = @options[:query]
|
196
241
|
head = @options[:head] ? munge_header_keys(@options[:head]) : {}
|
197
|
-
body =
|
242
|
+
body = normalize_body
|
198
243
|
|
199
244
|
# Set the Host header if it hasn't been specified already
|
200
245
|
head['host'] ||= encode_host
|
@@ -205,9 +250,9 @@ module EventMachine
|
|
205
250
|
# Set the User-Agent if it hasn't been specified
|
206
251
|
head['user-agent'] ||= "EventMachine HttpClient"
|
207
252
|
|
208
|
-
# Set
|
209
|
-
if head
|
210
|
-
|
253
|
+
# Set the cookie header if provided
|
254
|
+
if cookie = head.delete('cookie')
|
255
|
+
head['cookie'] = encode_cookie(cookie)
|
211
256
|
end
|
212
257
|
|
213
258
|
# Build the request
|
@@ -220,11 +265,7 @@ module EventMachine
|
|
220
265
|
|
221
266
|
def send_request_body
|
222
267
|
return unless @options[:body]
|
223
|
-
|
224
|
-
body = @options[:body].to_params
|
225
|
-
else
|
226
|
-
body = @options[:body]
|
227
|
-
end
|
268
|
+
body = normalize_body
|
228
269
|
send_data body
|
229
270
|
end
|
230
271
|
|
@@ -247,15 +288,19 @@ module EventMachine
|
|
247
288
|
end
|
248
289
|
|
249
290
|
def on_decoded_body_data(data)
|
250
|
-
if
|
251
|
-
|
291
|
+
if @stream
|
292
|
+
@stream.call(data)
|
252
293
|
else
|
253
294
|
@response << data
|
254
295
|
end
|
255
296
|
end
|
256
297
|
|
257
298
|
def unbind
|
258
|
-
|
299
|
+
if @state == :finished || (@state == :body && @bytes_remaining.nil?)
|
300
|
+
succeed(self)
|
301
|
+
else
|
302
|
+
fail(self)
|
303
|
+
end
|
259
304
|
close_connection
|
260
305
|
end
|
261
306
|
|
@@ -286,7 +331,6 @@ module EventMachine
|
|
286
331
|
|
287
332
|
def parse_header(header)
|
288
333
|
return false if @data.empty?
|
289
|
-
|
290
334
|
begin
|
291
335
|
@parser_nbytes = @parser.execute(header, @data.to_str, @parser_nbytes)
|
292
336
|
rescue EventMachine::HttpClientParserError
|
@@ -313,22 +357,50 @@ module EventMachine
|
|
313
357
|
return false
|
314
358
|
end
|
315
359
|
|
360
|
+
# correct location header - some servers will incorrectly give a relative URI
|
361
|
+
if @response_header.location
|
362
|
+
begin
|
363
|
+
location = URI.parse @response_header.location
|
364
|
+
if location.relative?
|
365
|
+
location = (@uri.merge location).to_s
|
366
|
+
@response_header[LOCATION] = location
|
367
|
+
end
|
368
|
+
rescue
|
369
|
+
on_error "Location header format error"
|
370
|
+
return false
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
# shortcircuit on HEAD requests
|
375
|
+
if @method == "HEAD"
|
376
|
+
@state = :finished
|
377
|
+
on_request_complete
|
378
|
+
end
|
379
|
+
|
316
380
|
if @response_header.chunked_encoding?
|
317
381
|
@state = :chunk_header
|
382
|
+
elsif @response_header.content_length
|
383
|
+
if @response_header.content_length > 0
|
384
|
+
@state = :body
|
385
|
+
@bytes_remaining = @response_header.content_length
|
386
|
+
else
|
387
|
+
@state = :body
|
388
|
+
@bytes_remaining = nil
|
389
|
+
end
|
318
390
|
else
|
319
|
-
@state = :
|
320
|
-
|
391
|
+
@state = :invalid
|
392
|
+
on_error "no HTTP response"
|
393
|
+
return false
|
321
394
|
end
|
322
395
|
|
323
|
-
if
|
324
|
-
decoder_class = HttpDecoders.decoder_for_encoding(response_header[CONTENT_ENCODING])
|
396
|
+
if decoder_class = HttpDecoders.decoder_for_encoding(response_header[CONTENT_ENCODING])
|
325
397
|
begin
|
326
398
|
@content_decoder = decoder_class.new do |s| on_decoded_body_data(s) end
|
327
399
|
rescue HttpDecoders::DecoderError
|
328
400
|
on_error "Content-decoder error"
|
329
401
|
end
|
330
402
|
end
|
331
|
-
|
403
|
+
|
332
404
|
true
|
333
405
|
end
|
334
406
|
|
data/lib/em-http/decoders.rb
CHANGED
data/lib/em-http/request.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'uri'
|
2
1
|
require 'base64'
|
2
|
+
require 'addressable/uri'
|
3
3
|
|
4
4
|
module EventMachine
|
5
5
|
|
@@ -27,7 +27,7 @@ module EventMachine
|
|
27
27
|
|
28
28
|
def initialize(host, headers = {})
|
29
29
|
@headers = headers
|
30
|
-
@uri = host.kind_of?(URI) ? host : URI::parse(host)
|
30
|
+
@uri = host.kind_of?(Addressable::URI) ? host : Addressable::URI::parse(host)
|
31
31
|
end
|
32
32
|
|
33
33
|
# Send an HTTP request and consume the response. Supported options:
|
@@ -50,6 +50,7 @@ module EventMachine
|
|
50
50
|
# Host: header
|
51
51
|
|
52
52
|
def get options = {}; send_request(:get, options); end
|
53
|
+
def head options = {}; send_request(:head, options); end
|
53
54
|
def post options = {}; send_request(:post, options); end
|
54
55
|
|
55
56
|
protected
|
@@ -57,19 +58,30 @@ module EventMachine
|
|
57
58
|
def send_request(method, options)
|
58
59
|
raise ArgumentError, "invalid request path" unless /^\// === @uri.path
|
59
60
|
|
61
|
+
# Make sure the port is set as Addressable::URI doesn't set the
|
62
|
+
# port if it isn't there.
|
63
|
+
@uri.port = @uri.port ? @uri.port : 80
|
60
64
|
method = method.to_s.upcase
|
61
65
|
begin
|
62
66
|
host = options[:host] || @uri.host
|
67
|
+
raise ArgumentError, "invalid host" unless host
|
68
|
+
raise ArgumentError, "invalid port" unless @uri.port
|
63
69
|
EventMachine.connect(host, @uri.port, EventMachine::HttpClient) { |c|
|
64
70
|
c.uri = @uri
|
65
71
|
c.method = method
|
66
72
|
c.options = options
|
67
|
-
|
73
|
+
if options.has_key?(:timeout) && options[:timeout]
|
74
|
+
c.comm_inactivity_timeout = options[:timeout]
|
75
|
+
c.pending_connect_timeout = options[:timeout]
|
76
|
+
elsif options.has_key?(:timeout)
|
77
|
+
c.comm_inactivity_timeout = 5
|
78
|
+
c.pending_connect_timeout = 5
|
79
|
+
end
|
68
80
|
}
|
69
81
|
rescue RuntimeError => e
|
70
82
|
raise e unless e.message == "no connection"
|
71
83
|
conn = EventMachine::HttpClient.new("")
|
72
|
-
conn.on_error("no connection")
|
84
|
+
conn.on_error("no connection", true)
|
73
85
|
conn
|
74
86
|
end
|
75
87
|
end
|
data/test/stallion.rb
CHANGED
@@ -80,9 +80,22 @@ Stallion.saddle :spec do |stable|
|
|
80
80
|
elsif stable.request.path_info == '/echo_query'
|
81
81
|
stable.response.write stable.request.query_string
|
82
82
|
|
83
|
+
elsif stable.request.path_info == '/echo_content_length'
|
84
|
+
stable.response.write stable.request.content_length
|
85
|
+
|
86
|
+
elsif stable.request.head?
|
87
|
+
stable.response.status = 200
|
88
|
+
|
83
89
|
elsif stable.request.post?
|
84
90
|
stable.response.write stable.request.body.read
|
85
91
|
|
92
|
+
elsif stable.request.path_info == '/set_cookie'
|
93
|
+
stable.response["Set-Cookie"] = "id=1; expires=Tue, 09-Aug-2011 17:53:39 GMT; path=/;"
|
94
|
+
stable.response.write "cookie set"
|
95
|
+
|
96
|
+
elsif stable.request.path_info == '/echo_cookie'
|
97
|
+
stable.response.write stable.request.env["HTTP_COOKIE"]
|
98
|
+
|
86
99
|
elsif stable.request.path_info == '/timeout'
|
87
100
|
sleep(10)
|
88
101
|
stable.response.write 'timeout'
|
@@ -121,7 +134,11 @@ Stallion.saddle :spec do |stable|
|
|
121
134
|
end
|
122
135
|
|
123
136
|
Thread.new do
|
124
|
-
|
137
|
+
begin
|
138
|
+
Stallion.run :Host => '127.0.0.1', :Port => 8080
|
139
|
+
rescue Exception => e
|
140
|
+
print e
|
141
|
+
end
|
125
142
|
end
|
126
143
|
|
127
|
-
sleep(
|
144
|
+
sleep(1)
|
data/test/stub_server.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
class StubServer
|
2
|
+
module Server
|
3
|
+
def receive_data(data)
|
4
|
+
send_data @response
|
5
|
+
close_connection_after_writing
|
6
|
+
end
|
7
|
+
|
8
|
+
def response=(response)
|
9
|
+
@response = response
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(response, port=8081)
|
14
|
+
@sig = EventMachine::start_server("127.0.0.1", port, Server) { |s|
|
15
|
+
s.response = response
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def stop
|
20
|
+
EventMachine.stop_server @sig
|
21
|
+
end
|
22
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'test/helper'
|
2
2
|
|
3
3
|
describe Hash do
|
4
|
+
|
4
5
|
describe ".to_params" do
|
5
6
|
it "should transform a basic hash into HTTP POST Params" do
|
6
7
|
{:a => "alpha", :b => "beta"}.to_params.should == "a=alpha&b=beta"
|
@@ -9,9 +10,10 @@ describe Hash do
|
|
9
10
|
it "should transform a more complex hash into HTTP POST Params" do
|
10
11
|
{:a => "a", :b => ["c", "d", "e"]}.to_params.should == "a=a&b[0]=c&b[1]=d&b[2]=e"
|
11
12
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
|
14
|
+
# Ruby 1.8 Hash is not sorted, so this test breaks randomly. Maybe once we're all on 1.9. ;-)
|
15
|
+
# it "should transform a very complex hash into HTTP POST Params" do
|
16
|
+
# {:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]}.to_params.should == "a=a&b[0][d]=d&b[0][c]=c&b[1][f]=f&b[1][e]=e"
|
17
|
+
# end
|
16
18
|
end
|
17
19
|
end
|
data/test/test_multi.rb
CHANGED
@@ -3,11 +3,6 @@ require 'test/stallion'
|
|
3
3
|
|
4
4
|
describe EventMachine::MultiRequest do
|
5
5
|
|
6
|
-
def failed
|
7
|
-
EventMachine.stop
|
8
|
-
fail
|
9
|
-
end
|
10
|
-
|
11
6
|
it "should submit multiple requests in parallel and return once all of them are complete" do
|
12
7
|
EventMachine.run {
|
13
8
|
|
@@ -16,7 +11,7 @@ describe EventMachine::MultiRequest do
|
|
16
11
|
|
17
12
|
# add multiple requests to the multi-handler
|
18
13
|
multi.add(EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get(:query => {:q => 'test'}))
|
19
|
-
multi.add(EventMachine::HttpRequest.new('http://
|
14
|
+
multi.add(EventMachine::HttpRequest.new('http://0.0.0.0/').get(:timeout => 1))
|
20
15
|
|
21
16
|
multi.callback {
|
22
17
|
# verify successfull request
|
data/test/test_request.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
require 'test/helper'
|
2
2
|
require 'test/stallion'
|
3
|
-
|
3
|
+
require 'test/stub_server'
|
4
|
+
|
4
5
|
describe EventMachine::HttpRequest do
|
5
6
|
|
6
7
|
def failed
|
7
8
|
EventMachine.stop
|
8
9
|
fail
|
9
10
|
end
|
10
|
-
|
11
|
+
|
11
12
|
it "should fail GET on DNS timeout" do
|
12
13
|
EventMachine.run {
|
13
|
-
http = EventMachine::HttpRequest.new('http://127.1.1.1/').get
|
14
|
+
http = EventMachine::HttpRequest.new('http://127.1.1.1/').get :timeout => 1
|
14
15
|
http.callback { failed }
|
15
16
|
http.errback {
|
16
17
|
http.response_header.status.should == 0
|
@@ -21,7 +22,7 @@ describe EventMachine::HttpRequest do
|
|
21
22
|
|
22
23
|
it "should fail GET on invalid host" do
|
23
24
|
EventMachine.run {
|
24
|
-
http = EventMachine::HttpRequest.new('http://google1.com/').get
|
25
|
+
http = EventMachine::HttpRequest.new('http://google1.com/').get :timeout => 1
|
25
26
|
http.callback { failed }
|
26
27
|
http.errback {
|
27
28
|
http.response_header.status.should == 0
|
@@ -68,12 +69,26 @@ describe EventMachine::HttpRequest do
|
|
68
69
|
}
|
69
70
|
end
|
70
71
|
|
72
|
+
it "should perform successfull HEAD with a URI passed as argument" do
|
73
|
+
EventMachine.run {
|
74
|
+
uri = URI.parse('http://127.0.0.1:8080/')
|
75
|
+
http = EventMachine::HttpRequest.new(uri).head
|
76
|
+
|
77
|
+
http.errback { failed }
|
78
|
+
http.callback {
|
79
|
+
http.response_header.status.should == 200
|
80
|
+
http.response.should == ""
|
81
|
+
EventMachine.stop
|
82
|
+
}
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
71
86
|
it "should return 404 on invalid path" do
|
72
87
|
EventMachine.run {
|
73
88
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/fail').get
|
74
89
|
|
75
90
|
http.errback { failed }
|
76
|
-
http.callback {
|
91
|
+
http.callback {
|
77
92
|
http.response_header.status.should == 404
|
78
93
|
EventMachine.stop
|
79
94
|
}
|
@@ -145,6 +160,20 @@ describe EventMachine::HttpRequest do
|
|
145
160
|
}
|
146
161
|
}
|
147
162
|
end
|
163
|
+
|
164
|
+
it "should perform successfull POST with Ruby Hash/Array as params and with the correct content length" do
|
165
|
+
EventMachine.run {
|
166
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_length').post :body => {"key1" => "data1"}
|
167
|
+
|
168
|
+
http.errback { failed }
|
169
|
+
http.callback {
|
170
|
+
http.response_header.status.should == 200
|
171
|
+
|
172
|
+
http.response.to_i.should == 10
|
173
|
+
EventMachine.stop
|
174
|
+
}
|
175
|
+
}
|
176
|
+
end
|
148
177
|
|
149
178
|
it "should perform successfull GET with custom header" do
|
150
179
|
EventMachine.run {
|
@@ -233,10 +262,10 @@ describe EventMachine::HttpRequest do
|
|
233
262
|
it "should timeout after 10 seconds" do
|
234
263
|
EventMachine.run {
|
235
264
|
t = Time.now.to_i
|
236
|
-
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/timeout').get :timeout =>
|
265
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/timeout').get :timeout => 1
|
237
266
|
|
238
267
|
http.errback {
|
239
|
-
(Time.now.to_i - t).should
|
268
|
+
(Time.now.to_i - t).should >= 2
|
240
269
|
EventMachine.stop
|
241
270
|
}
|
242
271
|
http.callback { failed }
|
@@ -246,10 +275,11 @@ describe EventMachine::HttpRequest do
|
|
246
275
|
it "should optionally pass the response body progressively" do
|
247
276
|
EventMachine.run {
|
248
277
|
body = ''
|
249
|
-
|
250
|
-
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :on_response => on_body
|
278
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
|
251
279
|
|
252
280
|
http.errback { failed }
|
281
|
+
http.stream { |chunk| body += chunk }
|
282
|
+
|
253
283
|
http.callback {
|
254
284
|
http.response_header.status.should == 200
|
255
285
|
http.response.should == ''
|
@@ -262,11 +292,11 @@ describe EventMachine::HttpRequest do
|
|
262
292
|
it "should optionally pass the deflate-encoded response body progressively" do
|
263
293
|
EventMachine.run {
|
264
294
|
body = ''
|
265
|
-
|
266
|
-
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/deflate').get :head => {"accept-encoding" => "deflate, compressed"},
|
267
|
-
:on_response => on_body
|
295
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/deflate').get :head => {"accept-encoding" => "deflate, compressed"}
|
268
296
|
|
269
297
|
http.errback { failed }
|
298
|
+
http.stream { |chunk| body += chunk }
|
299
|
+
|
270
300
|
http.callback {
|
271
301
|
http.response_header.status.should == 200
|
272
302
|
http.response_header["CONTENT_ENCODING"].should == "deflate"
|
@@ -277,16 +307,86 @@ describe EventMachine::HttpRequest do
|
|
277
307
|
}
|
278
308
|
end
|
279
309
|
|
280
|
-
it "should
|
310
|
+
it "should initiate SSL/TLS on HTTPS connections" do
|
311
|
+
EventMachine.run {
|
312
|
+
http = EventMachine::HttpRequest.new('https://mail.google.com:443/mail/').get
|
313
|
+
|
314
|
+
http.errback { failed }
|
315
|
+
http.callback {
|
316
|
+
http.response_header.status.should == 302
|
317
|
+
EventMachine.stop
|
318
|
+
}
|
319
|
+
}
|
320
|
+
end
|
321
|
+
|
322
|
+
it "should accept & return cookie header to user" do
|
281
323
|
EventMachine.run {
|
282
|
-
http = EventMachine::HttpRequest.new('http://127.
|
324
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/set_cookie').get
|
283
325
|
|
284
326
|
http.errback { failed }
|
285
327
|
http.callback {
|
286
328
|
http.response_header.status.should == 200
|
287
|
-
http.
|
329
|
+
http.response_header.cookie.should == "id=1; expires=Tue, 09-Aug-2011 17:53:39 GMT; path=/;"
|
330
|
+
EventMachine.stop
|
331
|
+
}
|
332
|
+
}
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should pass cookie header to server from string" do
|
336
|
+
EventMachine.run {
|
337
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_cookie').get :head => {'cookie' => 'id=2;'}
|
338
|
+
|
339
|
+
http.errback { failed }
|
340
|
+
http.callback {
|
341
|
+
http.response.should == "id=2;"
|
288
342
|
EventMachine.stop
|
289
343
|
}
|
290
344
|
}
|
291
345
|
end
|
346
|
+
|
347
|
+
it "should pass cookie header to server from Hash" do
|
348
|
+
EventMachine.run {
|
349
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_cookie').get :head => {'cookie' => {'id' => 2}}
|
350
|
+
|
351
|
+
http.errback { failed }
|
352
|
+
http.callback {
|
353
|
+
http.response.should == "id=2;"
|
354
|
+
EventMachine.stop
|
355
|
+
}
|
356
|
+
}
|
357
|
+
end
|
358
|
+
|
359
|
+
context "when talking to a stub HTTP/1.0 server" do
|
360
|
+
it "should get the body without Content-Length" do
|
361
|
+
EventMachine.run {
|
362
|
+
@s = StubServer.new("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nFoo")
|
363
|
+
|
364
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
|
365
|
+
http.errback { failed }
|
366
|
+
http.callback {
|
367
|
+
http.response.should match(/Foo/)
|
368
|
+
|
369
|
+
@s.stop
|
370
|
+
EventMachine.stop
|
371
|
+
}
|
372
|
+
}
|
373
|
+
end
|
374
|
+
|
375
|
+
it "should work with \\n instead of \\r\\n" do
|
376
|
+
EventMachine.run {
|
377
|
+
@s = StubServer.new("HTTP/1.0 200 OK\nContent-Type: text/plain\nContent-Length: 3\nConnection: close\n\nFoo")
|
378
|
+
|
379
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
|
380
|
+
http.errback { failed }
|
381
|
+
http.callback {
|
382
|
+
http.response_header.status.should == 200
|
383
|
+
http.response_header['CONTENT_TYPE'].should == 'text/plain'
|
384
|
+
http.response.should match(/Foo/)
|
385
|
+
|
386
|
+
@s.stop
|
387
|
+
EventMachine.stop
|
388
|
+
}
|
389
|
+
}
|
390
|
+
end
|
391
|
+
end
|
292
392
|
end
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: astro-em-http-request
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ilya Grigorik
|
8
|
+
- Stephan Maka
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date: 2009-
|
13
|
+
date: 2009-10-20 00:00:00 +02:00
|
13
14
|
default_executable:
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
@@ -20,10 +21,20 @@ dependencies:
|
|
20
21
|
requirements:
|
21
22
|
- - ">="
|
22
23
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.12.
|
24
|
+
version: 0.12.9
|
25
|
+
version:
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: addressable
|
28
|
+
type: :runtime
|
29
|
+
version_requirement:
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.0.0
|
24
35
|
version:
|
25
36
|
description: EventMachine based HTTP Request interface
|
26
|
-
email:
|
37
|
+
email: astro@spaceboyz.net
|
27
38
|
executables: []
|
28
39
|
|
29
40
|
extensions:
|
@@ -52,13 +63,16 @@ files:
|
|
52
63
|
- lib/em-http/decoders.rb
|
53
64
|
- lib/em-http/multi.rb
|
54
65
|
- lib/em-http/request.rb
|
55
|
-
- test/
|
66
|
+
- test/test_hash.rb
|
56
67
|
- test/helper.rb
|
57
68
|
- test/stallion.rb
|
69
|
+
- test/stub_server.rb
|
58
70
|
- test/test_multi.rb
|
59
71
|
- test/test_request.rb
|
60
72
|
has_rdoc: true
|
61
73
|
homepage: http://github.com/igrigorik/em-http-request
|
74
|
+
licenses: []
|
75
|
+
|
62
76
|
post_install_message:
|
63
77
|
rdoc_options: []
|
64
78
|
|
@@ -79,9 +93,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
93
|
requirements: []
|
80
94
|
|
81
95
|
rubyforge_project: em-http-request
|
82
|
-
rubygems_version: 1.
|
96
|
+
rubygems_version: 1.3.5
|
83
97
|
signing_key:
|
84
|
-
specification_version:
|
98
|
+
specification_version: 3
|
85
99
|
summary: EventMachine based HTTP Request interface
|
86
100
|
test_files: []
|
87
101
|
|