em-http-request 0.3.0 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of em-http-request might be problematic. Click here for more details.

Files changed (44) hide show
  1. data/.gitignore +1 -0
  2. data/Changelog.md +10 -0
  3. data/README.md +43 -160
  4. data/Rakefile +2 -73
  5. data/em-http-request.gemspec +7 -7
  6. data/examples/fetch.rb +30 -30
  7. data/examples/fibered-http.rb +38 -38
  8. data/examples/oauth-tweet.rb +49 -49
  9. data/lib/em-http.rb +4 -6
  10. data/lib/em-http/client.rb +101 -522
  11. data/lib/em-http/http_connection.rb +125 -0
  12. data/lib/em-http/http_encoding.rb +19 -12
  13. data/lib/em-http/http_header.rb +2 -17
  14. data/lib/em-http/http_options.rb +37 -19
  15. data/lib/em-http/request.rb +33 -66
  16. data/lib/em-http/version.rb +2 -2
  17. data/spec/client_spec.rb +575 -0
  18. data/spec/dns_spec.rb +41 -0
  19. data/spec/encoding_spec.rb +6 -6
  20. data/spec/external_spec.rb +99 -0
  21. data/spec/fixtures/google.ca +13 -17
  22. data/spec/helper.rb +17 -8
  23. data/spec/http_proxy_spec.rb +53 -0
  24. data/spec/middleware_spec.rb +114 -0
  25. data/spec/multi_spec.rb +11 -38
  26. data/spec/pipelining_spec.rb +38 -0
  27. data/spec/redirect_spec.rb +114 -0
  28. data/spec/socksify_proxy_spec.rb +24 -0
  29. data/spec/ssl_spec.rb +20 -0
  30. data/spec/stallion.rb +7 -63
  31. metadata +59 -39
  32. data/examples/websocket-handler.rb +0 -28
  33. data/examples/websocket-server.rb +0 -8
  34. data/ext/buffer/em_buffer.c +0 -639
  35. data/ext/buffer/extconf.rb +0 -53
  36. data/ext/http11_client/ext_help.h +0 -14
  37. data/ext/http11_client/extconf.rb +0 -6
  38. data/ext/http11_client/http11_client.c +0 -328
  39. data/ext/http11_client/http11_parser.c +0 -418
  40. data/ext/http11_client/http11_parser.h +0 -48
  41. data/ext/http11_client/http11_parser.rl +0 -170
  42. data/lib/em-http/mock.rb +0 -137
  43. data/spec/mock_spec.rb +0 -166
  44. data/spec/request_spec.rb +0 -1003
@@ -1,48 +0,0 @@
1
- /**
2
- * Copyright (c) 2005 Zed A. Shaw
3
- * You can redistribute it and/or modify it under the same terms as Ruby.
4
- */
5
-
6
- #ifndef http11_parser_h
7
- #define http11_parser_h
8
-
9
- #include <sys/types.h>
10
-
11
- #if defined(_WIN32)
12
- #include <stddef.h>
13
- #endif
14
-
15
- typedef void (*element_cb)(void *data, const char *at, size_t length);
16
- typedef void (*field_cb)(void *data, const char *field, size_t flen, const char *value, size_t vlen);
17
-
18
- typedef struct httpclient_parser {
19
- int cs;
20
- size_t body_start;
21
- int content_len;
22
- size_t nread;
23
- size_t mark;
24
- size_t field_start;
25
- size_t field_len;
26
-
27
- void *data;
28
-
29
- field_cb http_field;
30
- element_cb reason_phrase;
31
- element_cb status_code;
32
- element_cb chunk_size;
33
- element_cb http_version;
34
- element_cb header_done;
35
- element_cb last_chunk;
36
-
37
-
38
- } httpclient_parser;
39
-
40
- int httpclient_parser_init(httpclient_parser *parser);
41
- int httpclient_parser_finish(httpclient_parser *parser);
42
- size_t httpclient_parser_execute(httpclient_parser *parser, const char *data, size_t len, size_t off);
43
- int httpclient_parser_has_error(httpclient_parser *parser);
44
- int httpclient_parser_is_finished(httpclient_parser *parser);
45
-
46
- #define httpclient_parser_nread(parser) (parser)->nread
47
-
48
- #endif
@@ -1,170 +0,0 @@
1
- /**
2
- * Copyright (c) 2005 Zed A. Shaw
3
- * You can redistribute it and/or modify it under the same terms as Ruby.
4
- */
5
-
6
- #include "http11_parser.h"
7
- #include <stdio.h>
8
- #include <assert.h>
9
- #include <stdlib.h>
10
- #include <ctype.h>
11
- #include <string.h>
12
-
13
- #define LEN(AT, FPC) (FPC - buffer - parser->AT)
14
- #define MARK(M,FPC) (parser->M = (FPC) - buffer)
15
- #define PTR_TO(F) (buffer + parser->F)
16
- #define L(M) fprintf(stderr, "" # M "\n");
17
-
18
-
19
- /** machine **/
20
- %%{
21
- machine httpclient_parser;
22
-
23
- action mark {MARK(mark, fpc); }
24
-
25
- action start_field { MARK(field_start, fpc); }
26
-
27
- action write_field {
28
- parser->field_len = LEN(field_start, fpc);
29
- }
30
-
31
- action start_value { MARK(mark, fpc); }
32
-
33
- action write_value {
34
- parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc));
35
- }
36
-
37
- action reason_phrase {
38
- parser->reason_phrase(parser->data, PTR_TO(mark), LEN(mark, fpc));
39
- }
40
-
41
- action status_code {
42
- parser->status_code(parser->data, PTR_TO(mark), LEN(mark, fpc));
43
- }
44
-
45
- action http_version {
46
- parser->http_version(parser->data, PTR_TO(mark), LEN(mark, fpc));
47
- }
48
-
49
- action chunk_size {
50
- parser->chunk_size(parser->data, PTR_TO(mark), LEN(mark, fpc));
51
- }
52
-
53
- action last_chunk {
54
- parser->last_chunk(parser->data, NULL, 0);
55
- }
56
-
57
- action done {
58
- parser->body_start = fpc - buffer + 1;
59
- if(parser->header_done != NULL)
60
- parser->header_done(parser->data, fpc + 1, pe - fpc - 1);
61
- fbreak;
62
- }
63
-
64
- # line endings
65
- CRLF = ("\r\n" | "\n");
66
-
67
- # character types
68
- CTL = (cntrl | 127);
69
- tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
70
-
71
- # elements
72
- token = (ascii -- (CTL | tspecials));
73
-
74
- Reason_Phrase = (any -- CRLF)* >mark %reason_phrase;
75
- Status_Code = digit{3} >mark %status_code;
76
- http_number = (digit+ "." digit+) ;
77
- HTTP_Version = ("HTTP/" http_number) >mark %http_version ;
78
- Status_Line = HTTP_Version " " Status_Code " "? Reason_Phrase :> CRLF;
79
-
80
- field_name = token+ >start_field %write_field;
81
- field_value = any* >start_value %write_value;
82
- message_header = field_name ":" " "* field_value :> CRLF;
83
-
84
- Response = Status_Line (message_header)* (CRLF @done);
85
-
86
- chunk_ext_val = token+;
87
- chunk_ext_name = token+;
88
- chunk_extension = (";" chunk_ext_name >start_field %write_field %start_value ("=" chunk_ext_val >start_value)? %write_value )*;
89
- last_chunk = "0"? chunk_extension :> (CRLF @last_chunk @done);
90
- chunk_size = xdigit+;
91
- chunk = chunk_size >mark %chunk_size chunk_extension space* :> (CRLF @done);
92
- Chunked_Header = (chunk | last_chunk);
93
-
94
- main := Response | Chunked_Header;
95
- }%%
96
-
97
- /** Data **/
98
- %% write data;
99
-
100
- int httpclient_parser_init(httpclient_parser *parser) {
101
- int cs = 0;
102
- %% write init;
103
- parser->cs = cs;
104
- parser->body_start = 0;
105
- parser->content_len = 0;
106
- parser->mark = 0;
107
- parser->nread = 0;
108
- parser->field_len = 0;
109
- parser->field_start = 0;
110
-
111
- return(1);
112
- }
113
-
114
-
115
- /** exec **/
116
- size_t httpclient_parser_execute(httpclient_parser *parser, const char *buffer, size_t len, size_t off) {
117
- const char *p, *pe;
118
- int cs = parser->cs;
119
-
120
- assert(off <= len && "offset past end of buffer");
121
-
122
- p = buffer+off;
123
- pe = buffer+len;
124
-
125
- assert(*pe == '\0' && "pointer does not end on NUL");
126
- assert(pe - p == len - off && "pointers aren't same distance");
127
-
128
-
129
- %% write exec;
130
-
131
- parser->cs = cs;
132
- parser->nread += p - (buffer + off);
133
-
134
- assert(p <= pe && "buffer overflow after parsing execute");
135
- assert(parser->nread <= len && "nread longer than length");
136
- assert(parser->body_start <= len && "body starts after buffer end");
137
- assert(parser->mark < len && "mark is after buffer end");
138
- assert(parser->field_len <= len && "field has length longer than whole buffer");
139
- assert(parser->field_start < len && "field starts after buffer end");
140
-
141
- if(parser->body_start) {
142
- /* final \r\n combo encountered so stop right here */
143
- parser->nread = parser->body_start;
144
- }
145
-
146
- return(parser->nread);
147
- }
148
-
149
- int httpclient_parser_finish(httpclient_parser *parser)
150
- {
151
- int cs = parser->cs;
152
-
153
- parser->cs = cs;
154
-
155
- if (httpclient_parser_has_error(parser) ) {
156
- return -1;
157
- } else if (httpclient_parser_is_finished(parser) ) {
158
- return 1;
159
- } else {
160
- return 0;
161
- }
162
- }
163
-
164
- int httpclient_parser_has_error(httpclient_parser *parser) {
165
- return parser->cs == httpclient_parser_error;
166
- }
167
-
168
- int httpclient_parser_is_finished(httpclient_parser *parser) {
169
- return parser->cs == httpclient_parser_first_final;
170
- }
data/lib/em-http/mock.rb DELETED
@@ -1,137 +0,0 @@
1
- module EventMachine
2
- OriginalHttpRequest = HttpRequest unless const_defined?(:OriginalHttpRequest)
3
-
4
- class MockHttpRequest < EventMachine::HttpRequest
5
-
6
- include HttpEncoding
7
-
8
- class RegisteredRequest < Struct.new(:uri, :method, :headers)
9
- def self.build(uri, method, headers)
10
- new(uri, method.to_s.upcase, headers || {})
11
- end
12
- end
13
-
14
- class FakeHttpClient < EventMachine::HttpClient
15
- attr_writer :response
16
- attr_reader :data
17
- def setup(response, uri)
18
- @uri = uri
19
- if response == :fail
20
- fail(self)
21
- else
22
- if response.respond_to?(:call)
23
- response.call(self)
24
- @state = :body
25
- else
26
- receive_data(response)
27
- end
28
- @state == :body ? succeed(self) : fail(self)
29
- end
30
- end
31
-
32
- def unbind
33
- end
34
- end
35
-
36
- @@registry = Hash.new
37
- @@registry_count = Hash.new{|h,k| h[k] = 0}
38
-
39
- def self.use
40
- activate!
41
- yield
42
- ensure
43
- deactivate!
44
- end
45
-
46
- def self.activate!
47
- EventMachine.send(:remove_const, :HttpRequest)
48
- EventMachine.send(:const_set, :HttpRequest, MockHttpRequest)
49
- end
50
-
51
- def self.deactivate!
52
- EventMachine.send(:remove_const, :HttpRequest)
53
- EventMachine.send(:const_set, :HttpRequest, OriginalHttpRequest)
54
- end
55
-
56
- def self.reset_counts!
57
- @@registry_count.clear
58
- end
59
-
60
- def self.reset_registry!
61
- @@registry.clear
62
- end
63
-
64
- @@pass_through_requests = true
65
-
66
- def self.pass_through_requests=(pass_through_requests)
67
- @@pass_through_requests = pass_through_requests
68
- end
69
-
70
- def self.pass_through_requests
71
- @@pass_through_requests
72
- end
73
-
74
- def self.parse_register_args(args, &proc)
75
- args << proc{|client| proc.call(client); ''} if proc
76
- headers, data = case args.size
77
- when 3
78
- args[2].is_a?(Hash) ?
79
- [args[2][:headers], args[2][:data]] :
80
- [{}, args[2]]
81
- when 4
82
- [args[2], args[3]]
83
- else
84
- raise
85
- end
86
-
87
- url = args[0]
88
- method = args[1]
89
- [headers, url, method, data]
90
- end
91
-
92
- def self.register(*args, &proc)
93
- headers, url, method, data = parse_register_args(args, &proc)
94
- @@registry[RegisteredRequest.build(url, method, headers)] = data
95
- end
96
-
97
- def self.register_file(*args)
98
- headers, url, method, data = parse_register_args(args)
99
- @@registry[RegisteredRequest.build(url, method, headers)] = File.read(data)
100
- end
101
-
102
- def self.count(url, method, headers = {})
103
- @@registry_count[RegisteredRequest.build(url, method, headers)]
104
- end
105
-
106
- def self.registered?(url, method, headers = {})
107
- @@registry.key?(RegisteredRequest.build(url, method, headers))
108
- end
109
-
110
- def self.registered_content(url, method, headers = {})
111
- @@registry[RegisteredRequest.build(url, method, headers)]
112
- end
113
-
114
- def self.increment_access(url, method, headers = {})
115
- @@registry_count[RegisteredRequest.build(url, method, headers)] += 1
116
- end
117
-
118
- alias_method :real_send_request, :send_request
119
-
120
- protected
121
- def send_request(&blk)
122
- query = "#{@req.uri.scheme}://#{@req.uri.host}:#{@req.uri.port}#{encode_query(@req.uri, @req.options[:query])}"
123
- headers = @req.options[:head]
124
- if self.class.registered?(query, @req.method, headers)
125
- self.class.increment_access(query, @req.method, headers)
126
- client = FakeHttpClient.new(nil)
127
- content = self.class.registered_content(query, @req.method, headers)
128
- client.setup(content, @req.uri)
129
- client
130
- elsif @@pass_through_requests
131
- real_send_request
132
- else
133
- raise "this request #{query} for method #{@req.method} with the headers #{@req.options[:head].inspect} isn't registered, and pass_through_requests is current set to false"
134
- end
135
- end
136
- end
137
- end
data/spec/mock_spec.rb DELETED
@@ -1,166 +0,0 @@
1
- require 'helper'
2
-
3
- describe 'em-http mock' do
4
-
5
- before(:all) do
6
- EventMachine::MockHttpRequest.activate!
7
- end
8
-
9
- after(:all) do
10
- EventMachine::MockHttpRequest.deactivate!
11
- end
12
-
13
- before(:each) do
14
- EventMachine::MockHttpRequest.reset_registry!
15
- EventMachine::MockHttpRequest.reset_counts!
16
- end
17
-
18
- it "should serve a fake http request from a proc" do
19
- EventMachine::HttpRequest.register('http://www.google.ca:80/', :get) { |req|
20
- req.response_header.http_status = 200
21
- req.response_header['SOME_WACKY_HEADER'] = 'WACKY_HEADER_VALUE'
22
- req.response = "Well, now this is fun."
23
- }
24
- EM.run {
25
- http = EventMachine::HttpRequest.new('http://www.google.ca/').get
26
- http.errback { fail }
27
- http.callback {
28
- http.response_header.status.should == 200
29
- http.response_header['SOME_WACKY_HEADER'].should == 'WACKY_HEADER_VALUE'
30
- http.response.should == "Well, now this is fun."
31
- EventMachine.stop
32
- }
33
- }
34
-
35
- EventMachine::HttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
36
- end
37
-
38
- it "should serve a fake http request from a proc with raw data" do
39
- EventMachine::HttpRequest.register('http://www.google.ca:80/', :get) { |req|
40
- req.receive_data(File.read(File.join(File.dirname(__FILE__), 'fixtures', 'google.ca')))
41
- }
42
- EM.run {
43
- http = EventMachine::HttpRequest.new('http://www.google.ca/').get
44
- http.errback { fail }
45
- http.callback {
46
- http.response_header.status.should == 200
47
- http.response.should == File.read(File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'), :encoding => 'ISO-8859-1').split("\r\n\r\n", 2).last
48
- http.response.encoding.to_s.should == 'ISO-8859-1'
49
- EventMachine::HttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
50
- EventMachine.stop
51
- }
52
- }
53
- end
54
-
55
- it "should serve a fake http request from a file" do
56
- EventMachine::HttpRequest.register_file('http://www.google.ca:80/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
57
- EM.run {
58
-
59
- http = EventMachine::HttpRequest.new('http://www.google.ca/').get
60
- http.errback { fail }
61
- http.callback {
62
- http.response_header.status.should == 200
63
- http.response.should == File.read(File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'), :encoding => 'ISO-8859-1').split("\r\n\r\n", 2).last
64
- http.response.encoding.to_s.should == 'ISO-8859-1'
65
- EventMachine::HttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
66
- EventMachine.stop
67
- }
68
- }
69
- end
70
-
71
- it "should serve a fake http request from a string" do
72
- data = <<-HEREDOC
73
- HTTP/1.0 200 OK
74
- Date: Mon, 16 Nov 2009 20:39:15 GMT
75
- Expires: -1
76
- Cache-Control: private, max-age=0
77
- Content-Type: text/html; charset=ISO-8859-1
78
- Set-Cookie: PREF=ID=9454187d21c4a6a6:TM=1258403955:LM=1258403955:S=2-mf1n5oV5yAeT9-; expires=Wed, 16-Nov-2011 20:39:15 GMT; path=/; domain=.google.ca
79
- Set-Cookie: NID=28=lvxxVdiBQkCetu_WFaUxLyB7qPlHXS5OdAGYTqge_laVlCKVN8VYYeVBh4bNZiK_Oan2gm8oP9GA-FrZfMPC3ZMHeNq37MG2JH8AIW9LYucU8brOeuggMEbLNNXuiWg4; expires=Tue, 18-May-2010 20:39:15 GMT; path=/; domain=.google.ca; HttpOnly
80
- Server: gws
81
- X-XSS-Protection: 0
82
- X-Cache: MISS from .
83
- Via: 1.0 .:80 (squid)
84
- Connection: close
85
-
86
- <!doctype html><html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Google</title><script>window.google={kEI:"eLgBS4LROqCQedKVvfUL",kEXPI:"17259,21329,21516,22107",kCSI:{e:"17259,21329,21516,22107",ei:"eLgBS4LROqCQedKVvfUL"},kHL:"en",time:function(){return(new Date).getTime()},log:function(b,d,c){var a=new Image,e=google,g=e.lc,f=e.li;a.onerror=(a.onload=(a.onabort=function(){delete g[f]}));g[f]=a;c=c||"/gen_204?atyp=i&ct="+b+"&cad="+d+"&zx="+google.time();a.src=c;e.li=f+1},lc:[],li:0};
87
- window.google.sn="webhp";window.google.timers={load:{t:{start:(new Date).getTime()}}};try{}catch(b){}window.google.jsrt_kill=1;
88
- var _gjwl=location;function _gjuc(){var e=_gjwl.href.indexOf("#");if(e>=0){var a=_gjwl.href.substring(e);if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var f=a.substring(d,b);if(f.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(f=="cad=h")return 0;c=b}_gjwl.href="/search?"+a+"&cad=h";return 1}}}return 0}function _gjp(){!(window._gjwl.hash&&
89
- window._gjuc())&&setTimeout(_gjp,500)};
90
- window._gjp && _gjp()</script><style>td{line-height:.8em;}.gac_m td{line-height:17px;}form{margin-bottom:20px;}body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}em{font-weight:bold;font-style:normal}.lst{font:17px arial,sans-serif;margin-bottom:.2em;vertical-align:bottom;}input{font-family:inherit}.lsb,.gac_sb{font-size:15px;height:1.85em!important;margin:.2em;}#gbar{height:22px}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#guser{padding-bottom:7px !important;text-align:right}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.5em;vertical-align:top}#gbar{float:left}}a.gb1,a.gb3,a.gb4{color:#00c !important}.gb3{text-decoration:none}</style><script>google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/nav_logo7.png'" topmargin=3 marginheight=3><textarea id=csi style=display:none></textarea><div id=gbar><nobr><b class=gb1>Web</b> <a href="http://images.google.ca/imghp?hl=en&tab=wi" class=gb1>Images</a> <a href="http://video.google.ca/?hl=en&tab=wv" class=gb1>Videos</a> <a href="http://maps.google.ca/maps?hl=en&tab=wl" class=gb1>Maps</a> <a href="http://news.google.ca/nwshp?hl=en&tab=wn" class=gb1>News</a> <a href="http://groups.google.ca/grphp?hl=en&tab=wg" class=gb1>Groups</a> <a href="http://mail.google.com/mail/?hl=en&tab=wm" class=gb1>Gmail</a> <a href="http://www.google.ca/intl/en/options/" class=gb3><u>more</u> &raquo;</a></nobr></div><div id=guser width=100%><nobr><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.ca/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNG2Kt7TgMZuV7Fl3FeeTOmTWMvggA" class=gb4>iGoogle</a> | <a href="/preferences?hl=en" class=gb4>Search settings</a> | <a href="https://www.google.com/accounts/Login?hl=en&continue=http://www.google.ca/" class=gb4>Sign in</a></nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><center><br clear=all id=lgpd><img alt="Google" height=110 src="/intl/en_ca/images/logo.gif" width=276 id=logo onload="window.lol&&lol()"><br><br><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%>&nbsp;</td><td align=center nowrap><input name=hl type=hidden value=en><input name=source type=hidden value=hp><input type=hidden name=ie value="ISO-8859-1"><input autocomplete="off" maxlength=2048 name=q size=55 class=lst title="Google Search" value=""><br><input name=btnG type=submit value="Google Search" class=lsb><input name=btnI type=submit value="I'm Feeling Lucky" class=lsb></td><td nowrap width=25% align=left><font size=-2>&nbsp;&nbsp;<a href=/advanced_search?hl=en>Advanced Search</a><br>&nbsp;&nbsp;<a href=/language_tools?hl=en>Language Tools</a></font></td></tr><tr><td align=center colspan=3><font size=-1><span style="text-align:left">Search: <input id=all type=radio name=meta value="" checked><label for=all> the web </label> <input id=cty type=radio name=meta value="cr=countryCA"><label for=cty> pages from Canada </label> </span></font></td></tr></table></form><br><font size=-1>Google.ca offered in: <a href="http://www.google.ca/setprefs?sig=0_XtMil90_yvnNEW8dIglASaHCVhU=&hl=fr">fran?ais</a> </font><br><br><br><font size=-1><a href="/intl/en/ads/">Advertising&nbsp;Programs</a> - <a href="/services/">Business Solutions</a> - <a href="/intl/en/about.html">About Google</a> - <a href="http://www.google.com/ncr">Go to Google.com</a></font><p><font size=-2>&copy;2009 - <a href="/intl/en/privacy.html">Privacy</a></font></p></center><div id=xjsd></div><div id=xjsi><script>if(google.y)google.y.first=[];if(google.y)google.y.first=[];google.dstr=[];google.rein=[];window.setTimeout(function(){var a=document.createElement("script");a.src="/extern_js/f/CgJlbhICY2EgACswCjhBQB0sKzAOOAksKzAYOAQsKzAlOMmIASwrMCY4BywrMCc4Aiw/n_sssePDGvc.js";(document.getElementById("xjsd")||document.body).appendChild(a)},0);
91
- ;google.y.first.push(function(){google.ac.b=true;google.ac.i(document.f,document.f.q,'','')});google.xjs&&google.j&&google.j.xi&&google.j.xi()</script></div><script>(function(){
92
- 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();
93
- })();
94
- HEREDOC
95
- EventMachine::HttpRequest.register('http://www.google.ca:80/', :get, {}, data)
96
- EventMachine.run {
97
-
98
- http = EventMachine::HttpRequest.new('http://www.google.ca/').get
99
- http.errback { fail }
100
- http.callback {
101
- http.response.should == data.split("\n\n", 2).last
102
- EventMachine::HttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
103
- EventMachine.stop
104
- }
105
- }
106
-
107
- end
108
-
109
- it "should serve a fake failing http request" do
110
- EventMachine::HttpRequest.register('http://www.google.ca:80/', :get, {}, :fail)
111
- error = false
112
-
113
- EventMachine.run {
114
- http = EventMachine::HttpRequest.new('http://www.google.ca/').get
115
- http.callback {
116
- EventMachine.stop
117
- fail
118
- }
119
- http.errback {
120
- EventMachine::HttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
121
- EventMachine.stop
122
- }
123
- }
124
-
125
- end
126
-
127
- it "should distinguish the cache by the given headers" do
128
- EventMachine::HttpRequest.register_file('http://www.google.ca:80/', :get, {:user_agent => 'BERT'}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
129
- EventMachine::HttpRequest.register_file('http://www.google.ca:80/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
130
- EM.run {
131
- http = EventMachine::HttpRequest.new('http://www.google.ca/').get
132
- http.errback { fail }
133
- http.callback {
134
- http.response_header.status.should == 200
135
- http.response.should == File.read(File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'), :encoding => 'ISO-8859-1').split("\r\n\r\n", 2).last
136
- http.response.encoding.to_s.should == 'ISO-8859-1'
137
- EventMachine::HttpRequest.count('http://www.google.ca:80/', :get, {}).should == 1
138
- EventMachine::HttpRequest.count('http://www.google.ca:80/', :get, {:user_agent => 'BERT'}).should == 0
139
- EventMachine.stop
140
- }
141
- }
142
-
143
- EM.run {
144
- http = EventMachine::HttpRequest.new('http://www.google.ca/').get({:head => {:user_agent => 'BERT'}})
145
- http.errback { fail }
146
- http.callback {
147
- http.response_header.status.should == 200
148
- http.response.should == File.read(File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'), :encoding => 'ISO-8859-1').split("\r\n\r\n", 2).last
149
- http.response.encoding.to_s.should == 'ISO-8859-1'
150
- EventMachine::HttpRequest.count('http://www.google.ca:80/', :get, {:user_agent => 'BERT'}).should == 1
151
- EventMachine.stop
152
- }
153
- }
154
-
155
- end
156
-
157
- it "should raise an exception if pass-thru is disabled" do
158
- EventMachine::HttpRequest.pass_through_requests = false
159
- EventMachine.run {
160
- proc {
161
- http = EventMachine::HttpRequest.new('http://www.google.ca/').get
162
- }.should raise_error
163
- EventMachine.stop
164
- }
165
- end
166
- end