simplehttp 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|