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.
- data/.gitignore +1 -0
- data/Changelog.md +10 -0
- data/README.md +43 -160
- data/Rakefile +2 -73
- data/em-http-request.gemspec +7 -7
- data/examples/fetch.rb +30 -30
- data/examples/fibered-http.rb +38 -38
- data/examples/oauth-tweet.rb +49 -49
- data/lib/em-http.rb +4 -6
- data/lib/em-http/client.rb +101 -522
- data/lib/em-http/http_connection.rb +125 -0
- data/lib/em-http/http_encoding.rb +19 -12
- data/lib/em-http/http_header.rb +2 -17
- data/lib/em-http/http_options.rb +37 -19
- data/lib/em-http/request.rb +33 -66
- data/lib/em-http/version.rb +2 -2
- data/spec/client_spec.rb +575 -0
- data/spec/dns_spec.rb +41 -0
- data/spec/encoding_spec.rb +6 -6
- data/spec/external_spec.rb +99 -0
- data/spec/fixtures/google.ca +13 -17
- data/spec/helper.rb +17 -8
- data/spec/http_proxy_spec.rb +53 -0
- data/spec/middleware_spec.rb +114 -0
- data/spec/multi_spec.rb +11 -38
- data/spec/pipelining_spec.rb +38 -0
- data/spec/redirect_spec.rb +114 -0
- data/spec/socksify_proxy_spec.rb +24 -0
- data/spec/ssl_spec.rb +20 -0
- data/spec/stallion.rb +7 -63
- metadata +59 -39
- data/examples/websocket-handler.rb +0 -28
- data/examples/websocket-server.rb +0 -8
- data/ext/buffer/em_buffer.c +0 -639
- data/ext/buffer/extconf.rb +0 -53
- data/ext/http11_client/ext_help.h +0 -14
- data/ext/http11_client/extconf.rb +0 -6
- data/ext/http11_client/http11_client.c +0 -328
- data/ext/http11_client/http11_parser.c +0 -418
- data/ext/http11_client/http11_parser.h +0 -48
- data/ext/http11_client/http11_parser.rl +0 -170
- data/lib/em-http/mock.rb +0 -137
- data/spec/mock_spec.rb +0 -166
- 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> »</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%> </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> <a href=/advanced_search?hl=en>Advanced Search</a><br> <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 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>©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
|