astro-em-http-request 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/astro-em-http-request.gemspec +11 -12
- data/ext/buffer/em_buffer.c +74 -65
- data/lib/em-http-request.rb +1 -0
- data/lib/em-http/client.rb +9 -5
- data/lib/em-http/mock.rb +31 -12
- data/lib/em-http/multi.rb +3 -3
- data/lib/em-http/request.rb +4 -4
- data/lib/em_buffer.so +0 -0
- data/lib/http11_client.so +0 -0
- data/spec/mock_spec.rb +33 -4
- data/spec/multi_spec.rb +24 -2
- data/spec/request_spec.rb +3 -3
- metadata +9 -17
- data/test/another_test.rb +0 -21
data/Rakefile
CHANGED
@@ -92,9 +92,9 @@ begin
|
|
92
92
|
gemspec.email = "ilya@igvita.com"
|
93
93
|
gemspec.homepage = "http://github.com/igrigorik/em-http-request"
|
94
94
|
gemspec.authors = ["Ilya Grigorik", "Stephan Maka", "Julien Genestoux"]
|
95
|
+
gemspec.required_ruby_version = ">= 1.8.7"
|
95
96
|
gemspec.extensions = ["ext/buffer/extconf.rb" , "ext/http11_client/extconf.rb"]
|
96
97
|
gemspec.add_dependency('eventmachine', '>= 0.12.9')
|
97
|
-
gemspec.add_dependency('addressable', '>= 2.0.0')
|
98
98
|
gemspec.rubyforge_project = "astro-em-http-request"
|
99
99
|
gemspec.files = FileList[`git ls-files`.split]
|
100
100
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.9
|
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{astro-em-http-request}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.9"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Ilya Grigorik", "Stephan Maka", "Julien Genestoux"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-04-07}
|
13
13
|
s.description = %q{EventMachine based, async HTTP Request interface}
|
14
14
|
s.email = %q{ilya@igvita.com}
|
15
15
|
s.extensions = ["ext/buffer/extconf.rb", "ext/http11_client/extconf.rb"]
|
@@ -35,6 +35,7 @@ Gem::Specification.new do |s|
|
|
35
35
|
"ext/http11_client/http11_parser.c",
|
36
36
|
"ext/http11_client/http11_parser.h",
|
37
37
|
"ext/http11_client/http11_parser.rl",
|
38
|
+
"lib/em-http-request.rb",
|
38
39
|
"lib/em-http.rb",
|
39
40
|
"lib/em-http/client.rb",
|
40
41
|
"lib/em-http/core_ext/hash.rb",
|
@@ -42,6 +43,8 @@ Gem::Specification.new do |s|
|
|
42
43
|
"lib/em-http/mock.rb",
|
43
44
|
"lib/em-http/multi.rb",
|
44
45
|
"lib/em-http/request.rb",
|
46
|
+
"lib/em_buffer.so",
|
47
|
+
"lib/http11_client.so",
|
45
48
|
"spec/fixtures/google.ca",
|
46
49
|
"spec/hash_spec.rb",
|
47
50
|
"spec/helper.rb",
|
@@ -54,20 +57,20 @@ Gem::Specification.new do |s|
|
|
54
57
|
s.homepage = %q{http://github.com/igrigorik/em-http-request}
|
55
58
|
s.rdoc_options = ["--charset=UTF-8"]
|
56
59
|
s.require_paths = ["lib"]
|
60
|
+
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
57
61
|
s.rubyforge_project = %q{astro-em-http-request}
|
58
62
|
s.rubygems_version = %q{1.3.5}
|
59
63
|
s.summary = %q{EventMachine based, async HTTP Request interface}
|
60
64
|
s.test_files = [
|
61
65
|
"spec/hash_spec.rb",
|
62
66
|
"spec/helper.rb",
|
67
|
+
"spec/stub_server.rb",
|
68
|
+
"spec/stallion.rb",
|
63
69
|
"spec/mock_spec.rb",
|
64
70
|
"spec/multi_spec.rb",
|
65
71
|
"spec/request_spec.rb",
|
66
|
-
"spec/stallion.rb",
|
67
|
-
"spec/stub_server.rb",
|
68
|
-
"test/another_test.rb",
|
69
|
-
"examples/fetch.rb",
|
70
72
|
"examples/fibered-http.rb",
|
73
|
+
"examples/fetch.rb",
|
71
74
|
"examples/oauth-tweet.rb"
|
72
75
|
]
|
73
76
|
|
@@ -77,14 +80,10 @@ Gem::Specification.new do |s|
|
|
77
80
|
|
78
81
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
79
82
|
s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.9"])
|
80
|
-
s.add_runtime_dependency(%q<addressable>, [">= 2.0.0"])
|
81
83
|
else
|
82
84
|
s.add_dependency(%q<eventmachine>, [">= 0.12.9"])
|
83
|
-
s.add_dependency(%q<addressable>, [">= 2.0.0"])
|
84
85
|
end
|
85
86
|
else
|
86
87
|
s.add_dependency(%q<eventmachine>, [">= 0.12.9"])
|
87
|
-
s.add_dependency(%q<addressable>, [">= 2.0.0"])
|
88
88
|
end
|
89
89
|
end
|
90
|
-
|
data/ext/buffer/em_buffer.c
CHANGED
@@ -29,15 +29,15 @@
|
|
29
29
|
#define PURGE_INTERVAL 10
|
30
30
|
|
31
31
|
struct buffer {
|
32
|
-
|
32
|
+
time_t last_purged_at;
|
33
33
|
unsigned size, node_size;
|
34
34
|
struct buffer_node *head, *tail;
|
35
35
|
struct buffer_node *pool_head, *pool_tail;
|
36
|
-
|
36
|
+
|
37
37
|
};
|
38
38
|
|
39
39
|
struct buffer_node {
|
40
|
-
|
40
|
+
time_t last_used_at;
|
41
41
|
unsigned start, end;
|
42
42
|
struct buffer_node *next;
|
43
43
|
unsigned char data[0];
|
@@ -72,7 +72,7 @@ static void buffer_copy(struct buffer *buf, char *str, unsigned len);
|
|
72
72
|
static int buffer_read_from(struct buffer *buf, int fd);
|
73
73
|
static int buffer_write_to(struct buffer *buf, int fd);
|
74
74
|
|
75
|
-
/*
|
75
|
+
/*
|
76
76
|
* High speed buffering geared towards non-blocking I/O.
|
77
77
|
*
|
78
78
|
* Data is stored in a byte queue implemented as a linked list of equal size
|
@@ -94,8 +94,8 @@ void Init_em_buffer()
|
|
94
94
|
rb_define_method(cEm_Buffer, "append", Em_Buffer_append, 1);
|
95
95
|
rb_define_method(cEm_Buffer, "prepend", Em_Buffer_prepend, 1);
|
96
96
|
rb_define_method(cEm_Buffer, "read", Em_Buffer_read, -1);
|
97
|
-
|
98
|
-
|
97
|
+
rb_define_method(cEm_Buffer, "to_str", Em_Buffer_to_str, 0);
|
98
|
+
rb_define_method(cEm_Buffer, "read_from", Em_Buffer_read_from, 1);
|
99
99
|
rb_define_method(cEm_Buffer, "write_to", Em_Buffer_write_to, 1);
|
100
100
|
}
|
101
101
|
|
@@ -118,7 +118,7 @@ static void Em_Buffer_free(struct buffer *buf)
|
|
118
118
|
/**
|
119
119
|
* call-seq:
|
120
120
|
* EventMachine::Buffer.new(size = DEFAULT_NODE_SIZE) -> EventMachine::Buffer
|
121
|
-
*
|
121
|
+
*
|
122
122
|
* Create a new EventMachine::Buffer with linked segments of the given size
|
123
123
|
*/
|
124
124
|
static VALUE Em_Buffer_initialize(int argc, VALUE *argv, VALUE self)
|
@@ -147,7 +147,7 @@ static VALUE Em_Buffer_initialize(int argc, VALUE *argv, VALUE self)
|
|
147
147
|
/**
|
148
148
|
* call-seq:
|
149
149
|
* EventMachine::Buffer#clear -> nil
|
150
|
-
*
|
150
|
+
*
|
151
151
|
* Clear all data from the EventMachine::Buffer
|
152
152
|
*/
|
153
153
|
static VALUE Em_Buffer_clear(VALUE self)
|
@@ -163,10 +163,10 @@ static VALUE Em_Buffer_clear(VALUE self)
|
|
163
163
|
/**
|
164
164
|
* call-seq:
|
165
165
|
* EventMachine::Buffer#size -> Integer
|
166
|
-
*
|
166
|
+
*
|
167
167
|
* Return the size of the buffer in bytes
|
168
168
|
*/
|
169
|
-
static VALUE Em_Buffer_size(VALUE self)
|
169
|
+
static VALUE Em_Buffer_size(VALUE self)
|
170
170
|
{
|
171
171
|
struct buffer *buf;
|
172
172
|
Data_Get_Struct(self, struct buffer, buf);
|
@@ -177,21 +177,21 @@ static VALUE Em_Buffer_size(VALUE self)
|
|
177
177
|
/**
|
178
178
|
* call-seq:
|
179
179
|
* EventMachine::Buffer#empty? -> Boolean
|
180
|
-
*
|
180
|
+
*
|
181
181
|
* Is the buffer empty?
|
182
182
|
*/
|
183
|
-
static VALUE Em_Buffer_empty(VALUE self)
|
183
|
+
static VALUE Em_Buffer_empty(VALUE self)
|
184
184
|
{
|
185
185
|
struct buffer *buf;
|
186
186
|
Data_Get_Struct(self, struct buffer, buf);
|
187
187
|
|
188
|
-
return buf->size > 0 ? Qfalse : Qtrue;
|
188
|
+
return buf->size > 0 ? Qfalse : Qtrue;
|
189
189
|
}
|
190
190
|
|
191
191
|
/**
|
192
192
|
* call-seq:
|
193
193
|
* EventMachine::Buffer#append(data) -> String
|
194
|
-
*
|
194
|
+
*
|
195
195
|
* Append the given data to the end of the buffer
|
196
196
|
*/
|
197
197
|
static VALUE Em_Buffer_append(VALUE self, VALUE data)
|
@@ -209,7 +209,7 @@ static VALUE Em_Buffer_append(VALUE self, VALUE data)
|
|
209
209
|
/**
|
210
210
|
* call-seq:
|
211
211
|
* EventMachine::Buffer#prepend(data) -> String
|
212
|
-
*
|
212
|
+
*
|
213
213
|
* Prepend the given data to the beginning of the buffer
|
214
214
|
*/
|
215
215
|
static VALUE Em_Buffer_prepend(VALUE self, VALUE data)
|
@@ -226,7 +226,7 @@ static VALUE Em_Buffer_prepend(VALUE self, VALUE data)
|
|
226
226
|
/**
|
227
227
|
* call-seq:
|
228
228
|
* EventMachine::Buffer#read(length = nil) -> String
|
229
|
-
*
|
229
|
+
*
|
230
230
|
* Read the specified abount of data from the buffer. If no value
|
231
231
|
* is given the entire contents of the buffer are returned. Any data
|
232
232
|
* read from the buffer is cleared.
|
@@ -263,31 +263,31 @@ static VALUE Em_Buffer_read(int argc, VALUE *argv, VALUE self)
|
|
263
263
|
/**
|
264
264
|
* call-seq:
|
265
265
|
* EventMachine::Buffer#to_str -> String
|
266
|
-
*
|
266
|
+
*
|
267
267
|
* Convert the Buffer to a String. The original buffer is unmodified.
|
268
268
|
*/
|
269
269
|
static VALUE Em_Buffer_to_str(VALUE self) {
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
270
|
+
VALUE str;
|
271
|
+
struct buffer *buf;
|
272
|
+
|
273
|
+
Data_Get_Struct(self, struct buffer, buf);
|
274
|
+
|
275
|
+
str = rb_str_new(0, buf->size);
|
276
|
+
buffer_copy(buf, RSTRING_PTR(str), buf->size);
|
277
|
+
|
278
278
|
return str;
|
279
279
|
}
|
280
280
|
|
281
281
|
/**
|
282
282
|
* call-seq:
|
283
283
|
* EventMachine::Buffer#read_from(io) -> Integer
|
284
|
-
*
|
284
|
+
*
|
285
285
|
* Perform a nonblocking read of the the given IO object and fill
|
286
286
|
* the buffer with any data received. The call will read as much
|
287
287
|
* data as it can until the read would block.
|
288
288
|
*/
|
289
289
|
static VALUE Em_Buffer_read_from(VALUE self, VALUE io) {
|
290
|
-
|
290
|
+
struct buffer *buf;
|
291
291
|
#if HAVE_RB_IO_T
|
292
292
|
rb_io_t *fptr;
|
293
293
|
#else
|
@@ -298,20 +298,24 @@ static VALUE Em_Buffer_read_from(VALUE self, VALUE io) {
|
|
298
298
|
GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
|
299
299
|
rb_io_set_nonblock(fptr);
|
300
300
|
|
301
|
+
#ifdef HAVE_RB_IO_FD
|
302
|
+
return INT2NUM(buffer_read_from(buf, rb_io_fd(io)));
|
303
|
+
#else
|
301
304
|
return INT2NUM(buffer_read_from(buf, FPTR_TO_FD(fptr)));
|
305
|
+
#endif
|
302
306
|
}
|
303
307
|
|
304
308
|
/**
|
305
309
|
* call-seq:
|
306
310
|
* EventMachine::Buffer#write_to(io) -> Integer
|
307
|
-
*
|
311
|
+
*
|
308
312
|
* Perform a nonblocking write of the buffer to the given IO object.
|
309
313
|
* As much data as possible is written until the call would block.
|
310
314
|
* Any data which is written is removed from the buffer.
|
311
315
|
*/
|
312
316
|
static VALUE Em_Buffer_write_to(VALUE self, VALUE io) {
|
313
317
|
struct buffer *buf;
|
314
|
-
#if HAVE_RB_IO_T
|
318
|
+
#if HAVE_RB_IO_T
|
315
319
|
rb_io_t *fptr;
|
316
320
|
#else
|
317
321
|
OpenFile *fptr;
|
@@ -321,11 +325,16 @@ static VALUE Em_Buffer_write_to(VALUE self, VALUE io) {
|
|
321
325
|
GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
|
322
326
|
rb_io_set_nonblock(fptr);
|
323
327
|
|
324
|
-
|
328
|
+
#ifdef HAVE_RB_IO_FD
|
329
|
+
return INT2NUM(buffer_read_from(buf, rb_io_fd(io)));
|
330
|
+
#else
|
331
|
+
return INT2NUM(buffer_read_from(buf, FPTR_TO_FD(fptr)));
|
332
|
+
#endif
|
333
|
+
|
325
334
|
}
|
326
335
|
|
327
336
|
/*
|
328
|
-
* Ruby bindings end here. Below is the actual implementation of
|
337
|
+
* Ruby bindings end here. Below is the actual implementation of
|
329
338
|
* the underlying data structures.
|
330
339
|
*/
|
331
340
|
|
@@ -338,8 +347,8 @@ static struct buffer *buffer_new(void)
|
|
338
347
|
buf->head = buf->tail = buf->pool_head = buf->pool_tail = 0;
|
339
348
|
buf->size = 0;
|
340
349
|
buf->node_size = DEFAULT_NODE_SIZE;
|
341
|
-
|
342
|
-
|
350
|
+
time(&buf->last_purged_at);
|
351
|
+
|
343
352
|
return buf;
|
344
353
|
}
|
345
354
|
|
@@ -359,7 +368,7 @@ static void buffer_clear(struct buffer *buf)
|
|
359
368
|
}
|
360
369
|
|
361
370
|
/* Free a buffer */
|
362
|
-
static void buffer_free(struct buffer *buf)
|
371
|
+
static void buffer_free(struct buffer *buf)
|
363
372
|
{
|
364
373
|
struct buffer_node *tmp;
|
365
374
|
|
@@ -381,11 +390,11 @@ static void buffer_gc(struct buffer *buf)
|
|
381
390
|
time_t now;
|
382
391
|
time(&now);
|
383
392
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
393
|
+
/* Only purge if we've passed the purge interval */
|
394
|
+
if(now - buf->last_purged_at < PURGE_INTERVAL)
|
395
|
+
return;
|
396
|
+
|
397
|
+
buf->last_purged_at = now;
|
389
398
|
|
390
399
|
while(buf->pool_head && now - buf->pool_head->last_used_at >= MAX_AGE) {
|
391
400
|
tmp = buf->pool_head;
|
@@ -394,7 +403,7 @@ static void buffer_gc(struct buffer *buf)
|
|
394
403
|
}
|
395
404
|
|
396
405
|
if(!buf->pool_head)
|
397
|
-
|
406
|
+
buf->pool_tail = 0;
|
398
407
|
}
|
399
408
|
|
400
409
|
/* Create a new buffer_node (or pull one from the memory pool) */
|
@@ -494,11 +503,11 @@ static void buffer_append(struct buffer *buf, char *str, unsigned len)
|
|
494
503
|
while(len > 0) {
|
495
504
|
nbytes = buf->node_size - buf->tail->end;
|
496
505
|
if(len < nbytes) nbytes = len;
|
497
|
-
|
506
|
+
|
498
507
|
memcpy(buf->tail->data + buf->tail->end, str, nbytes);
|
499
|
-
str += nbytes;
|
508
|
+
str += nbytes;
|
500
509
|
len -= nbytes;
|
501
|
-
|
510
|
+
|
502
511
|
buf->tail->end += nbytes;
|
503
512
|
|
504
513
|
if(len > 0) {
|
@@ -541,7 +550,7 @@ static void buffer_copy(struct buffer *buf, char *str, unsigned len)
|
|
541
550
|
unsigned nbytes;
|
542
551
|
struct buffer_node *node;
|
543
552
|
|
544
|
-
|
553
|
+
node = buf->head;
|
545
554
|
while(node && len > 0) {
|
546
555
|
nbytes = node->end - node->start;
|
547
556
|
if(len < nbytes) nbytes = len;
|
@@ -551,7 +560,7 @@ static void buffer_copy(struct buffer *buf, char *str, unsigned len)
|
|
551
560
|
len -= nbytes;
|
552
561
|
|
553
562
|
if(node->start + nbytes == node->end)
|
554
|
-
|
563
|
+
node = node->next;
|
555
564
|
}
|
556
565
|
}
|
557
566
|
|
@@ -596,7 +605,7 @@ static int buffer_write_to(struct buffer *buf, int fd)
|
|
596
605
|
/* Append data to the front of the buffer */
|
597
606
|
static int buffer_read_from(struct buffer *buf, int fd)
|
598
607
|
{
|
599
|
-
|
608
|
+
int bytes_read, total_bytes_read = 0;
|
600
609
|
unsigned nbytes;
|
601
610
|
|
602
611
|
/* Empty list needs initialized */
|
@@ -605,26 +614,26 @@ static int buffer_read_from(struct buffer *buf, int fd)
|
|
605
614
|
buf->tail = buf->head;
|
606
615
|
}
|
607
616
|
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
617
|
+
do {
|
618
|
+
nbytes = buf->node_size - buf->tail->end;
|
619
|
+
bytes_read = read(fd, buf->tail->data + buf->tail->end, nbytes);
|
620
|
+
|
621
|
+
if(bytes_read < 1) {
|
622
|
+
if(errno != EAGAIN)
|
614
623
|
rb_sys_fail("read");
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
+
|
625
|
+
return total_bytes_read;
|
626
|
+
}
|
627
|
+
|
628
|
+
total_bytes_read += bytes_read;
|
629
|
+
buf->tail->end += nbytes;
|
630
|
+
buf->size += nbytes;
|
631
|
+
|
632
|
+
if(buf->tail->end == buf->node_size) {
|
624
633
|
buf->tail->next = buffer_node_new(buf);
|
625
634
|
buf->tail = buf->tail->next;
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
635
|
+
}
|
636
|
+
} while(bytes_read == nbytes);
|
637
|
+
|
638
|
+
return total_bytes_read;
|
630
639
|
}
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'em-http'
|
data/lib/em-http/client.rb
CHANGED
@@ -84,7 +84,7 @@ module EventMachine
|
|
84
84
|
# Escapes a URI.
|
85
85
|
def escape(s)
|
86
86
|
s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
|
87
|
-
'%'+$1.unpack('H2'*$1.
|
87
|
+
'%'+$1.unpack('H2'*$1.bytesize).join('%').upcase
|
88
88
|
}.tr(' ', '+')
|
89
89
|
end
|
90
90
|
|
@@ -104,7 +104,11 @@ module EventMachine
|
|
104
104
|
# you include port 80 then further redirects will tack on the :80 which is
|
105
105
|
# annoying.
|
106
106
|
def encode_host
|
107
|
-
|
107
|
+
if @uri.port == 80 || @uri.port == 443
|
108
|
+
return @uri.host
|
109
|
+
else
|
110
|
+
@uri.host + ":#{@uri.port}"
|
111
|
+
end
|
108
112
|
end
|
109
113
|
|
110
114
|
def encode_request(method, path, query, uri_query)
|
@@ -313,7 +317,7 @@ module EventMachine
|
|
313
317
|
|
314
318
|
else
|
315
319
|
# Set the Content-Length if body is given
|
316
|
-
head['content-length'] = body.
|
320
|
+
head['content-length'] = body.bytesize if body
|
317
321
|
|
318
322
|
# Set the cookie header if provided
|
319
323
|
if cookie = head.delete('cookie')
|
@@ -473,9 +477,9 @@ module EventMachine
|
|
473
477
|
# correct location header - some servers will incorrectly give a relative URI
|
474
478
|
if @response_header.location
|
475
479
|
begin
|
476
|
-
location =
|
480
|
+
location = URI.parse @response_header.location
|
477
481
|
if location.relative?
|
478
|
-
location = (@uri.
|
482
|
+
location = (@uri.merge location).to_s
|
479
483
|
@response_header[LOCATION] = location
|
480
484
|
end
|
481
485
|
rescue
|
data/lib/em-http/mock.rb
CHANGED
@@ -20,11 +20,15 @@ module EventMachine
|
|
20
20
|
@@registry_count = nil
|
21
21
|
|
22
22
|
def self.reset_counts!
|
23
|
-
@@registry_count = Hash.new
|
23
|
+
@@registry_count = Hash.new do |registry,query|
|
24
|
+
registry[query] = Hash.new{|h,k| h[k] = Hash.new(0)}
|
25
|
+
end
|
24
26
|
end
|
25
27
|
|
26
28
|
def self.reset_registry!
|
27
|
-
@@registry = Hash.new
|
29
|
+
@@registry = Hash.new do |registry,query|
|
30
|
+
registry[query] = Hash.new{|h,k| h[k] = {}}
|
31
|
+
end
|
28
32
|
end
|
29
33
|
|
30
34
|
reset_counts!
|
@@ -40,18 +44,32 @@ module EventMachine
|
|
40
44
|
@@pass_through_requests
|
41
45
|
end
|
42
46
|
|
43
|
-
def self.register(uri, method, data)
|
47
|
+
def self.register(uri, method, headers, data)
|
44
48
|
method = method.to_s.upcase
|
45
|
-
|
49
|
+
headers = headers.to_s
|
50
|
+
@@registry[uri][method][headers] = data
|
46
51
|
end
|
47
52
|
|
48
|
-
def self.register_file(uri, method, file)
|
49
|
-
register(uri, method, File.read(file))
|
53
|
+
def self.register_file(uri, method, headers, file)
|
54
|
+
register(uri, method, headers, File.read(file))
|
50
55
|
end
|
51
56
|
|
52
|
-
def self.count(uri, method)
|
57
|
+
def self.count(uri, method, headers)
|
53
58
|
method = method.to_s.upcase
|
54
|
-
|
59
|
+
headers = headers.to_s
|
60
|
+
@@registry_count[uri][method][headers] rescue 0
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.registered?(query, method, headers)
|
64
|
+
@@registry[query] and @@registry[query][method] and @@registry[query][method][headers]
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.registered_content(query, method, headers)
|
68
|
+
@@registry[query][method][headers]
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.increment_access(query, method, headers)
|
72
|
+
@@registry_count[query][method][headers] += 1
|
55
73
|
end
|
56
74
|
|
57
75
|
alias_method :real_send_request, :send_request
|
@@ -59,15 +77,16 @@ module EventMachine
|
|
59
77
|
protected
|
60
78
|
def send_request(&blk)
|
61
79
|
query = "#{@uri.scheme}://#{@uri.host}:#{@uri.port}#{encode_query(@uri.path, @options[:query], @uri.query)}"
|
62
|
-
|
63
|
-
|
80
|
+
headers = @options[:head].to_s
|
81
|
+
if self.class.registered?(query, @method, headers)
|
82
|
+
self.class.increment_access(query, @method, headers)
|
64
83
|
client = FakeHttpClient.new(nil)
|
65
|
-
client.setup(
|
84
|
+
client.setup(self.class.registered_content(query, @method, headers), @uri)
|
66
85
|
client
|
67
86
|
elsif @@pass_through_requests
|
68
87
|
real_send_request
|
69
88
|
else
|
70
|
-
raise "this request #{query} for method #{@method} isn't registered, and pass_through_requests is current set to false"
|
89
|
+
raise "this request #{query} for method #{@method} with the headers #{@options[:head].inspect} isn't registered, and pass_through_requests is current set to false"
|
71
90
|
end
|
72
91
|
end
|
73
92
|
end
|
data/lib/em-http/multi.rb
CHANGED
@@ -34,10 +34,10 @@ module EventMachine
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def add(conn)
|
37
|
+
@requests.push(conn)
|
38
|
+
|
37
39
|
conn.callback { @responses[:succeeded].push(conn); check_progress }
|
38
40
|
conn.errback { @responses[:failed].push(conn); check_progress }
|
39
|
-
|
40
|
-
@requests.push(conn)
|
41
41
|
end
|
42
42
|
|
43
43
|
protected
|
@@ -48,4 +48,4 @@ module EventMachine
|
|
48
48
|
end
|
49
49
|
|
50
50
|
end
|
51
|
-
end
|
51
|
+
end
|
data/lib/em-http/request.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'base64'
|
2
|
-
require '
|
2
|
+
require 'uri'
|
3
3
|
|
4
4
|
module EventMachine
|
5
5
|
|
@@ -28,7 +28,7 @@ module EventMachine
|
|
28
28
|
|
29
29
|
def initialize(host, headers = {})
|
30
30
|
@headers = headers
|
31
|
-
@uri = host.kind_of?(
|
31
|
+
@uri = host.kind_of?(URI) ? host : URI::parse(host)
|
32
32
|
end
|
33
33
|
|
34
34
|
# Send an HTTP request and consume the response. Supported options:
|
@@ -70,7 +70,7 @@ module EventMachine
|
|
70
70
|
# default connect & inactivity timeouts
|
71
71
|
@options[:timeout] = 10 if not @options[:timeout]
|
72
72
|
|
73
|
-
# Make sure the ports are set as
|
73
|
+
# Make sure the ports are set as URI doesn't
|
74
74
|
# set the port if it isn't there
|
75
75
|
if @uri.scheme == "https"
|
76
76
|
@uri.port ||= 443
|
@@ -109,4 +109,4 @@ module EventMachine
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
112
|
-
end
|
112
|
+
end
|
data/lib/em_buffer.so
ADDED
Binary file
|
Binary file
|
data/spec/mock_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe 'em-http mock' do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should serve a fake http request from a file" do
|
11
|
-
EventMachine::MockHttpRequest.register_file('http://www.google.ca:80/', :get, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
11
|
+
EventMachine::MockHttpRequest.register_file('http://www.google.ca:80/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
12
12
|
EM.run {
|
13
13
|
|
14
14
|
http = EventMachine::MockHttpRequest.new('http://www.google.ca/').get
|
@@ -19,7 +19,7 @@ describe 'em-http mock' do
|
|
19
19
|
}
|
20
20
|
}
|
21
21
|
|
22
|
-
EventMachine::MockHttpRequest.count('http://www.google.ca:80/', :get).should == 1
|
22
|
+
EventMachine::MockHttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should serve a fake http request from a string" do
|
@@ -46,7 +46,7 @@ window._gjp && _gjp()</script><style>td{line-height:.8em;}.gac_m td{line-height:
|
|
46
46
|
function a(){google.timers.load.t.ol=(new Date).getTime();google.report&&google.timers.load.t.xjs&&google.report(google.timers.load,google.kCSI)}if(window.addEventListener)window.addEventListener("load",a,false);else if(window.attachEvent)window.attachEvent("onload",a);google.timers.load.t.prt=(new Date).getTime();
|
47
47
|
})();
|
48
48
|
HEREDOC
|
49
|
-
EventMachine::MockHttpRequest.register('http://www.google.ca:80/', :get, data)
|
49
|
+
EventMachine::MockHttpRequest.register('http://www.google.ca:80/', :get, {}, data)
|
50
50
|
EventMachine.run {
|
51
51
|
|
52
52
|
http = EventMachine::MockHttpRequest.new('http://www.google.ca/').get
|
@@ -57,7 +57,36 @@ function a(){google.timers.load.t.ol=(new Date).getTime();google.report&&google.
|
|
57
57
|
}
|
58
58
|
}
|
59
59
|
|
60
|
-
EventMachine::MockHttpRequest.count('http://www.google.ca:80/', :get).should == 1
|
60
|
+
EventMachine::MockHttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should distinguish the cache by the given headers" do
|
64
|
+
EventMachine::MockHttpRequest.register_file('http://www.google.ca:80/', :get, {:user_agent => 'BERT'}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
65
|
+
EventMachine::MockHttpRequest.register_file('http://www.google.ca:80/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
66
|
+
EM.run {
|
67
|
+
|
68
|
+
http = EventMachine::MockHttpRequest.new('http://www.google.ca/').get
|
69
|
+
http.errback { fail }
|
70
|
+
http.callback {
|
71
|
+
http.response.should == File.read(File.join(File.dirname(__FILE__), 'fixtures', 'google.ca')).split("\n\n", 2).last
|
72
|
+
EventMachine.stop
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
EventMachine::MockHttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
|
77
|
+
EventMachine::MockHttpRequest.count('http://www.google.ca:80/', :get, {:user_agent => 'BERT'}).should == 0
|
78
|
+
|
79
|
+
EM.run {
|
80
|
+
|
81
|
+
http = EventMachine::MockHttpRequest.new('http://www.google.ca/').get({:head => {:user_agent => 'BERT'}})
|
82
|
+
http.errback { fail }
|
83
|
+
http.callback {
|
84
|
+
http.response.should == File.read(File.join(File.dirname(__FILE__), 'fixtures', 'google.ca')).split("\n\n", 2).last
|
85
|
+
EventMachine.stop
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
EventMachine::MockHttpRequest.count('http://www.google.ca:80/', :get, {:user_agent => 'BERT'}).should == 1
|
61
90
|
end
|
62
91
|
|
63
92
|
it "should raise an exception if pass-thru is disabled" do
|
data/spec/multi_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe EventMachine::MultiRequest do
|
|
14
14
|
multi.add(EventMachine::HttpRequest.new('http://0.0.0.0:8083/').get(:timeout => 1))
|
15
15
|
|
16
16
|
multi.callback {
|
17
|
-
# verify
|
17
|
+
# verify successful request
|
18
18
|
multi.responses[:succeeded].size.should == 1
|
19
19
|
multi.responses[:succeeded].first.response.should match(/test/)
|
20
20
|
|
@@ -26,4 +26,26 @@ describe EventMachine::MultiRequest do
|
|
26
26
|
}
|
27
27
|
}
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
|
+
it "should handle multiple mock requests" do
|
31
|
+
EventMachine::MockHttpRequest.register_file('http://127.0.0.1:8080/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
32
|
+
EventMachine::MockHttpRequest.register_file('http://0.0.0.0:8083/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
33
|
+
|
34
|
+
EventMachine.run {
|
35
|
+
|
36
|
+
# create an instance of multi-request handler, and the requests themselves
|
37
|
+
multi = EventMachine::MultiRequest.new
|
38
|
+
|
39
|
+
# add multiple requests to the multi-handler
|
40
|
+
multi.add(EventMachine::MockHttpRequest.new('http://127.0.0.1:8080/').get)
|
41
|
+
multi.add(EventMachine::MockHttpRequest.new('http://0.0.0.0:8083/').get)
|
42
|
+
|
43
|
+
multi.callback {
|
44
|
+
# verify successful request
|
45
|
+
multi.responses[:succeeded].size.should == 2
|
46
|
+
|
47
|
+
EventMachine.stop
|
48
|
+
}
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
data/spec/request_spec.rb
CHANGED
@@ -501,14 +501,14 @@ describe EventMachine::HttpRequest do
|
|
501
501
|
client.should be_kind_of(EventMachine::HttpClient)
|
502
502
|
http.response_header.status.should == 200
|
503
503
|
http.response.should match(/callback_run=yes/)
|
504
|
-
client.normalize_uri.should ==
|
504
|
+
client.normalize_uri.should == URI.parse('http://127.0.0.1:8080/')
|
505
505
|
EventMachine.stop
|
506
506
|
}
|
507
507
|
}
|
508
508
|
end
|
509
509
|
|
510
510
|
it "should retrieve multiple cookies" do
|
511
|
-
EventMachine::MockHttpRequest.register_file('http://www.google.ca:80/', :get, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
511
|
+
EventMachine::MockHttpRequest.register_file('http://www.google.ca:80/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
512
512
|
EventMachine.run {
|
513
513
|
|
514
514
|
http = EventMachine::MockHttpRequest.new('http://www.google.ca/').get
|
@@ -522,7 +522,7 @@ describe EventMachine::HttpRequest do
|
|
522
522
|
}
|
523
523
|
}
|
524
524
|
|
525
|
-
EventMachine::MockHttpRequest.count('http://www.google.ca:80/', :get).should == 1
|
525
|
+
EventMachine::MockHttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
|
526
526
|
end
|
527
527
|
|
528
528
|
context "connections via proxy" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: astro-em-http-request
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ilya Grigorik
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2010-
|
14
|
+
date: 2010-04-07 00:00:00 +02:00
|
15
15
|
default_executable:
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
@@ -24,16 +24,6 @@ dependencies:
|
|
24
24
|
- !ruby/object:Gem::Version
|
25
25
|
version: 0.12.9
|
26
26
|
version:
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: addressable
|
29
|
-
type: :runtime
|
30
|
-
version_requirement:
|
31
|
-
version_requirements: !ruby/object:Gem::Requirement
|
32
|
-
requirements:
|
33
|
-
- - ">="
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
version: 2.0.0
|
36
|
-
version:
|
37
27
|
description: EventMachine based, async HTTP Request interface
|
38
28
|
email: ilya@igvita.com
|
39
29
|
executables: []
|
@@ -62,6 +52,7 @@ files:
|
|
62
52
|
- ext/http11_client/http11_parser.c
|
63
53
|
- ext/http11_client/http11_parser.h
|
64
54
|
- ext/http11_client/http11_parser.rl
|
55
|
+
- lib/em-http-request.rb
|
65
56
|
- lib/em-http.rb
|
66
57
|
- lib/em-http/client.rb
|
67
58
|
- lib/em-http/core_ext/hash.rb
|
@@ -69,6 +60,8 @@ files:
|
|
69
60
|
- lib/em-http/mock.rb
|
70
61
|
- lib/em-http/multi.rb
|
71
62
|
- lib/em-http/request.rb
|
63
|
+
- lib/em_buffer.so
|
64
|
+
- lib/http11_client.so
|
72
65
|
- spec/fixtures/google.ca
|
73
66
|
- spec/hash_spec.rb
|
74
67
|
- spec/helper.rb
|
@@ -90,7 +83,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
83
|
requirements:
|
91
84
|
- - ">="
|
92
85
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
86
|
+
version: 1.8.7
|
94
87
|
version:
|
95
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
89
|
requirements:
|
@@ -108,12 +101,11 @@ summary: EventMachine based, async HTTP Request interface
|
|
108
101
|
test_files:
|
109
102
|
- spec/hash_spec.rb
|
110
103
|
- spec/helper.rb
|
104
|
+
- spec/stub_server.rb
|
105
|
+
- spec/stallion.rb
|
111
106
|
- spec/mock_spec.rb
|
112
107
|
- spec/multi_spec.rb
|
113
108
|
- spec/request_spec.rb
|
114
|
-
- spec/stallion.rb
|
115
|
-
- spec/stub_server.rb
|
116
|
-
- test/another_test.rb
|
117
|
-
- examples/fetch.rb
|
118
109
|
- examples/fibered-http.rb
|
110
|
+
- examples/fetch.rb
|
119
111
|
- examples/oauth-tweet.rb
|
data/test/another_test.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'test/helper'
|
2
|
-
|
3
|
-
describe EventMachine::HttpRequest do
|
4
|
-
|
5
|
-
def failed
|
6
|
-
EventMachine.stop
|
7
|
-
fail
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should return and error if the response side exceeds the :max_bytes option" do
|
11
|
-
EventMachine.run {
|
12
|
-
http = EventMachine::HttpRequest.new("http://updates.sixapart.com/atom-stream.xml").get(:timeout => 10)
|
13
|
-
http.errback { |http|
|
14
|
-
http.errors.should match /Max Connection Duration Exceeded/
|
15
|
-
EventMachine.stop
|
16
|
-
}
|
17
|
-
http.callback { failed }
|
18
|
-
}
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|