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 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
- body = ''
65
- on_body = lambda { |chunk| body += chunk }
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
@@ -34,6 +34,10 @@ task :ragel do
34
34
  end
35
35
  end
36
36
 
37
+ task :spec do
38
+ sh 'spec -c test/test_*.rb'
39
+ end
40
+
37
41
  def make(makedir)
38
42
  Dir.chdir(makedir) { sh MAKE }
39
43
  end
@@ -1,17 +1,18 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'em-http-request'
3
- s.version = '0.1.6'
4
- s.date = '2009-03-20'
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.2')
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/hash.rb",
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 27 "http11_parser.c"
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, 2, 3, 2, 6,
31
- 0, 2, 6, 5, 2, 9, 10, 2,
32
- 10, 9, 3, 2, 3, 4
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, 10, 10, 11, 22, 26, 27, 28,
37
- 39, 54, 75, 90, 110, 125, 146, 161,
38
- 181, 196, 214, 229, 246, 247, 248, 249,
39
- 250, 252, 255, 257, 260, 262, 264, 266,
40
- 268, 269, 270, 286, 302, 304, 305, 306
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, 70,
45
- 97, 102, 10, 13, 32, 59, 9, 12,
46
- 48, 57, 65, 70, 97, 102, 13, 32,
47
- 9, 12, 10, 10, 13, 32, 59, 9,
48
- 12, 48, 57, 65, 70, 97, 102, 33,
49
- 124, 126, 35, 39, 42, 43, 45, 46,
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, 33, 124, 126, 35, 39, 42,
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, 13, 32, 33, 59, 124, 126, 9,
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, 61,
69
- 124, 126, 35, 39, 42, 43, 45, 46,
70
- 48, 57, 65, 90, 94, 122, 33, 124,
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, 13, 32,
82
- 13, 13, 0
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
- 4, 0, 1, 3, 2, 1, 1, 3,
87
- 3, 7, 3, 6, 3, 7, 3, 6,
88
- 3, 6, 3, 5, 1, 1, 1, 1,
89
- 0, 1, 0, 1, 0, 0, 0, 2,
90
- 1, 1, 4, 4, 2, 1, 1, 0
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
- 3, 0, 0, 4, 1, 0, 0, 4,
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, 0, 6, 6, 0, 0, 0, 0
108
+ 0, 6, 6, 0, 0, 0, 0, 0
99
109
  };
100
110
 
101
- static const unsigned char _httpclient_parser_index_offsets[] = {
102
- 0, 8, 8, 10, 18, 22, 24, 26,
103
- 34, 44, 59, 69, 83, 93, 108, 118,
104
- 132, 142, 155, 165, 177, 179, 181, 183,
105
- 185, 187, 190, 192, 195, 197, 199, 201,
106
- 204, 206, 208, 219, 230, 233, 235, 237
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
- 14, 15, 17, 18, 16, 16, 16, 0,
111
- 30, 0, 63, 37, 64, 37, 39, 39,
112
- 39, 0, 19, 32, 32, 0, 29, 0,
113
- 31, 0, 38, 37, 40, 37, 39, 39,
114
- 39, 0, 58, 58, 58, 58, 58, 58,
115
- 58, 58, 58, 0, 42, 41, 43, 44,
116
- 45, 43, 43, 41, 43, 43, 43, 43,
117
- 43, 43, 0, 59, 59, 59, 59, 59,
118
- 59, 59, 59, 59, 0, 34, 33, 35,
119
- 36, 35, 35, 33, 35, 35, 35, 35,
120
- 35, 35, 0, 70, 70, 70, 70, 70,
121
- 70, 70, 70, 70, 0, 65, 41, 66,
122
- 67, 68, 66, 66, 41, 66, 66, 66,
123
- 66, 66, 66, 0, 69, 69, 69, 69,
124
- 69, 69, 69, 69, 69, 0, 60, 33,
125
- 61, 62, 61, 61, 33, 61, 61, 61,
126
- 61, 61, 61, 0, 10, 10, 10, 10,
127
- 10, 10, 10, 10, 10, 0, 24, 25,
128
- 26, 27, 25, 25, 25, 25, 25, 25,
129
- 25, 25, 0, 11, 11, 11, 11, 11,
130
- 11, 11, 11, 11, 0, 21, 22, 23,
131
- 22, 22, 22, 22, 22, 22, 22, 22,
132
- 0, 1, 0, 56, 0, 2, 0, 5,
133
- 0, 7, 0, 6, 7, 0, 13, 0,
134
- 12, 13, 0, 4, 0, 3, 0, 57,
135
- 0, 54, 55, 53, 49, 48, 28, 0,
136
- 19, 20, 20, 20, 20, 20, 20, 20,
137
- 20, 20, 0, 8, 9, 8, 8, 8,
138
- 8, 8, 8, 8, 8, 0, 47, 52,
139
- 51, 47, 46, 49, 50, 0, 0
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 _httpclient_parser_trans_targs_wi[] = {
143
- 1, 21, 23, 30, 29, 24, 26, 25,
144
- 35, 36, 17, 19, 28, 27, 2, 3,
145
- 7, 16, 20, 5, 35, 2, 19, 16,
146
- 2, 17, 16, 18, 34, 39, 39, 39,
147
- 4, 4, 5, 11, 8, 4, 5, 7,
148
- 8, 4, 5, 9, 8, 10, 37, 33,
149
- 32, 33, 32, 37, 36, 32, 33, 38,
150
- 22, 31, 9, 11, 6, 15, 12, 6,
151
- 12, 6, 13, 12, 14, 15, 13
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 _httpclient_parser_trans_actions_wi[] = {
155
- 0, 0, 0, 0, 1, 0, 0, 0,
156
- 0, 5, 3, 7, 13, 0, 0, 1,
157
- 1, 0, 1, 0, 3, 9, 0, 9,
158
- 34, 0, 34, 19, 0, 17, 28, 31,
159
- 0, 9, 9, 0, 9, 15, 15, 0,
160
- 15, 34, 34, 0, 34, 19, 0, 9,
161
- 0, 11, 1, 7, 7, 22, 25, 22,
162
- 0, 0, 3, 7, 9, 0, 9, 15,
163
- 15, 34, 0, 34, 19, 7, 3
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 = 0;
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 178 "http11_parser.c"
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 210 "http11_parser.c"
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 = _httpclient_parser_trans_targs_wi[_trans];
290
+ cs = _httpclient_parser_trans_targs[_trans];
273
291
 
274
- if ( _httpclient_parser_trans_actions_wi[_trans] == 0 )
292
+ if ( _httpclient_parser_trans_actions[_trans] == 0 )
275
293
  goto _again;
276
294
 
277
- _acts = _httpclient_parser_actions + _httpclient_parser_trans_actions_wi[_trans];
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 347 "http11_parser.c"
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
- %%write eof;
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) ) {
@@ -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.to_i != 80 ? ":#{@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
- return path unless query
98
- if query.kind_of? String
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
- return path + "?" + query.map { |k, v| encode_param(k, v) }.join('&')
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 encode_cookies(cookies)
138
- cookies.inject('') { |result, (k, v)| result << encode_field('Cookie', encode_param(k, v)) }
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
- unbind
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 = @options[: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 auto-inflate flags
209
- if head['accept-encoding']
210
- @inflate = head['accept-encoding'].split(',').map {|t| t.strip}
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
- if @options[:body].is_a? Hash
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 (on_response = @options[:on_response])
251
- on_response.call(data)
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
- (@state == :finished) ? succeed(self) : fail
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 = :body
320
- @bytes_remaining = @response_header.content_length
391
+ @state = :invalid
392
+ on_error "no HTTP response"
393
+ return false
321
394
  end
322
395
 
323
- if @inflate.include?(response_header[CONTENT_ENCODING]) &&
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
 
@@ -1,4 +1,5 @@
1
1
  require 'zlib'
2
+ require 'stringio'
2
3
 
3
4
  ##
4
5
  # Provides a unified callback interface to decompression libraries.
@@ -115,5 +116,3 @@ module EventMachine::HttpDecoders
115
116
  DECODERS = [Deflate, GZip]
116
117
 
117
118
  end
118
-
119
-
@@ -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
- c.comm_inactivity_timeout = options[:timeout] || 5
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
- Stallion.run :Host => '127.0.0.1', :Port => 8080
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(2)
144
+ sleep(1)
@@ -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
- it "should transform a very complex hash into HTTP POST Params" do
14
- {: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][e]=e&b[1][f]=f"
15
- end
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://169.169.169.169/').get)
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 => 2
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 == 2
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
- on_body = lambda { |chunk| body += chunk }
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
- on_body = lambda { |chunk| body += chunk }
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 respect manually-passed host address" do
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.1.1.1:8080/').get :host => '127.0.0.1'
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.response.should match(/Hello/)
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.6
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-03-20 00:00:00 -07:00
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.2
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: ilya@igvita.com
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/hash.rb
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.2.0
96
+ rubygems_version: 1.3.5
83
97
  signing_key:
84
- specification_version: 2
98
+ specification_version: 3
85
99
  summary: EventMachine based HTTP Request interface
86
100
  test_files: []
87
101