simplehttp 0.1.1 → 0.1.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.
- data/AUTHORS +1 -0
- data/CHANGELOG +4 -0
- data/README +2 -2
- data/TODO +2 -0
- data/lib/simple_http.rb +7 -372
- data/lib/simplehttp.rb +450 -0
- data/test/http_test.rb +6 -2
- data/test/http_test_server.rb +1 -0
- metadata +41 -33
data/AUTHORS
CHANGED
data/CHANGELOG
CHANGED
data/README
CHANGED
@@ -7,7 +7,7 @@ INSTALLATION
|
|
7
7
|
|
8
8
|
* Using +gem+
|
9
9
|
|
10
|
-
gem install
|
10
|
+
gem install simplehttp
|
11
11
|
|
12
12
|
* Using +setup.rb+
|
13
13
|
|
@@ -23,7 +23,7 @@ FEATURES / USAGE
|
|
23
23
|
|
24
24
|
* Require the lib:
|
25
25
|
|
26
|
-
require '
|
26
|
+
require 'simplehttp'
|
27
27
|
|
28
28
|
* No fuss one line GET and POST requests:
|
29
29
|
|
data/TODO
CHANGED
data/lib/simple_http.rb
CHANGED
@@ -1,372 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# Wrapper around ruby's standard net/http classes. Currently, only GET
|
9
|
-
# and POST https methods are supported. `SimpleHttp` provides class
|
10
|
-
# methods `get` and `post` to handle basic functionality. In case more
|
11
|
-
# complicated requests need to be made or default settings need to be
|
12
|
-
# overriden, it's possible to instantiate `SimpleHttp` and use instance
|
13
|
-
# methods `get` and `put`.
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# Features:
|
17
|
-
#
|
18
|
-
# * Handles Redirects automatically
|
19
|
-
# * Proxy used transparently if http_proxy environment variable is
|
20
|
-
# set.
|
21
|
-
# * SSL handled automatically
|
22
|
-
# * fault tolerant uri, e.g. all of these would work:
|
23
|
-
# "www.example.com", "www.example.com/", "http://www.example.com"
|
24
|
-
#
|
25
|
-
# Some usage examples:
|
26
|
-
# # plain GET (using class methods)
|
27
|
-
# SimpleHttp.get "www.example.com"
|
28
|
-
#
|
29
|
-
# # POST using the instance methods
|
30
|
-
# uri = URI.parse "https://www.example.com/index.html"
|
31
|
-
# sh = SimpleHttp uri
|
32
|
-
# sh.set_proxy "my.proxy", "8080"
|
33
|
-
# sh.post {"query" => "query_data"}
|
34
|
-
#
|
35
|
-
# # POST using class methods.
|
36
|
-
# binaryData = getImage
|
37
|
-
# SimpleData.post binaryData, "image/png"
|
38
|
-
#
|
39
|
-
# # GET requst with a custom request_header
|
40
|
-
# sh = SimpleHttp.new "http://www.example.com"
|
41
|
-
# sh.request_headers= {'X-Special-Http-Header'=>'my-value'}
|
42
|
-
# sh.get
|
43
|
-
class SimpleHttp
|
44
|
-
|
45
|
-
VERSION='0.1.1'
|
46
|
-
|
47
|
-
attr_accessor :proxy_host, :proxy_port, :proxy_user, :proxy_pwd, :uri, :request_headers, :response_headers, :response_handlers, :follow_num_redirects
|
48
|
-
|
49
|
-
RESPONSE_HANDLERS = {
|
50
|
-
Net::HTTPResponse => lambda { |request, response, http|
|
51
|
-
response.each_header {|key, value|
|
52
|
-
http.response_headers[key]=value
|
53
|
-
}
|
54
|
-
raise response.to_s
|
55
|
-
},
|
56
|
-
Net::HTTPSuccess => lambda { |request, response, http|
|
57
|
-
response.each_header {|key, value|
|
58
|
-
http.response_headers[key]=value
|
59
|
-
}
|
60
|
-
return response.body
|
61
|
-
},
|
62
|
-
Net::HTTPRedirection => lambda { |request, response, http|
|
63
|
-
raise "too many redirects!" unless http.follow_num_redirects > 0
|
64
|
-
|
65
|
-
# create a new SimpleHttp for the location
|
66
|
-
# refered to decreasing the remaining redirects
|
67
|
-
# by one.
|
68
|
-
sh = SimpleHttp.new response['location']
|
69
|
-
sh.follow_num_redirects = http.follow_num_redirects-1
|
70
|
-
|
71
|
-
# copy the response handlers used in the current
|
72
|
-
# request in case they were non standard.
|
73
|
-
sh.response_handlers = http.response_handlers
|
74
|
-
|
75
|
-
# copy the request headers
|
76
|
-
sh.request_headers=http.request_headers
|
77
|
-
sh.response_headers=http.response_headers
|
78
|
-
|
79
|
-
# http doesn't permit redirects for methods
|
80
|
-
# other than GET of HEAD, so we complain in case
|
81
|
-
# we get them in response to a POST request. (Or
|
82
|
-
# anything other than GET, for that matter.)
|
83
|
-
|
84
|
-
if request.class == Net::HTTP::Get
|
85
|
-
return sh.get
|
86
|
-
else
|
87
|
-
raise "Not a valid HTTP method for redirection: #{request.class}"
|
88
|
-
|
89
|
-
end
|
90
|
-
}
|
91
|
-
|
92
|
-
}
|
93
|
-
|
94
|
-
# SimpleHttp can either be used directly through the +get+ and
|
95
|
-
# +post+ class methods or be instantiated, in case you need to
|
96
|
-
# to add custom behaviour to the requests.
|
97
|
-
#
|
98
|
-
# @param may be a URI or a String.
|
99
|
-
#
|
100
|
-
# Example:
|
101
|
-
# http = SimpleHttp.new(URI.parse("http://www.example.com"))
|
102
|
-
# http = SimpleHttp.new "www.example.com"
|
103
|
-
# http = SimpleHttp.new "http://usr:pwd@www.example.com:1234"
|
104
|
-
def initialize uri
|
105
|
-
set_proxy ENV['http_proxy'] if ENV['http_proxy']
|
106
|
-
|
107
|
-
if uri.class == String
|
108
|
-
|
109
|
-
unless uri =~ /^https?:\/\//
|
110
|
-
uri = "http://#{uri}"
|
111
|
-
end
|
112
|
-
|
113
|
-
uri = URI.parse uri
|
114
|
-
|
115
|
-
end
|
116
|
-
@uri = uri
|
117
|
-
if !@uri.path || "" == @uri.path.strip
|
118
|
-
@uri.path="/"
|
119
|
-
end
|
120
|
-
|
121
|
-
|
122
|
-
@request_headers={}
|
123
|
-
@response_headers={}
|
124
|
-
@response_handlers=RESPONSE_HANDLERS.clone
|
125
|
-
@follow_num_redirects=3
|
126
|
-
|
127
|
-
if @uri.user
|
128
|
-
basic_authentication @uri.user, @uri.password
|
129
|
-
end
|
130
|
-
|
131
|
-
end
|
132
|
-
|
133
|
-
#
|
134
|
-
# Provides facilities to perform http basic authentication. You
|
135
|
-
# don't need to provide +usr+ and +pwd+ if they are already included
|
136
|
-
# in the uri, i.e. http://user:password@www.example.com/
|
137
|
-
#
|
138
|
-
|
139
|
-
def basic_authentication usr, pwd
|
140
|
-
str = Base64.encode64("#{usr}:#{pwd}")
|
141
|
-
str = "Basic #{str}"
|
142
|
-
@request_headers["Authorization"]=str
|
143
|
-
end
|
144
|
-
|
145
|
-
#
|
146
|
-
# this method can be used to register response handlers for specific
|
147
|
-
# http responses in case you need to override the default behaviour.
|
148
|
-
# Defaults are:
|
149
|
-
#
|
150
|
-
# HTTPSuccess : return the body of the response
|
151
|
-
# HTTPRedirection : follow the redirection until success
|
152
|
-
# Others : raise an exception
|
153
|
-
#
|
154
|
-
# `clazz` is the subclass of HTTPResponse (or HTTPResponse in case you
|
155
|
-
# want to define "default" behaviour) that you are registering the
|
156
|
-
# handler for.
|
157
|
-
#
|
158
|
-
# `block` is the handler itself, if a response of the appropriate class
|
159
|
-
# is received, `block` is called with three parameters: the the
|
160
|
-
# Net::HTTPRequest, the actual HTTPResponse object that was received
|
161
|
-
# and a reference to the instance of `SimpleHttp` that is executing the
|
162
|
-
# call.
|
163
|
-
#
|
164
|
-
# example:
|
165
|
-
#
|
166
|
-
# # to override the default action of following a HTTP
|
167
|
-
# # redirect, you could register the folllowing handler:
|
168
|
-
#
|
169
|
-
# sh = SimpleHttp "www.example.com"
|
170
|
-
# sh.register_response_handler Net::HTTPRedirection {|request, response, shttp|
|
171
|
-
# response['location']
|
172
|
-
# }
|
173
|
-
#
|
174
|
-
|
175
|
-
def register_response_handler clazz, &block
|
176
|
-
c = clazz
|
177
|
-
while c != Object
|
178
|
-
# completely unnecessary sanity check to make sure parameter
|
179
|
-
# `clazz` is in fact a HTTPResponse ...
|
180
|
-
if c == Net::HTTPResponse
|
181
|
-
@response_handlers[clazz]=block
|
182
|
-
return
|
183
|
-
end
|
184
|
-
c = c.superclass
|
185
|
-
end
|
186
|
-
|
187
|
-
raise "Trying to register a response handler for non-response class: #{clazz}"
|
188
|
-
end
|
189
|
-
|
190
|
-
#
|
191
|
-
# Set the proxy to use for the http request.
|
192
|
-
# Note that you don't need to set the proxy in case the
|
193
|
-
# `http_proxy` environment variable is set. To override
|
194
|
-
# previous proxy settings and connect directly, call
|
195
|
-
# `set_proxy nil`
|
196
|
-
#
|
197
|
-
# usage:
|
198
|
-
# http = SimpleHttp.new "www.example.com"
|
199
|
-
#
|
200
|
-
# http.set_proxy "http://proxy:8000"
|
201
|
-
# or:
|
202
|
-
# http.set_proxy(URI.parse("http://proxy:8000"))
|
203
|
-
# or:
|
204
|
-
# http.set_proxy 'proxy', '8000', 'my_user', 'secret'
|
205
|
-
# or:
|
206
|
-
# http.set_proxy nil # to override previous proxy
|
207
|
-
# settings and make the request directly.
|
208
|
-
#
|
209
|
-
|
210
|
-
|
211
|
-
def set_proxy proxy, port=nil, user=nil, pwd=nil
|
212
|
-
|
213
|
-
|
214
|
-
if !proxy
|
215
|
-
@proxy_host=@proxy_port=@proxy_user=@proxy_pwd=nil
|
216
|
-
return
|
217
|
-
end
|
218
|
-
|
219
|
-
if proxy.class == String
|
220
|
-
if !port && !user && !pwd
|
221
|
-
proxy = URI.parse(proxy)
|
222
|
-
else
|
223
|
-
@proxy_host= host
|
224
|
-
@proxy_port= port
|
225
|
-
@proxy_user= user
|
226
|
-
@proxy_pwd = pwd
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
if proxy.class == URI::HTTP
|
231
|
-
@proxy_host= proxy.host
|
232
|
-
@proxy_port= proxy.port
|
233
|
-
@proxy_user= proxy.user
|
234
|
-
@proxy_pwd = proxy.password
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
# interal
|
239
|
-
# Takes a HTTPResponse (or subclass) and determines how to
|
240
|
-
# handle the response. Default behaviour is:
|
241
|
-
#
|
242
|
-
# HTTPSuccess : return the body of the response
|
243
|
-
# HTTPRedirection : follow the redirect until success.
|
244
|
-
# default : raise the HTTPResponse.
|
245
|
-
#
|
246
|
-
# the default behaviour can be overidden by registering a
|
247
|
-
# response handler using the `register_response_handler` method.
|
248
|
-
#
|
249
|
-
|
250
|
-
def handle_response http_request, http_response
|
251
|
-
raise "Not a Net::HTTPResponse" unless http_response.is_a? Net::HTTPResponse
|
252
|
-
|
253
|
-
c = http_response.class
|
254
|
-
while c!=Object
|
255
|
-
# the response_handlers hash contains a handler
|
256
|
-
# for the specific response class.
|
257
|
-
if @response_handlers[c]
|
258
|
-
return @response_handlers[c].call(http_request, http_response, self)
|
259
|
-
end
|
260
|
-
|
261
|
-
c=c.superclass
|
262
|
-
end
|
263
|
-
|
264
|
-
# if we reached this place, no handler was registered
|
265
|
-
# for this response. default is to return the response.
|
266
|
-
|
267
|
-
return http_response
|
268
|
-
end
|
269
|
-
|
270
|
-
# internal
|
271
|
-
def do_http request
|
272
|
-
response = nil
|
273
|
-
|
274
|
-
http = Net::HTTP.new(@uri.host, @uri.port, @proxy_host,
|
275
|
-
@proxy_port, @proxy_user, @proxy_pwd)
|
276
|
-
http.use_ssl = @uri.scheme == 'https'
|
277
|
-
|
278
|
-
# add custom request headers.
|
279
|
-
|
280
|
-
@request_headers.each {|key,value|
|
281
|
-
request[key]=value;
|
282
|
-
}
|
283
|
-
|
284
|
-
handle_response(request, http.request(request));
|
285
|
-
end
|
286
|
-
|
287
|
-
# internal
|
288
|
-
def make_query query
|
289
|
-
return query unless query && query.class == Hash
|
290
|
-
str = ""
|
291
|
-
query.collect { |key, value|
|
292
|
-
str += CGI::escape(key) + "=" + CGI::escape(value)
|
293
|
-
}
|
294
|
-
str
|
295
|
-
end
|
296
|
-
|
297
|
-
# Make a simple GET request to the provided URI.
|
298
|
-
#
|
299
|
-
# Example:
|
300
|
-
# puts(SimpleHttp.get("www.example.com"))
|
301
|
-
def self.get uri, query=nil
|
302
|
-
http = SimpleHttp.new uri
|
303
|
-
http.get query
|
304
|
-
end
|
305
|
-
|
306
|
-
# Make a POST request to the provided URI.
|
307
|
-
#
|
308
|
-
# Example:
|
309
|
-
# puts(SimpleHttp.post("www.example.com", "query"=>"my_query"))
|
310
|
-
#
|
311
|
-
# Alternatively, you can post any sort of data, but will have to
|
312
|
-
# set the appriate content_type:
|
313
|
-
#
|
314
|
-
# SimpleHttp.post("http://www.example.com/", binary_data, "img/png")
|
315
|
-
|
316
|
-
def self.post uri, query=nil, content_type='application/x-www-form-urlencoded'
|
317
|
-
http = SimpleHttp.new uri
|
318
|
-
http.post query, content_type
|
319
|
-
end
|
320
|
-
|
321
|
-
# Call the +get+ method as an instance method if you need to
|
322
|
-
# modify the default behaviour of the library, or set special
|
323
|
-
# headers:
|
324
|
-
#
|
325
|
-
# http = SimpleHttp.new "www.example.com"
|
326
|
-
# http.request_headers["X-Special"]="whatever"
|
327
|
-
# str = http.get
|
328
|
-
def get query = nil
|
329
|
-
if (query = make_query query)
|
330
|
-
@uri.query = @uri.query ? @uri.query+"&"+query : query
|
331
|
-
end
|
332
|
-
full_path = @uri.path + (@uri.query ? "?#{@uri.query}" : "")
|
333
|
-
|
334
|
-
req = Net::HTTP::Get.new(full_path)
|
335
|
-
# puts Net::HTTP::Proxy(@proxy_host, @proxy_port, @proxy_user, @proxy_pwd).get(@uri)
|
336
|
-
do_http req
|
337
|
-
end
|
338
|
-
|
339
|
-
#
|
340
|
-
# Post the query data to the url.
|
341
|
-
# The body of the request remains empty if query=nil.
|
342
|
-
# In case `query` is a `Hash`, it's assumed that we are
|
343
|
-
# sending a form.
|
344
|
-
# In case `query` is a `String`, it's also assumed that a
|
345
|
-
# form is being sent, UNLESS the `content_type` parameter
|
346
|
-
# is set.
|
347
|
-
#
|
348
|
-
def post query=nil, content_type='application/x-www-form-urlencoded'
|
349
|
-
req = Net::HTTP::Post.new(@uri.path)
|
350
|
-
|
351
|
-
req.body= make_query query if query
|
352
|
-
req.content_type=content_type if query
|
353
|
-
req.content_length=query ? req.body.length : 0
|
354
|
-
|
355
|
-
do_http req
|
356
|
-
end
|
357
|
-
|
358
|
-
end
|
359
|
-
|
360
|
-
#ht = SimpleHttp.new "http://www.google.com/aldfksjaldskjfalskjfdlk"
|
361
|
-
##ht.register_response_handler(Net::HTTPRedirection) {|req, res, ht| puts res['location']}
|
362
|
-
#puts ht.get.class
|
363
|
-
##puts(ht.get("q"=>"bla"))
|
364
|
-
#
|
365
|
-
##puts (SimpleHttp.get "http://www.google.com")
|
366
|
-
#
|
367
|
-
#['http://www.google.com/', 'www.google.com', 'https://www.google.com'].each {|u|
|
368
|
-
# SimpleHttp.new u
|
369
|
-
#}
|
370
|
-
##puts ht.post
|
371
|
-
|
372
|
-
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
|
5
|
+
# kept for backwards compatibility
|
6
|
+
#
|
7
|
+
require 'simplehttp.rb'
|
data/lib/simplehttp.rb
ADDED
@@ -0,0 +1,450 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
|
5
|
+
require 'net/http'
|
6
|
+
require 'net/https'
|
7
|
+
require 'uri'
|
8
|
+
require 'cgi'
|
9
|
+
require 'base64'
|
10
|
+
|
11
|
+
|
12
|
+
# Wrapper around ruby's standard net/http classes. Currently, only GET
|
13
|
+
# and POST https methods are supported. `SimpleHttp` provides class
|
14
|
+
# methods `get` and `post` to handle basic functionality. In case more
|
15
|
+
# complicated requests need to be made or default settings need to be
|
16
|
+
# overriden, it's possible to instantiate `SimpleHttp` and use instance
|
17
|
+
# methods `get` and `put`.
|
18
|
+
#
|
19
|
+
#
|
20
|
+
# Features:
|
21
|
+
#
|
22
|
+
# * Handles Redirects automatically
|
23
|
+
# * Proxy used transparently if http_proxy environment variable is
|
24
|
+
# set.
|
25
|
+
# * SSL handled automatically
|
26
|
+
# * fault tolerant uri, e.g. all of these would work:
|
27
|
+
# "www.example.com", "www.example.com/", "http://www.example.com"
|
28
|
+
#
|
29
|
+
# Some usage examples:
|
30
|
+
# # plain GET (using class methods)
|
31
|
+
# SimpleHttp.get "www.example.com"
|
32
|
+
#
|
33
|
+
# # POST using the instance methods
|
34
|
+
# uri = URI.parse "https://www.example.com/index.html"
|
35
|
+
# sh = SimpleHttp uri
|
36
|
+
# sh.set_proxy "my.proxy", "8080"
|
37
|
+
# sh.post {"query" => "query_data"}
|
38
|
+
#
|
39
|
+
# # POST using class methods.
|
40
|
+
# binaryData = getImage
|
41
|
+
# SimpleData.post binaryData, "image/png"
|
42
|
+
#
|
43
|
+
# # GET requst with a custom request_header
|
44
|
+
# sh = SimpleHttp.new "http://www.example.com"
|
45
|
+
# sh.request_headers= {'X-Special-Http-Header'=>'my-value'}
|
46
|
+
# sh.get
|
47
|
+
class SimpleHttp
|
48
|
+
|
49
|
+
VERSION='0.1.3'
|
50
|
+
|
51
|
+
attr_accessor :proxy_host, :proxy_port, :proxy_user, :proxy_pwd, :uri, :request_headers, :response_headers, :response_handlers, :follow_num_redirects
|
52
|
+
RESPONSE_HANDLERS = {
|
53
|
+
Net::HTTPResponse => lambda { |request, response, http|
|
54
|
+
response.each_header {|key, value|
|
55
|
+
http.response_headers[key]=value
|
56
|
+
}
|
57
|
+
raise "#{response.to_s} : #{response.code} : #{http.uri}"
|
58
|
+
},
|
59
|
+
Net::HTTPSuccess => lambda { |request, response, http|
|
60
|
+
response.each_header {|key, value|
|
61
|
+
http.response_headers[key]=value
|
62
|
+
}
|
63
|
+
#http.cookies += response.cookies
|
64
|
+
if request.class == Net::HTTP::Head || request.class == Net::HTTP::Options
|
65
|
+
return http.response_headers
|
66
|
+
end
|
67
|
+
return response.body
|
68
|
+
},
|
69
|
+
Net::HTTPRedirection => lambda { |request, response, http|
|
70
|
+
raise "too many redirects!" unless http.follow_num_redirects > 0
|
71
|
+
# create a new SimpleHttp for the location
|
72
|
+
# refered to decreasing the remaining redirects
|
73
|
+
# by one.
|
74
|
+
|
75
|
+
if (location = response['location']) !~ /^https?:\/\//
|
76
|
+
new_location = "#{http.uri.scheme}://#{http.uri.host}"
|
77
|
+
if location =~ /^\//
|
78
|
+
new_location += location
|
79
|
+
else
|
80
|
+
new_location += "/#{http.uri.path}/#{location}"
|
81
|
+
end
|
82
|
+
location = new_location
|
83
|
+
end
|
84
|
+
|
85
|
+
sh = SimpleHttp.new location
|
86
|
+
#STDERR.puts location
|
87
|
+
sh.follow_num_redirects = http.follow_num_redirects-1
|
88
|
+
|
89
|
+
# copy the response handlers used in the current
|
90
|
+
# request in case they were non standard.
|
91
|
+
sh.response_handlers = http.response_handlers
|
92
|
+
|
93
|
+
# copy the request headers
|
94
|
+
sh.request_headers=http.request_headers
|
95
|
+
sh.response_headers=http.response_headers
|
96
|
+
#sh.cookies+=http.cookies
|
97
|
+
|
98
|
+
# copy host and port
|
99
|
+
sh.uri.host = http.uri.host
|
100
|
+
sh.uri.port = http.uri.port
|
101
|
+
|
102
|
+
# HTTP doesn't permit redirects for methods other than
|
103
|
+
# GET or HEAD. The exception is 303 redirects, which
|
104
|
+
# should automatically follow the redirect URI using a
|
105
|
+
# GET method regardless of the initial method. For
|
106
|
+
# other classes of redirection, the client is required
|
107
|
+
# to prompt the user before redirection occurs. Because
|
108
|
+
# that's not a feasible action for this library, all
|
109
|
+
# 3xx redirect URIs are followed using a GET method.
|
110
|
+
#
|
111
|
+
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
112
|
+
|
113
|
+
case request
|
114
|
+
when Net::HTTP::Get,
|
115
|
+
Net::HTTP::Head,
|
116
|
+
Net::HTTP::Options
|
117
|
+
|
118
|
+
sh.get
|
119
|
+
when Net::HTTP::Post
|
120
|
+
sh.request_headers['content-length']=nil
|
121
|
+
sh.get
|
122
|
+
else
|
123
|
+
raise "Not a valid HTTP method for redirection: #{request.class}"
|
124
|
+
end
|
125
|
+
|
126
|
+
}
|
127
|
+
|
128
|
+
}
|
129
|
+
|
130
|
+
# SimpleHttp can either be used directly through the +get+ and
|
131
|
+
# +post+ class methods or be instantiated, in case you need to
|
132
|
+
# to add custom behaviour to the requests.
|
133
|
+
#
|
134
|
+
# @param may be a URI or a String.
|
135
|
+
#
|
136
|
+
# Example:
|
137
|
+
# http = SimpleHttp.new(URI.parse("http://www.example.com"))
|
138
|
+
# http = SimpleHttp.new "www.example.com"
|
139
|
+
# http = SimpleHttp.new "http://usr:pwd@www.example.com:1234"
|
140
|
+
def initialize uri
|
141
|
+
set_proxy ENV['http_proxy'] if ENV['http_proxy']
|
142
|
+
|
143
|
+
if uri.class == String
|
144
|
+
|
145
|
+
unless uri =~ /^https?:\/\//
|
146
|
+
uri = "http://#{uri}"
|
147
|
+
end
|
148
|
+
|
149
|
+
uri = URI.parse uri
|
150
|
+
|
151
|
+
end
|
152
|
+
@uri = uri
|
153
|
+
if !@uri.path || "" == @uri.path.strip
|
154
|
+
@uri.path="/"
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
@request_headers={}
|
159
|
+
@response_headers={}
|
160
|
+
@cookies=[]
|
161
|
+
@response_handlers=RESPONSE_HANDLERS.clone
|
162
|
+
@follow_num_redirects=5
|
163
|
+
|
164
|
+
if @uri.user
|
165
|
+
basic_authentication @uri.user, @uri.password
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
# Provides facilities to perform http basic authentication. You
|
172
|
+
# don't need to provide +usr+ and +pwd+ if they are already included
|
173
|
+
# in the uri, i.e. http://user:password@www.example.com/
|
174
|
+
#
|
175
|
+
|
176
|
+
def basic_authentication usr, pwd
|
177
|
+
str = Base64.encode64("#{usr}:#{pwd}")
|
178
|
+
str = "Basic #{str}"
|
179
|
+
@request_headers["Authorization"]=str
|
180
|
+
end
|
181
|
+
|
182
|
+
#
|
183
|
+
# this method can be used to register response handlers for specific
|
184
|
+
# http responses in case you need to override the default behaviour.
|
185
|
+
# Defaults are:
|
186
|
+
#
|
187
|
+
# HTTPSuccess : return the body of the response
|
188
|
+
# HTTPRedirection : follow the redirection until success
|
189
|
+
# Others : raise an exception
|
190
|
+
#
|
191
|
+
# `clazz` is the subclass of HTTPResponse (or HTTPResponse in case you
|
192
|
+
# want to define "default" behaviour) that you are registering the
|
193
|
+
# handler for.
|
194
|
+
#
|
195
|
+
# `block` is the handler itself, if a response of the appropriate class
|
196
|
+
# is received, `block` is called with three parameters: the the
|
197
|
+
# Net::HTTPRequest, the actual HTTPResponse object that was received
|
198
|
+
# and a reference to the instance of `SimpleHttp` that is executing the
|
199
|
+
# call.
|
200
|
+
#
|
201
|
+
# example:
|
202
|
+
#
|
203
|
+
# # to override the default action of following a HTTP
|
204
|
+
# # redirect, you could register the folllowing handler:
|
205
|
+
#
|
206
|
+
# sh = SimpleHttp "www.example.com"
|
207
|
+
# sh.register_response_handler Net::HTTPRedirection {|request, response, shttp|
|
208
|
+
# response['location']
|
209
|
+
# }
|
210
|
+
#
|
211
|
+
|
212
|
+
def register_response_handler clazz, &block
|
213
|
+
c = clazz
|
214
|
+
while c != Object
|
215
|
+
# completely unnecessary sanity check to make sure parameter
|
216
|
+
# `clazz` is in fact a HTTPResponse ...
|
217
|
+
if c == Net::HTTPResponse
|
218
|
+
@response_handlers[clazz]=block
|
219
|
+
return
|
220
|
+
end
|
221
|
+
c = c.superclass
|
222
|
+
end
|
223
|
+
|
224
|
+
raise "Trying to register a response handler for non-response class: #{clazz}"
|
225
|
+
end
|
226
|
+
|
227
|
+
#
|
228
|
+
# Set the proxy to use for the http request.
|
229
|
+
# Note that you don't need to set the proxy in case the
|
230
|
+
# `http_proxy` environment variable is set. To override
|
231
|
+
# previous proxy settings and connect directly, call
|
232
|
+
# `set_proxy nil`
|
233
|
+
#
|
234
|
+
# usage:
|
235
|
+
# http = SimpleHttp.new "www.example.com"
|
236
|
+
#
|
237
|
+
# http.set_proxy "http://proxy:8000"
|
238
|
+
# or:
|
239
|
+
# http.set_proxy(URI.parse("http://proxy:8000"))
|
240
|
+
# or:
|
241
|
+
# http.set_proxy 'proxy', '8000', 'my_user', 'secret'
|
242
|
+
# or:
|
243
|
+
# http.set_proxy nil # to override previous proxy
|
244
|
+
# settings and make the request directly.
|
245
|
+
#
|
246
|
+
|
247
|
+
|
248
|
+
def set_proxy proxy, port=nil, user=nil, pwd=nil
|
249
|
+
|
250
|
+
|
251
|
+
if !proxy
|
252
|
+
@proxy_host=@proxy_port=@proxy_user=@proxy_pwd=nil
|
253
|
+
return
|
254
|
+
end
|
255
|
+
|
256
|
+
if proxy.class == String
|
257
|
+
if !port && !user && !pwd
|
258
|
+
proxy = URI.parse(proxy)
|
259
|
+
else
|
260
|
+
@proxy_host= host
|
261
|
+
@proxy_port= port
|
262
|
+
@proxy_user= user
|
263
|
+
@proxy_pwd = pwd
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
if proxy.class == URI::HTTP
|
268
|
+
@proxy_host= proxy.host
|
269
|
+
@proxy_port= proxy.port
|
270
|
+
@proxy_user= proxy.user
|
271
|
+
@proxy_pwd = proxy.password
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
# interal
|
276
|
+
# Takes a HTTPResponse (or subclass) and determines how to
|
277
|
+
# handle the response. Default behaviour is:
|
278
|
+
#
|
279
|
+
# HTTPSuccess : return the body of the response
|
280
|
+
# HTTPRedirection : follow the redirect until success.
|
281
|
+
# default : raise the HTTPResponse.
|
282
|
+
#
|
283
|
+
# the default behaviour can be overidden by registering a
|
284
|
+
# response handler using the `register_response_handler` method.
|
285
|
+
#
|
286
|
+
|
287
|
+
def handle_response http_request, http_response
|
288
|
+
raise "Not a Net::HTTPResponse" unless http_response.is_a? Net::HTTPResponse
|
289
|
+
|
290
|
+
c = http_response.class
|
291
|
+
while c!=Object
|
292
|
+
# the response_handlers hash contains a handler
|
293
|
+
# for the specific response class.
|
294
|
+
if @response_handlers[c]
|
295
|
+
#STDERR.puts "!#{http_response.class}"
|
296
|
+
#STDERR.puts "!#{@response_handlers[c]}"
|
297
|
+
return @response_handlers[c].call(http_request, http_response, self)
|
298
|
+
end
|
299
|
+
|
300
|
+
c=c.superclass
|
301
|
+
end
|
302
|
+
|
303
|
+
# if we reached this place, no handler was registered
|
304
|
+
# for this response. default is to return the response.
|
305
|
+
|
306
|
+
return http_response
|
307
|
+
end
|
308
|
+
|
309
|
+
# internal
|
310
|
+
def do_http request
|
311
|
+
response = nil
|
312
|
+
|
313
|
+
http = Net::HTTP.new(@uri.host, @uri.port, @proxy_host,
|
314
|
+
@proxy_port, @proxy_user, @proxy_pwd)
|
315
|
+
http.use_ssl = @uri.scheme == 'https'
|
316
|
+
|
317
|
+
# add custom request headers.
|
318
|
+
|
319
|
+
@request_headers.each {|key,value|
|
320
|
+
request[key]=value;
|
321
|
+
}
|
322
|
+
|
323
|
+
handle_response(request, http.request(request));
|
324
|
+
end
|
325
|
+
|
326
|
+
# internal
|
327
|
+
def make_query query
|
328
|
+
return query unless query && query.class == Hash
|
329
|
+
query.inject([]) do |s, (key, value)|
|
330
|
+
s << CGI::escape(key) + "=" + CGI::escape(value)
|
331
|
+
end.join('&')
|
332
|
+
end
|
333
|
+
|
334
|
+
# Make a simple GET request to the provided URI.
|
335
|
+
#
|
336
|
+
# Example:
|
337
|
+
# puts(SimpleHttp.get("www.example.com"))
|
338
|
+
def self.get uri, query=nil
|
339
|
+
http = SimpleHttp.new uri
|
340
|
+
http.get query
|
341
|
+
end
|
342
|
+
|
343
|
+
def self.head uri, query=nil
|
344
|
+
http = SimpleHttp.new uri
|
345
|
+
http.head query
|
346
|
+
end
|
347
|
+
|
348
|
+
def self.options uri
|
349
|
+
http = SimpleHttp.new uri
|
350
|
+
http.options
|
351
|
+
end
|
352
|
+
|
353
|
+
def self.trace uri
|
354
|
+
http = SimpleHttp.new uri
|
355
|
+
http.trace
|
356
|
+
end
|
357
|
+
|
358
|
+
# Make a POST request to the provided URI.
|
359
|
+
#
|
360
|
+
# Example:
|
361
|
+
# puts(SimpleHttp.post("www.example.com", "query"=>"my_query"))
|
362
|
+
#
|
363
|
+
# Alternatively, you can post any sort of data, but will have to
|
364
|
+
# set the appriate content_type:
|
365
|
+
#
|
366
|
+
# SimpleHttp.post("http://www.example.com/", binary_data, "img/png")
|
367
|
+
|
368
|
+
def self.post uri, query=nil, content_type='application/x-www-form-urlencoded'
|
369
|
+
http = SimpleHttp.new uri
|
370
|
+
http.post query, content_type
|
371
|
+
end
|
372
|
+
|
373
|
+
# Call the +get+ method as an instance method if you need to
|
374
|
+
# modify the default behaviour of the library, or set special
|
375
|
+
# headers:
|
376
|
+
#
|
377
|
+
# http = SimpleHttp.new "www.example.com"
|
378
|
+
# http.request_headers["X-Special"]="whatever"
|
379
|
+
# str = http.get
|
380
|
+
def get query = nil
|
381
|
+
if (query = make_query query)
|
382
|
+
@uri.query = @uri.query ? @uri.query+"&"+query : query
|
383
|
+
end
|
384
|
+
full_path = @uri.path + (@uri.query ? "?#{@uri.query}" : "")
|
385
|
+
|
386
|
+
req = Net::HTTP::Get.new(full_path)
|
387
|
+
# puts Net::HTTP::Proxy(@proxy_host, @proxy_port, @proxy_user, @proxy_pwd).get(@uri)
|
388
|
+
do_http req
|
389
|
+
end
|
390
|
+
|
391
|
+
# Call the +head+ method as an instance method.
|
392
|
+
#
|
393
|
+
def head query = nil
|
394
|
+
if (query = make_query query)
|
395
|
+
@uri.query = @uri.query ? @uri.query+"&"+query : query
|
396
|
+
end
|
397
|
+
full_path = @uri.path + (@uri.query ? "?#{@uri.query}" : "")
|
398
|
+
|
399
|
+
req = Net::HTTP::Head.new(full_path)
|
400
|
+
# puts Net::HTTP::Proxy(@proxy_host, @proxy_port, @proxy_user, @proxy_pwd).get(@uri)
|
401
|
+
do_http req
|
402
|
+
end
|
403
|
+
|
404
|
+
# Call http +options+ method. Returns the response
|
405
|
+
def options
|
406
|
+
# we don't support sending a payload in options' body.
|
407
|
+
req = Net::HTTP::Options.new(@uri.path)
|
408
|
+
do_http req
|
409
|
+
end
|
410
|
+
|
411
|
+
def trace
|
412
|
+
# payload?
|
413
|
+
req = Net::HTTP::Trace.new(@uri.path)
|
414
|
+
do_http req
|
415
|
+
end
|
416
|
+
|
417
|
+
#
|
418
|
+
# Post the query data to the url.
|
419
|
+
# The body of the request remains empty if query=nil.
|
420
|
+
# In case `query` is a `Hash`, it's assumed that we are
|
421
|
+
# sending a form.
|
422
|
+
# In case `query` is a `String`, it's also assumed that a
|
423
|
+
# form is being sent, UNLESS the `content_type` parameter
|
424
|
+
# is set.
|
425
|
+
#
|
426
|
+
def post query=nil, content_type='application/x-www-form-urlencoded'
|
427
|
+
req = Net::HTTP::Post.new(@uri.path)
|
428
|
+
|
429
|
+
req.body= make_query query if query
|
430
|
+
req.content_type=content_type if query
|
431
|
+
req.content_length=query ? req.body.length : 0
|
432
|
+
|
433
|
+
do_http req
|
434
|
+
end
|
435
|
+
|
436
|
+
end
|
437
|
+
|
438
|
+
#ht = SimpleHttp.new "http://www.google.com/aldfksjaldskjfalskjfdlk"
|
439
|
+
##ht.register_response_handler(Net::HTTPRedirection) {|req, res, ht| puts res['location']}
|
440
|
+
#puts ht.get.class
|
441
|
+
##puts(ht.get("q"=>"bla"))
|
442
|
+
#
|
443
|
+
##puts (SimpleHttp.get "http://www.google.com")
|
444
|
+
#
|
445
|
+
#['http://www.google.com/', 'www.google.com', 'https://www.google.com'].each {|u|
|
446
|
+
# SimpleHttp.new u
|
447
|
+
#}
|
448
|
+
##puts ht.post
|
449
|
+
|
450
|
+
|
data/test/http_test.rb
CHANGED
@@ -70,6 +70,10 @@ class SimpleHttpTest < Test::Unit::TestCase
|
|
70
70
|
ret = http.get "query2" => "query_test"
|
71
71
|
assert_equal("query_test", ret, "basic GET (query) 3 test failed.")
|
72
72
|
|
73
|
+
http = SimpleHttp.new(URI.parse("http://127.0.0.1:12345/query_test2?bla=true"))
|
74
|
+
ret = http.get "something"=>"or the other", "query2" => "query_test"
|
75
|
+
assert_equal("query_test", ret, "basic GET (query) 4 test failed.")
|
76
|
+
|
73
77
|
# GET request with a custom request_header
|
74
78
|
http = SimpleHttp.new "http://127.0.0.1:12345/header_test"
|
75
79
|
http.request_headers= {'x-special-http-header'=>'my-value'}
|
@@ -196,11 +200,11 @@ class SimpleHttpTest < Test::Unit::TestCase
|
|
196
200
|
ret = http.get
|
197
201
|
}
|
198
202
|
|
203
|
+
|
199
204
|
ret = SimpleHttp.get "http://test:pwd@127.0.0.1:12345/redirect"
|
200
205
|
assert_equal(ret, TestServer::SUCCESS_TEXT_0, "redirect test 2");
|
201
|
-
|
202
|
-
|
203
206
|
end
|
207
|
+
|
204
208
|
|
205
209
|
|
206
210
|
end
|
data/test/http_test_server.rb
CHANGED
metadata
CHANGED
@@ -1,35 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.0
|
3
|
-
specification_version: 1
|
4
2
|
name: simplehttp
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2007-02-09 00:00:00 +01:00
|
8
|
-
summary: "simple_http: Simple Http client lib."
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email:
|
12
|
-
homepage:
|
13
|
-
rubyforge_project:
|
14
|
-
description: Wrapper around net/http to provide quick and dirty http access.
|
15
|
-
autorequire:
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: false
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
4
|
+
version: 0.1.3
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors: []
|
30
7
|
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-09-21 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Wrapper around net/http to provide quick and dirty http access.
|
17
|
+
email:
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
31
24
|
files:
|
32
25
|
- lib/simple_http.rb
|
26
|
+
- lib/simplehttp.rb
|
33
27
|
- AUTHORS
|
34
28
|
- CHANGELOG
|
35
29
|
- LICENSE
|
@@ -38,17 +32,31 @@ files:
|
|
38
32
|
- TODO
|
39
33
|
- test/http_test.rb
|
40
34
|
- test/http_test_server.rb
|
41
|
-
|
42
|
-
|
35
|
+
has_rdoc: false
|
36
|
+
homepage:
|
37
|
+
post_install_message:
|
43
38
|
rdoc_options: []
|
44
39
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
version:
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
51
54
|
requirements:
|
52
55
|
- none
|
53
|
-
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.0.1
|
58
|
+
signing_key:
|
59
|
+
specification_version: 2
|
60
|
+
summary: "simple_http: Simple Http client lib."
|
61
|
+
test_files: []
|
54
62
|
|