em-http-request 0.2.2 → 0.2.3

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/Rakefile CHANGED
@@ -36,6 +36,7 @@ end
36
36
 
37
37
  task :spec do
38
38
  sh 'spec test/test_*.rb'
39
+ sh 'spec test/mock/test_*.rb'
39
40
  end
40
41
 
41
42
  def make(makedir)
@@ -96,6 +97,7 @@ begin
96
97
  gemspec.add_dependency('eventmachine', '>= 0.12.9')
97
98
  gemspec.add_dependency('addressable', '>= 2.0.0')
98
99
  gemspec.rubyforge_project = "em-http-request"
100
+ gemspec.files = FileList["[A-Z]*", "{lib,test,ext}/**/*"]
99
101
  end
100
102
 
101
103
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.2.3
@@ -0,0 +1,157 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /opt/local/lib/ruby/1.8/i686-darwin10
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ exec_prefix = $(prefix)
11
+ prefix = $(DESTDIR)/opt/local
12
+ sharedstatedir = $(prefix)/com
13
+ mandir = $(DESTDIR)/opt/local/share/man
14
+ psdir = $(docdir)
15
+ oldincludedir = $(DESTDIR)/usr/include
16
+ localedir = $(datarootdir)/locale
17
+ bindir = $(exec_prefix)/bin
18
+ libexecdir = $(exec_prefix)/libexec
19
+ sitedir = $(libdir)/ruby/site_ruby
20
+ htmldir = $(docdir)
21
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
22
+ includedir = $(prefix)/include
23
+ infodir = $(datarootdir)/info
24
+ vendorlibdir = $(vendordir)/$(ruby_version)
25
+ sysconfdir = $(prefix)/etc
26
+ libdir = $(exec_prefix)/lib
27
+ sbindir = $(exec_prefix)/sbin
28
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
29
+ docdir = $(datarootdir)/doc/$(PACKAGE)
30
+ dvidir = $(docdir)
31
+ vendordir = $(DESTDIR)/opt/local/lib/ruby/vendor_ruby
32
+ datarootdir = $(prefix)/share
33
+ pdfdir = $(docdir)
34
+ archdir = $(rubylibdir)/$(arch)
35
+ sitearchdir = $(sitelibdir)/$(sitearch)
36
+ datadir = $(datarootdir)
37
+ localstatedir = $(prefix)/var
38
+ sitelibdir = $(sitedir)/$(ruby_version)
39
+
40
+ CC = /usr/bin/gcc-4.2
41
+ LIBRUBY = $(LIBRUBY_SO)
42
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
43
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
44
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
45
+
46
+ RUBY_EXTCONF_H =
47
+ CFLAGS = -fno-common -O2 -arch x86_64 -fno-common -pipe -fno-common $(cflags) -arch x86_64
48
+ INCFLAGS = -I. -I. -I/opt/local/lib/ruby/1.8/i686-darwin10 -I.
49
+ DEFS =
50
+ CPPFLAGS = -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -I/opt/local/include
51
+ CXXFLAGS = $(CFLAGS)
52
+ ldflags = -L. -L/opt/local/lib
53
+ dldflags =
54
+ archflag = -arch x86_64
55
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
56
+ LDSHARED = $(CC) -dynamic -bundle -undefined suppress -flat_namespace
57
+ AR = ar
58
+ EXEEXT =
59
+
60
+ RUBY_INSTALL_NAME = ruby
61
+ RUBY_SO_NAME = ruby
62
+ arch = i686-darwin10
63
+ sitearch = i686-darwin10
64
+ ruby_version = 1.8
65
+ ruby = /opt/local/bin/ruby
66
+ RUBY = $(ruby)
67
+ RM = rm -f
68
+ MAKEDIRS = mkdir -p
69
+ INSTALL = /usr/bin/install -c
70
+ INSTALL_PROG = $(INSTALL) -m 0755
71
+ INSTALL_DATA = $(INSTALL) -m 644
72
+ COPY = cp
73
+
74
+ #### End of system configuration section. ####
75
+
76
+ preload =
77
+
78
+ libpath = . $(libdir)
79
+ LIBPATH = -L. -L$(libdir)
80
+ DEFFILE =
81
+
82
+ CLEANFILES = mkmf.log
83
+ DISTCLEANFILES =
84
+
85
+ extout =
86
+ extout_prefix =
87
+ target_prefix =
88
+ LOCAL_LIBS =
89
+ LIBS = $(LIBRUBYARG_SHARED) -lc -lpthread -ldl -lobjc
90
+ SRCS = http11_client.c http11_parser.c
91
+ OBJS = http11_client.o http11_parser.o
92
+ TARGET = http11_client
93
+ DLLIB = $(TARGET).bundle
94
+ EXTSTATIC =
95
+ STATIC_LIB =
96
+
97
+ BINDIR = $(bindir)
98
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
99
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
100
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
101
+
102
+ TARGET_SO = $(DLLIB)
103
+ CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
104
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
105
+
106
+ all: $(DLLIB)
107
+ static: $(STATIC_LIB)
108
+
109
+ clean:
110
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
111
+
112
+ distclean: clean
113
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
114
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
115
+
116
+ realclean: distclean
117
+ install: install-so install-rb
118
+
119
+ install-so: $(RUBYARCHDIR)
120
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
121
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
122
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
123
+ install-rb: pre-install-rb install-rb-default
124
+ install-rb-default: pre-install-rb-default
125
+ pre-install-rb: Makefile
126
+ pre-install-rb-default: Makefile
127
+ $(RUBYARCHDIR):
128
+ $(MAKEDIRS) $@
129
+
130
+ site-install: site-install-so site-install-rb
131
+ site-install-so: install-so
132
+ site-install-rb: install-rb
133
+
134
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
135
+
136
+ .cc.o:
137
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
138
+
139
+ .cxx.o:
140
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
141
+
142
+ .cpp.o:
143
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
144
+
145
+ .C.o:
146
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
147
+
148
+ .c.o:
149
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
150
+
151
+ $(DLLIB): $(OBJS) Makefile
152
+ @-$(RM) $@
153
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
154
+
155
+
156
+
157
+ $(OBJS): ruby.h defines.h
@@ -3,10 +3,8 @@
3
3
  # You can redistribute this under the terms of the Ruby license
4
4
  # See file LICENSE for details
5
5
  #++
6
-
7
- require 'rubygems'
8
- require 'eventmachine'
9
-
6
+
7
+ require 'eventmachine'
10
8
 
11
9
  require File.dirname(__FILE__) + '/http11_client'
12
10
  require File.dirname(__FILE__) + '/em_buffer'
@@ -15,4 +13,4 @@ require File.dirname(__FILE__) + '/em-http/core_ext/hash'
15
13
  require File.dirname(__FILE__) + '/em-http/client'
16
14
  require File.dirname(__FILE__) + '/em-http/multi'
17
15
  require File.dirname(__FILE__) + '/em-http/request'
18
- require File.dirname(__FILE__) + '/em-http/decoders'
16
+ require File.dirname(__FILE__) + '/em-http/decoders'
@@ -108,18 +108,18 @@ module EventMachine
108
108
  @uri.host + (@uri.port != 80 ? ":#{@uri.port}" : "")
109
109
  end
110
110
 
111
- def encode_request(method, path, query)
112
- HTTP_REQUEST_HEADER % [method.to_s.upcase, encode_query(path, query)]
111
+ def encode_request(method, path, query, uri_query)
112
+ HTTP_REQUEST_HEADER % [method.to_s.upcase, encode_query(path, query, uri_query)]
113
113
  end
114
114
 
115
- def encode_query(path, query)
115
+ def encode_query(path, query, uri_query)
116
116
  encoded_query = if query.kind_of?(Hash)
117
117
  query.map { |k, v| encode_param(k, v) }.join('&')
118
118
  else
119
119
  query.to_s
120
120
  end
121
- if !@uri.query.to_s.empty?
122
- encoded_query = [encoded_query, @uri.query].reject {|part| part.empty?}.join("&")
121
+ if !uri_query.to_s.empty?
122
+ encoded_query = [encoded_query, uri_query].reject {|part| part.empty?}.join("&")
123
123
  end
124
124
  return path if encoded_query.to_s.empty?
125
125
  "#{path}?#{encoded_query}"
@@ -262,7 +262,7 @@ module EventMachine
262
262
  end
263
263
 
264
264
  # Build the request
265
- request_header = encode_request(@method, @uri.path, query)
265
+ request_header = encode_request(@method, @uri.path, query, @uri.query)
266
266
  request_header << encode_headers(head)
267
267
  request_header << CRLF
268
268
 
@@ -367,9 +367,9 @@ module EventMachine
367
367
  # correct location header - some servers will incorrectly give a relative URI
368
368
  if @response_header.location
369
369
  begin
370
- location = URI.parse @response_header.location
370
+ location = Addressable::URI.parse @response_header.location
371
371
  if location.relative?
372
- location = (@uri.merge location).to_s
372
+ location = (@uri.join location).to_s
373
373
  @response_header[LOCATION] = location
374
374
  end
375
375
  rescue
@@ -0,0 +1,73 @@
1
+ module EventMachine
2
+ class HttpRequest
3
+
4
+ include HttpEncoding
5
+
6
+ class FakeHttpClient < EventMachine::HttpClient
7
+
8
+ def setup(response)
9
+ receive_data(response)
10
+ succeed(self)
11
+ end
12
+
13
+ def unbind
14
+ end
15
+
16
+ end
17
+
18
+ @@registry = nil
19
+ @@registry_count = nil
20
+
21
+ def self.reset_counts!
22
+ @@registry_count = Hash.new{|h,k| h[k] = Hash.new(0)}
23
+ end
24
+
25
+ def self.reset_registry!
26
+ @@registry = Hash.new{|h,k| h[k] = {}}
27
+ end
28
+
29
+ reset_counts!
30
+ reset_registry!
31
+
32
+ @@pass_through_requests = true
33
+
34
+ def self.pass_through_requests=(pass_through_requests)
35
+ @@pass_through_requests = pass_through_requests
36
+ end
37
+
38
+ def self.pass_through_requests
39
+ @@pass_through_requests
40
+ end
41
+
42
+ def self.register(uri, method, data)
43
+ method = method.to_s.upcase
44
+ @@registry[uri][method] = data
45
+ end
46
+
47
+ def self.register_file(uri, method, file)
48
+ register(uri, method, File.read(file))
49
+ end
50
+
51
+ def self.count(uri, method)
52
+ method = method.to_s.upcase
53
+ @@registry_count[uri][method]
54
+ end
55
+
56
+ alias_method :real_send_request, :send_request
57
+
58
+ protected
59
+ def send_request
60
+ query = "#{@uri.scheme}://#{@uri.host}:#{@uri.port}#{encode_query(@uri.path, @options[:query], @uri.query)}"
61
+ if s = @@registry[query] and fake = s[@method]
62
+ @@registry_count[query][@method] += 1
63
+ client = FakeHttpClient.new(nil)
64
+ client.setup(fake)
65
+ client
66
+ elsif @@pass_through_requests
67
+ real_send_request
68
+ else
69
+ raise "this request #{query} for method #{@method} isn't registered, and pass_through_requests is current set to false"
70
+ end
71
+ end
72
+ end
73
+ end
@@ -24,6 +24,8 @@ module EventMachine
24
24
  #
25
25
 
26
26
  class HttpRequest
27
+
28
+ attr_reader :options, :method
27
29
 
28
30
  def initialize(host, headers = {})
29
31
  @headers = headers
@@ -45,35 +47,42 @@ module EventMachine
45
47
  # Called for each response body chunk (you may assume HTTP 200
46
48
  # OK then)
47
49
  #
48
-
49
- def get options = {}; send_request(:get, options); end
50
- def head options = {}; send_request(:head, options); end
51
- def post options = {}; send_request(:post, options); end
50
+
51
+ def get options = {}; setup_request(:get, options); end
52
+ def head options = {}; setup_request(:head, options); end
53
+ def delete options = {}; setup_request(:delete, options); end
54
+ def put options = {}; setup_request(:put, options); end
55
+ def post options = {}; setup_request(:post, options); end
52
56
 
53
57
  protected
54
58
 
55
- def send_request(method, options)
59
+ def setup_request(method, options)
56
60
  raise ArgumentError, "invalid request path" unless /^\// === @uri.path
57
61
 
62
+ @options = options
63
+
58
64
  # default connect & inactivity timeouts
59
- options[:timeout] = 5 if not options[:timeout]
65
+ @options[:timeout] = 5 if not @options[:timeout]
60
66
 
61
67
  # Make sure the port is set as Addressable::URI doesn't set the
62
68
  # port if it isn't there.
63
- @uri.port = @uri.port ? @uri.port : 80
64
- method = method.to_s.upcase
69
+ @uri.port ||= 80
70
+ @method = method.to_s.upcase
71
+ send_request
72
+ end
73
+
74
+ def send_request
65
75
  begin
66
76
  EventMachine.connect(@uri.host, @uri.port, EventMachine::HttpClient) { |c|
67
77
  c.uri = @uri
68
- c.method = method
69
- c.options = options
70
- c.comm_inactivity_timeout = options[:timeout]
71
- c.pending_connect_timeout = options[:timeout]
78
+ c.method = @method
79
+ c.options = @options
80
+ c.comm_inactivity_timeout = @options[:timeout]
81
+ c.pending_connect_timeout = @options[:timeout]
72
82
  }
73
- rescue RuntimeError => e
74
- raise e unless e.message == "no connection"
83
+ rescue EventMachine::ConnectionError => e
75
84
  conn = EventMachine::HttpClient.new("")
76
- conn.on_error("no connection", true)
85
+ conn.on_error(e.message, true)
77
86
  conn
78
87
  end
79
88
  end
@@ -0,0 +1,21 @@
1
+ HTTP/1.0 200 OK
2
+ Date: Mon, 16 Nov 2009 20:39:15 GMT
3
+ Expires: -1
4
+ Cache-Control: private, max-age=0
5
+ Content-Type: text/html; charset=ISO-8859-1
6
+ 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
7
+ Set-Cookie: NID=28=lvxxVdiBQkCetu_WFaUxLyB7qPlHXS5OdAGYTqge_laVlCKVN8VYYeVBh4bNZiK_Oan2gm8oP9GA-FrZfMPC3ZMHeNq37MG2JH8AIW9LYucU8brOeuggMEbLNNXuiWg4; expires=Tue, 18-May-2010 20:39:15 GMT; path=/; domain=.google.ca; HttpOnly
8
+ Server: gws
9
+ X-XSS-Protection: 0
10
+ X-Cache: MISS from .
11
+ Via: 1.0 .:80 (squid)
12
+ Connection: close
13
+
14
+ <!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};
15
+ window.google.sn="webhp";window.google.timers={load:{t:{start:(new Date).getTime()}}};try{}catch(b){}window.google.jsrt_kill=1;
16
+ 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&&
17
+ window._gjuc())&&setTimeout(_gjp,500)};
18
+ 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);
19
+ ;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(){
20
+ 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();
21
+ })();
@@ -0,0 +1,83 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'pp'
4
+
5
+ require 'lib/em-http'
6
+ require 'lib/em-http/mock'
7
+
8
+ describe 'em-http mock' do
9
+
10
+ before(:each) do
11
+ EM::HttpRequest.reset_registry!
12
+ EM::HttpRequest.reset_counts!
13
+ end
14
+
15
+ it "should serve a fake http request from a file" do
16
+ EM::HttpRequest.register_file('http://www.google.ca:80/', :get, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
17
+ EM.run do
18
+ http = EM::HttpRequest.new('http://www.google.ca/').get
19
+ http.callback do
20
+ http.response.should == File.read(File.join(File.dirname(__FILE__), 'fixtures', 'google.ca')).split("\n\n", 2).last
21
+ EM.stop
22
+ end
23
+ http.errback do
24
+ fail
25
+ EM.stop
26
+ end
27
+ end
28
+
29
+ EM::HttpRequest.count('http://www.google.ca:80/', :get).should == 1
30
+ end
31
+
32
+ it "should serve a fake http request from a string" do
33
+ data = <<-HEREDOC
34
+ HTTP/1.0 200 OK
35
+ Date: Mon, 16 Nov 2009 20:39:15 GMT
36
+ Expires: -1
37
+ Cache-Control: private, max-age=0
38
+ Content-Type: text/html; charset=ISO-8859-1
39
+ 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
40
+ Set-Cookie: NID=28=lvxxVdiBQkCetu_WFaUxLyB7qPlHXS5OdAGYTqge_laVlCKVN8VYYeVBh4bNZiK_Oan2gm8oP9GA-FrZfMPC3ZMHeNq37MG2JH8AIW9LYucU8brOeuggMEbLNNXuiWg4; expires=Tue, 18-May-2010 20:39:15 GMT; path=/; domain=.google.ca; HttpOnly
41
+ Server: gws
42
+ X-XSS-Protection: 0
43
+ X-Cache: MISS from .
44
+ Via: 1.0 .:80 (squid)
45
+ Connection: close
46
+
47
+ <!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};
48
+ window.google.sn="webhp";window.google.timers={load:{t:{start:(new Date).getTime()}}};try{}catch(b){}window.google.jsrt_kill=1;
49
+ 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&&
50
+ window._gjuc())&&setTimeout(_gjp,500)};
51
+ 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);
52
+ ;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(){
53
+ 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();
54
+ })();
55
+ HEREDOC
56
+ EM::HttpRequest.register('http://www.google.ca:80/', :get, data)
57
+ EM.run do
58
+ http = EM::HttpRequest.new('http://www.google.ca/').get
59
+ http.callback do
60
+ http.response.should == data.split("\n\n", 2).last
61
+ EM.stop
62
+ end
63
+ http.errback do
64
+ fail
65
+ EM.stop
66
+ end
67
+ end
68
+
69
+ EM::HttpRequest.count('http://www.google.ca:80/', :get).should == 1
70
+ end
71
+
72
+ it "should raise an exception if pass-thru is disabled" do
73
+ EM::HttpRequest.pass_through_requests = false
74
+ EM.run do
75
+ proc {
76
+ http = EM::HttpRequest.new('http://www.google.ca/').get
77
+ }.should raise_error
78
+ EM.stop
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -85,7 +85,13 @@ Stallion.saddle :spec do |stable|
85
85
 
86
86
  elsif stable.request.head?
87
87
  stable.response.status = 200
88
-
88
+
89
+ elsif stable.request.delete?
90
+ stable.response.status = 200
91
+
92
+ elsif stable.request.put?
93
+ stable.response.write stable.request.body.read
94
+
89
95
  elsif stable.request.post?
90
96
  if stable.request.path_info == '/echo_content_type'
91
97
  stable.response.write stable.request.env["CONTENT_TYPE"]
@@ -130,6 +136,10 @@ Stallion.saddle :spec do |stable|
130
136
  stable.response.status = 401
131
137
  end
132
138
 
139
+ elsif stable.request.path_info == '/relative-location'
140
+ stable.response.status = 301
141
+ stable.response["Location"] = '/forwarded'
142
+
133
143
  elsif
134
144
  stable.response.write 'Hello, World!'
135
145
  end
@@ -11,7 +11,7 @@ describe EventMachine::MultiRequest do
11
11
 
12
12
  # add multiple requests to the multi-handler
13
13
  multi.add(EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get(:query => {:q => 'test'}))
14
- multi.add(EventMachine::HttpRequest.new('http://0.0.0.0/').get(:timeout => 1))
14
+ multi.add(EventMachine::HttpRequest.new('http://0.0.0.0:8081/').get(:timeout => 1))
15
15
 
16
16
  multi.callback {
17
17
  # verify successfull request
@@ -17,7 +17,7 @@ describe EventMachine::HttpRequest do
17
17
  http.response_header.status.should == 0
18
18
  EventMachine.stop
19
19
  }
20
- }
20
+ }
21
21
  end
22
22
 
23
23
  it "should fail GET on invalid host" do
@@ -26,7 +26,7 @@ describe EventMachine::HttpRequest do
26
26
  http.callback { failed }
27
27
  http.errback {
28
28
  http.response_header.status.should == 0
29
- http.errors.should match(/no connection/)
29
+ http.errors.should match(/unable to resolve server address/)
30
30
  EventMachine.stop
31
31
  }
32
32
  }
@@ -82,6 +82,21 @@ describe EventMachine::HttpRequest do
82
82
  }
83
83
  }
84
84
  end
85
+
86
+ # should be no different than a GET
87
+ it "should perform successfull DELETE with a URI passed as argument" do
88
+ EventMachine.run {
89
+ uri = URI.parse('http://127.0.0.1:8080/')
90
+ http = EventMachine::HttpRequest.new(uri).delete
91
+
92
+ http.errback { failed }
93
+ http.callback {
94
+ http.response_header.status.should == 200
95
+ http.response.should == ""
96
+ EventMachine.stop
97
+ }
98
+ }
99
+ end
85
100
 
86
101
  it "should return 404 on invalid path" do
87
102
  EventMachine.run {
@@ -134,6 +149,20 @@ describe EventMachine::HttpRequest do
134
149
  }
135
150
  end
136
151
 
152
+ # should be no different than a POST
153
+ it "should perform successfull PUT" do
154
+ EventMachine.run {
155
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').put :body => "data"
156
+
157
+ http.errback { failed }
158
+ http.callback {
159
+ http.response_header.status.should == 200
160
+ http.response.should match(/data/)
161
+ EventMachine.stop
162
+ }
163
+ }
164
+ end
165
+
137
166
  it "should perform successfull POST" do
138
167
  EventMachine.run {
139
168
  http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => "data"
@@ -432,4 +461,16 @@ describe EventMachine::HttpRequest do
432
461
  }
433
462
  end
434
463
  end
464
+
465
+ it "should complete a Location: with a relative path" do
466
+ EventMachine.run {
467
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/relative-location').get
468
+
469
+ http.errback { failed }
470
+ http.callback {
471
+ http.response_header['LOCATION'].should == 'http://127.0.0.1:8080/forwarded'
472
+ EventMachine.stop
473
+ }
474
+ }
475
+ end
435
476
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-http-request
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ilya Grigorik
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-29 00:00:00 -04:00
12
+ date: 2009-12-01 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -43,17 +43,16 @@ extra_rdoc_files:
43
43
  - LICENSE
44
44
  - README.rdoc
45
45
  files:
46
- - .gitignore
47
46
  - LICENSE
48
47
  - README.rdoc
49
48
  - Rakefile
50
49
  - VERSION
51
- - examples/fetch.rb
52
- - examples/fibered-http.rb
53
50
  - ext/buffer/em_buffer.c
54
51
  - ext/buffer/extconf.rb
52
+ - ext/http11_client/Makefile
55
53
  - ext/http11_client/ext_help.h
56
54
  - ext/http11_client/extconf.rb
55
+ - ext/http11_client/http11_client.bundle
57
56
  - ext/http11_client/http11_client.c
58
57
  - ext/http11_client/http11_parser.c
59
58
  - ext/http11_client/http11_parser.h
@@ -62,9 +61,12 @@ files:
62
61
  - lib/em-http/client.rb
63
62
  - lib/em-http/core_ext/hash.rb
64
63
  - lib/em-http/decoders.rb
64
+ - lib/em-http/mock.rb
65
65
  - lib/em-http/multi.rb
66
66
  - lib/em-http/request.rb
67
67
  - test/helper.rb
68
+ - test/mock/fixtures/google.ca
69
+ - test/mock/test_mock.rb
68
70
  - test/stallion.rb
69
71
  - test/stub_server.rb
70
72
  - test/test_hash.rb
@@ -100,6 +102,7 @@ specification_version: 3
100
102
  summary: EventMachine based, async HTTP Request interface
101
103
  test_files:
102
104
  - test/helper.rb
105
+ - test/mock/test_mock.rb
103
106
  - test/stallion.rb
104
107
  - test/stub_server.rb
105
108
  - test/test_hash.rb
data/.gitignore DELETED
@@ -1,4 +0,0 @@
1
- *.bundle
2
- *.o
3
- Makefile
4
- mkmf.log