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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

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