em-http-request 0.2.2 → 0.2.3

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.

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