astro-em-http-request 0.1.6 → 0.1.12
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/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
|
|