fresh_simplehttp 0.1.7

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 ADDED
@@ -0,0 +1,4 @@
1
+ * Tim Becker (tim@kuriositaet.de)
2
+ * Minero Aoki (setup.rb)
3
+ * Clint Pachl
4
+ * Dave Myron
data/CHANGELOG ADDED
@@ -0,0 +1,20 @@
1
+ = Mon Sep 22 15:12:44 CEST 2008
2
+ * General code cleanup
3
+ * Additional Docs
4
+ * Reluctantly changes tabs to (ruby default) spaces (YUCK!)
5
+ = Mon Sep 22 13:25:22 CEST 2008
6
+ * bugfix: uri query parameter preserved on post req
7
+
8
+ = Sun Sep 21 18:29:20 CEST 2008
9
+ * changes to redirect handling
10
+ * bugfix make_query
11
+
12
+ = Wed Sep 26 16:25:55 2007
13
+ implemented +head+, +options+ and +trace+,
14
+ made filenames easier. 'simple_http' -> 'simplehttp'
15
+
16
+ = Fri Feb 9 12:23:20 CET 2007
17
+ * easier access to response headers
18
+ * pass through headers during redirects
19
+ * more tests and documentation
20
+ * included `setup.rb`
data/LICENSE ADDED
@@ -0,0 +1,58 @@
1
+ This package is copyrighted free software by Tim Becker <tim@kuriositaet.de>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ (see COPYING.txt file), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) rename any non-standard executables so the names do not conflict
21
+ with standard executables, which must also be provided.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or executable
26
+ form, provided that you do at least ONE of the following:
27
+
28
+ a) distribute the executables and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard executables non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under this terms.
43
+
44
+ They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
45
+ files under the ./missing directory. See each file for the copying
46
+ condition.
47
+
48
+ 5. The scripts and library files supplied as input to or produced as
49
+ output from the software do not automatically fall under the
50
+ copyright of the software, but belong to whomever generated them,
51
+ and may be sold commercially, and may be aggregated with this
52
+ software.
53
+
54
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
55
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57
+ PURPOSE.
58
+
data/README ADDED
@@ -0,0 +1,96 @@
1
+ = SimpleHttp - a simplified wrapper around Net::Http
2
+
3
+ SimpleHttp aims to reduce the complexity of Net::Http while providing
4
+ the most commonly used (by me) http functionality.
5
+
6
+ INSTALLATION
7
+
8
+ * Using +gem+
9
+
10
+ gem install simplehttp
11
+
12
+ * Using +setup.rb+
13
+
14
+ ruby setup.rb config
15
+ ruby setup.rb install
16
+
17
+ * tarball and zip packages are available from
18
+ RubyForge[http://rubyforge.org/projects/simplehttp/]
19
+
20
+
21
+
22
+ FEATURES / USAGE
23
+
24
+ * Require the lib:
25
+
26
+ require 'simplehttp'
27
+
28
+ * No fuss one line GET and POST requests:
29
+
30
+ str = SimpleHttp.get "http://www.example.com"
31
+ str = SimpleHttp.get "www.example.com"
32
+
33
+ * Can use URI or String url interchangibly
34
+
35
+ str = SimpleHttp.get URI.parse "http://www.example.com/"
36
+
37
+ * Transparent Proxy Handling. Uses the 'http_proxy' environment
38
+ variable if set, also provides a +set_proxy+ method.
39
+
40
+ http = SimpleHttp.new "http://www.example.com"
41
+ http.set_proxy "http://proxy.example.com:8000"
42
+ http.post "query" => "example_query"
43
+
44
+ * POST sends ruby Hashes as 'application/x-www-form/urlencoded' per
45
+ default, but can send any data.
46
+
47
+ http = SimpleHttp.new "http://www.example.com/image_upload"
48
+ http.post imageData, "img/png"
49
+
50
+ * Automatically handles SSL
51
+
52
+ str = SimpleHttp.get "https://secure.example.com"
53
+
54
+ * Easy HTTP Basic Authentication
55
+ str = SimpleHttp.get URI.parse("http://usr:pwd@www.example.com")
56
+ #or
57
+ http = SimpleHttp.new "http://www.example.com"
58
+ http.basic_authentication "user", "password"
59
+ http.post "query" => "example_query"
60
+
61
+ * Access headers of the request or response
62
+ http = SimpleHttp.new "www.example.com"
63
+ http.request_headers["X-Custom-Header"]="useful header"
64
+ http.get
65
+ puts "server set cookie: #{http.response_headers['set-cookie']}"
66
+
67
+ * Automatically follows Http Redirects.
68
+
69
+
70
+ The +get+ and +post+ methods return a +String+ containing the
71
+ body of the request if the request was successful (HTTP 200). In case of
72
+ a redirect, the redirect is followed and the ultimate response is
73
+ returned. Per Default, up to three redirects are followed, this
74
+ behaviour can be modified by setting +follow_num_redirects+.
75
+
76
+ In case of any other type of response, an exception is raised.
77
+
78
+ The default behaviour can be modified by registering handlers
79
+ using the +register_response_handler+ method. E.g. if you'd like to
80
+ retrieve the +Date+ header instead of the body for successful
81
+ transactions:
82
+
83
+ http = SimpleHttp.new ...
84
+ http.register_response_handler(Net::HTTPSuccess) {|req,res,http|
85
+ res['date']
86
+ }
87
+
88
+ Or you'd like to print the +Location+ and then raise an exception in
89
+ case of a redirect:
90
+
91
+
92
+ http = SimpleHttp.new ...
93
+ http.register_response_handler(Net::HTTPRedirect) {|req,res,http|
94
+ puts res['location']
95
+ raise "REDIRECT not allowed!"
96
+ }
data/Rakefile ADDED
@@ -0,0 +1,137 @@
1
+ require "rake/rdoctask"
2
+ require "rake/gempackagetask"
3
+ require "rake/testtask"
4
+ require "rake/clean"
5
+ require "rubygems"
6
+
7
+ require "lib/simple_http"
8
+
9
+ # Specifies the default task to execute. This is often the "test" task
10
+ # and we'll change things around as soon as we have some tests.
11
+
12
+ task :default => [:rdoc]
13
+
14
+ # The directory to generate +rdoc+ in.
15
+ RDOC_DIR="doc/html"
16
+
17
+ # This global variable contains files that will be erased by the `clean` task.
18
+ # The `clean` task itself is automatically generated by requiring `rake/clean`.
19
+
20
+ CLEAN << RDOC_DIR
21
+
22
+ begin
23
+ require 'jeweler'
24
+ Jeweler::Tasks.new do |gemspec|
25
+ gemspec.name = "fresh_simplehttp"
26
+ gemspec.summary = "simple_http: Simple Http client lib."
27
+ gemspec.description = "simple_http: Simple Http client lib. Use to do http requests without noise."
28
+ gemspec.email = "wilkerlucio@gmail.com"
29
+ gemspec.homepage = "http://github.com/wilkerlucio/simplehttp"
30
+ gemspec.authors = ["Wilker Lucio"]
31
+
32
+ gemspec.files.exclude "pkg/**/*"
33
+ gemspec.files.exclude "test/**/*"
34
+ end
35
+ Jeweler::GemcutterTasks.new
36
+ rescue LoadError
37
+ puts "Jeweler not available. Install it with: gem install jeweler"
38
+ end
39
+
40
+ # This is the task that generates the +rdoc+ documentation from the
41
+ # source files. Instantiating Rake::RDocTask automatically generates a
42
+ # task called `rdoc`.
43
+
44
+ Rake::RDocTask.new do |rd|
45
+ # Options for documenation generation are specified inside of
46
+ # this block. For example the following line specifies that the
47
+ # content of the README file should be the main page of the
48
+ # documenation.
49
+ rd.main = "README"
50
+
51
+ # The following line specifies all the files to extract
52
+ # documenation from.
53
+ rd.rdoc_files.include( "README", "AUTHORS", "LICENSE", "TODO",
54
+ "CHANGELOG", "bin/**/*", "lib/**/*.rb",
55
+ "examples/**/*rb","test/**/*.rb", "doc/*.rdoc")
56
+ # This one specifies the output directory ...
57
+ rd.rdoc_dir = "doc/html"
58
+
59
+ # Or the HTML title of the generated documentation set.
60
+ rd.title = "simple_http: Simple Http client lib."
61
+
62
+ # These are options specifiying how source code inlined in the
63
+ # documentation should be formatted.
64
+
65
+ rd.options = ["--line-numbers", "--inline-source"]
66
+
67
+ # Check:
68
+ # `rdoc --help` for more rdoc options
69
+ # the {rdoc documenation home}[http://www.ruby-doc.org/stdlib/libdoc/rdoc/rdoc/index.html]
70
+ # or the documentation for the +Rake::RDocTask+ task[http://rake.rubyforge.org/classes/Rake/RDocTask.html]
71
+ end
72
+
73
+ # The GemPackageTask facilitates getting all your files collected
74
+ # together into gem archives. You can also use it to generate tarball
75
+ # and zip archives.
76
+
77
+ # First you'll need to assemble a gemspec
78
+
79
+ PROJECT_NAME = "simplehttp"
80
+ PKG_VERSION = SimpleHttp::VERSION
81
+ PKG_FILES = FileList['lib/**/*.rb', 'bin/**/*', 'examples/**/*', '[A-Z]*', 'test/**/*'].to_a
82
+
83
+ spec = Gem::Specification.new do |s|
84
+ s.platform = Gem::Platform::RUBY
85
+ s.summary = "simple_http: Simple Http client lib."
86
+ s.name = PROJECT_NAME
87
+ s.version = PKG_VERSION
88
+ s.files = PKG_FILES
89
+ s.requirements << "none"
90
+ s.require_path = 'lib'
91
+ s.description = <<END_DESC
92
+ Wrapper around net/http to provide quick and dirty http access.
93
+ END_DESC
94
+ end
95
+
96
+ # Adding a new GemPackageTask adds a task named `package`, which generates
97
+ # packages as gems, tarball and zip archives.
98
+ Rake::GemPackageTask.new(spec) do |pkg|
99
+ pkg.need_zip = true
100
+ pkg.need_tar_gz = true
101
+ end
102
+
103
+
104
+ # This task is used to demonstrate how to upload files to Rubyforge.
105
+ # Calling `upload_page` creates a current version of the +rdoc+
106
+ # documentation and uploads it to the Rubyforge homepage of the project,
107
+ # assuming it's hosted there and naming conventions haven't changed.
108
+ #
109
+ # This task uses `sh` to call the `scp` binary, which is plattform
110
+ # dependant and may not be installed on your computer if you're using
111
+ # Windows. I'm currently not aware of any pure ruby way to do scp
112
+ # transfers.
113
+
114
+ RubyForgeUser="a2800276"
115
+ RubyForgeProject=PROJECT_NAME
116
+
117
+ desc "Upload the web pages to the web."
118
+ task :upload_pages => ["clean", :rdoc] do
119
+ if RubyForgeProject then
120
+ path = "/var/www/gforge-projects/#{RubyForgeProject}"
121
+ sh "scp -r doc/html/* #{RubyForgeUser}@rubyforge.org:#{path}"
122
+ sh "scp doc/images/*.png #{RubyForgeUser}@rubyforge.org:#{path}/images"
123
+ end
124
+ end
125
+
126
+
127
+ # This task will run the unit tests provided in files called
128
+ # `test/test*.rb`. The task itself can be run with a call to `rake test`
129
+
130
+ Rake::TestTask.new do |t|
131
+ t.libs << "test"
132
+ t.libs << "lib"
133
+ t.test_files = FileList['test/*.rb']
134
+ t.verbose = true
135
+ end
136
+
137
+
data/TODO ADDED
@@ -0,0 +1,28 @@
1
+ * Provide tests and documentation for +head+, +options+ and +trace+
2
+
3
+ * There seems to be a bug in webrick that it doesn't recognize the
4
+ Content-Length header if using basic authentication. The POST test
5
+ cases lead to a:
6
+ ERROR HTTPRequest#fixup: WEBrick::HTTPStatus::LengthRequired occured.
7
+ even though the Content-Length header is set correctly in the http
8
+ packet...
9
+
10
+ * I've not figured out how to set_up and teardown webbrick properly.
11
+ Since webbrick blocks after calling `start`, it needs to started in a
12
+ seperate thread. I didn't handle communication with it properly
13
+ though. Test::Unit calls set_up and teardown before
14
+ and after executing each test... method, and not as I expected, before
15
+ and after each test file. This leads to a new TestServer being
16
+ instantiated which complains "bind-adress already in use", because the
17
+ other instance wasn't properly shut down. I tried to dix this by setting
18
+ up the server in the constructor, but that has the same effect.
19
+ It seems like a new instance of TestCase is instantiated to run every
20
+ single test... method.
21
+
22
+ * There also seems to be something screwy about how rake calls the
23
+ tests. Some ruby files seem to be included twice. This leads to
24
+ "already initialized constant" error in the output of the unit tests.
25
+
26
+ * The two previous bugs aren't really problematic, because they only
27
+ make the output of the tests ugly. They should be easy to fix... (But
28
+ they're not high on my list of priorities.)
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.7
@@ -0,0 +1,55 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{fresh_simplehttp}
8
+ s.version = "0.1.7"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Wilker Lucio"]
12
+ s.date = %q{2010-04-22}
13
+ s.description = %q{simple_http: Simple Http client lib. Use to do http requests without noise.}
14
+ s.email = %q{wilkerlucio@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README",
18
+ "TODO"
19
+ ]
20
+ s.files = [
21
+ "AUTHORS",
22
+ "CHANGELOG",
23
+ "LICENSE",
24
+ "README",
25
+ "Rakefile",
26
+ "TODO",
27
+ "VERSION",
28
+ "fresh_simplehttp.gemspec",
29
+ "lib/fresh_simplehttp.rb",
30
+ "lib/simple_http.rb",
31
+ "lib/simplehttp.rb",
32
+ "setup.rb",
33
+ "simplehttp.gemspec"
34
+ ]
35
+ s.homepage = %q{http://github.com/wilkerlucio/simplehttp}
36
+ s.rdoc_options = ["--charset=UTF-8"]
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = %q{1.3.6}
39
+ s.summary = %q{simple_http: Simple Http client lib.}
40
+ s.test_files = [
41
+ "test/http_test.rb",
42
+ "test/http_test_server.rb"
43
+ ]
44
+
45
+ if s.respond_to? :specification_version then
46
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
50
+ else
51
+ end
52
+ else
53
+ end
54
+ end
55
+
@@ -0,0 +1,7 @@
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'
@@ -0,0 +1,7 @@
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,482 @@
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.5'
50
+
51
+ # Host component of proxy uri
52
+ attr_accessor :proxy_host
53
+ # Port component of proxy uri
54
+ attr_accessor :proxy_port
55
+ # Proxy User
56
+ attr_accessor :proxy_user
57
+ # Proxy Password
58
+ attr_accessor :proxy_pwd
59
+ # The +URI+ object to connect to
60
+ attr_reader :uri
61
+ # +Hash+ of headers that will be sent in the request.
62
+ attr_accessor :request_headers
63
+ # +Hash+ of headers that were set in the response.
64
+ attr_accessor :response_headers
65
+ # A +Hash+ of handlers for each class of HTTPResponse.
66
+ attr_accessor :response_handlers
67
+ # The number of redirects we should follow. Default 5.
68
+ # An exception gets raised after the fifth redirect.
69
+ attr_accessor :follow_num_redirects
70
+
71
+ RESPONSE_HANDLERS = {
72
+ Net::HTTPResponse => lambda { |request, response, http|
73
+ http._update_response_headers(response)
74
+ raise "#{response.to_s} : #{response.code} : #{http.uri}"
75
+ },
76
+ Net::HTTPSuccess => lambda { |request, response, http|
77
+ http._update_response_headers(response)
78
+ #http.cookies += response.cookies
79
+ case request
80
+ when Net::HTTP::Head, Net::HTTP::Options
81
+ http.response_headers
82
+ else
83
+ response.body
84
+ end
85
+ },
86
+ Net::HTTPRedirection => lambda { |request, response, http|
87
+ raise "too many redirects!" unless http.follow_num_redirects > 0
88
+ # create a new SimpleHttp for the location
89
+ # refered to decreasing the remaining redirects
90
+ # by one.
91
+
92
+ if (location = response['location']) !~ /^https?:\/\//
93
+ new_location = "#{http.uri.scheme}://#{http.uri.host}"
94
+ if location =~ /^\//
95
+ new_location += location
96
+ else
97
+ new_location += "/#{http.uri.path}/#{location}"
98
+ end
99
+ location = new_location
100
+ end
101
+
102
+ sh = SimpleHttp.new location
103
+ #STDERR.puts location
104
+ sh.follow_num_redirects = http.follow_num_redirects-1
105
+
106
+ # copy the response handlers used in the current
107
+ # request in case they were non standard.
108
+ sh.response_handlers = http.response_handlers
109
+
110
+ # copy the request headers
111
+ sh.request_headers=http.request_headers
112
+ sh.response_headers=http.response_headers
113
+ #sh.cookies+=http.cookies
114
+
115
+ # copy host and port
116
+ sh.uri.host = http.uri.host
117
+ sh.uri.port = http.uri.port
118
+
119
+ # HTTP doesn't permit redirects for methods other than
120
+ # GET or HEAD. The exception is 303 redirects, which
121
+ # should automatically follow the redirect URI using a
122
+ # GET method regardless of the initial method. For
123
+ # other classes of redirection, the client is required
124
+ # to prompt the user before redirection occurs. Because
125
+ # that's not a feasible action for this library, all
126
+ # 3xx redirect URIs are followed using a GET method.
127
+ #
128
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
129
+
130
+ case request
131
+ when Net::HTTP::Get,
132
+ Net::HTTP::Head,
133
+ Net::HTTP::Options
134
+ sh.get
135
+ when Net::HTTP::Post
136
+ sh.request_headers['content-length']=nil
137
+ sh.get
138
+ else
139
+ raise "Not a valid HTTP method for redirection: #{request.class}"
140
+ end
141
+
142
+ }
143
+
144
+ }
145
+
146
+ # SimpleHttp can either be used directly through the +get+ and
147
+ # +post+ class methods or be instantiated, in case you need to
148
+ # to add custom behaviour to the requests.
149
+ #
150
+ # @param may be a URI or a String.
151
+ #
152
+ # Example:
153
+ # http = SimpleHttp.new(URI.parse("http://www.example.com"))
154
+ # http = SimpleHttp.new "www.example.com"
155
+ # http = SimpleHttp.new "http://usr:pwd@www.example.com:1234"
156
+ def initialize uri
157
+ set_proxy ENV['http_proxy'] if ENV['http_proxy']
158
+
159
+ if uri.class == String
160
+ unless uri =~ /^https?:\/\//
161
+ uri = "http://#{uri}"
162
+ end
163
+ uri = URI.parse uri
164
+ end
165
+ @uri = uri
166
+
167
+ if !@uri.path || "" == @uri.path.strip
168
+ @uri.path="/"
169
+ end
170
+
171
+ @request_headers={}
172
+ @response_headers={}
173
+ @cookies=[]
174
+ @response_handlers=RESPONSE_HANDLERS.clone
175
+ @follow_num_redirects=5
176
+
177
+ if @uri.user
178
+ basic_authentication @uri.user, @uri.password
179
+ end
180
+
181
+ end
182
+
183
+ #
184
+ # Provides facilities to perform http basic authentication. You
185
+ # don't need to provide +usr+ and +pwd+ if they are already included
186
+ # in the uri, i.e. http://user:password@www.example.com/
187
+ #
188
+ # Usage:
189
+ # sh = SimpleHttp.new "www.example.com/password_protected_resource"
190
+ # sh.basic_authentication "user_name", "secret_password"
191
+ # sh.get
192
+ #
193
+
194
+ def basic_authentication usr, pwd
195
+ @basic_auth = [usr, pwd]
196
+ end
197
+
198
+ #
199
+ # This method can be used to register response handlers for specific
200
+ # http responses in case you need to override the default behaviour.
201
+ # Defaults are:
202
+ #
203
+ # <b>HTTPSuccess (200-206)</b> :: return the body of the response
204
+ # <b>HTTPRedirection (300-307)</b> :: follow the redirection until success
205
+ # *Others* :: raise an exception
206
+ #
207
+ # ===Parameters:
208
+ #
209
+ # +clazz+ is the subclass of <code>Net::HTTPResponse</code> (or +HTTPResponse+ in case you
210
+ # want to define "default" behaviour) that you are registering the
211
+ # handler for. E.g. to register a handler for a HTTP 303 response, +clazz+
212
+ # needs to be +HTTPSeeOther+.
213
+ #
214
+ # +block+ is the handler itself. When a response of the appropriate class
215
+ # is received by the library, +block+ is called with three parameters: the
216
+ # 'raw' <code>Net::HTTPRequest</code>, the actual +HTTPResponse+ object that was received
217
+ # and a reference to the instance of +SimpleHttp+ that is executing the
218
+ # call.
219
+ #
220
+ # ===Example:
221
+ #
222
+ # # to override the default action of following a HTTP
223
+ # # redirect, you could register the folllowing handler:
224
+ #
225
+ # sh = SimpleHttp "www.example.com"
226
+ # sh.register_response_handler Net::HTTPRedirection {|request, response, shttp|
227
+ # response['location']
228
+ # }
229
+ #
230
+
231
+ def register_response_handler clazz, &block
232
+ # completely unnecessary sanity check to make sure parameter
233
+ # `clazz` is in fact a HTTPResponse ...
234
+ unless clazz.ancestors.include? Net::HTTPResponse
235
+ raise "Trying to register a response handler for non-response class: #{clazz}"
236
+ end
237
+ @response_handlers[clazz]=block
238
+
239
+ end
240
+
241
+ #
242
+ # Set the proxy to use for the http request.
243
+ #
244
+ # Note: you don't need to set the proxy in case the
245
+ # +http_proxy+ environment variable is set.
246
+ #
247
+ # To override previous proxy settings and connect directly,
248
+ # call +set_proxy+ +nil+.
249
+ #
250
+ # ===Usage:
251
+ #
252
+ # http = SimpleHttp.new "www.example.com"
253
+ #
254
+ # http.set_proxy "http://proxy:8000"
255
+ # or:
256
+ # http.set_proxy(URI.parse("http://proxy:8000"))
257
+ # or:
258
+ # http.set_proxy 'proxy', '8000', 'my_user', 'secret'
259
+ # or:
260
+ # http.set_proxy nil # to override previous proxy
261
+ # settings and make the request directly.
262
+ #
263
+
264
+
265
+ def set_proxy proxy, port=nil, user=nil, pwd=nil
266
+
267
+
268
+ if !proxy
269
+ @proxy_host=@proxy_port=@proxy_user=@proxy_pwd=nil
270
+ return
271
+ end
272
+
273
+ if String === proxy
274
+ if !port && !user && !pwd
275
+ proxy = URI.parse(proxy)
276
+ else
277
+ @proxy_host= host
278
+ @proxy_port= port
279
+ @proxy_user= user
280
+ @proxy_pwd = pwd
281
+ end
282
+ end
283
+
284
+ if URI::HTTP === proxy
285
+ @proxy_host= proxy.host
286
+ @proxy_port= proxy.port
287
+ @proxy_user= proxy.user
288
+ @proxy_pwd = proxy.password
289
+ end
290
+ end
291
+
292
+ # ===Internal
293
+ # Takes a HTTPResponse (or subclass) and determines how to
294
+ # handle the response. Default behaviour is:
295
+ #
296
+ # HTTPSuccess : return the body of the response
297
+ # HTTPRedirection : follow the redirect until success.
298
+ # default : raise the HTTPResponse.
299
+ #
300
+ # the default behaviour can be overidden by registering a
301
+ # response handler using the `register_response_handler` method.
302
+ #
303
+
304
+ def _handle_response http_request, http_response
305
+ raise "Not a Net::HTTPResponse" unless http_response.is_a? Net::HTTPResponse
306
+
307
+ c = http_response.class
308
+ # Go up the inheritance chain to find the most specific handler
309
+ # for the class of response we received.
310
+ while c!=Object
311
+ # the response_handlers hash contains a handler
312
+ # for the specific response class.
313
+ if @response_handlers[c]
314
+ return @response_handlers[c].call(http_request, http_response, self)
315
+ end
316
+ c=c.superclass
317
+ end
318
+
319
+ # if we reached this place, no handler was registered
320
+ # for this response. default is to return the response.
321
+
322
+ return http_response
323
+ end
324
+
325
+ # ===Internal
326
+ #
327
+ # ===Parameter
328
+ # +request+ the <code>Net::HTTPRequest</code> to process.
329
+ def _do_http request
330
+ http = Net::HTTP.new(@uri.host, @uri.port,
331
+ @proxy_host, @proxy_port, @proxy_user, @proxy_pwd)
332
+ http.use_ssl = @uri.scheme == 'https'
333
+ request.basic_auth(@basic_auth[0], @basic_auth[1]) if @basic_auth
334
+
335
+ # add custom request headers.
336
+ @request_headers.each {|key,value|
337
+ request[key]=value;
338
+ }
339
+
340
+ response = http.request(request)
341
+ _handle_response(request, response);
342
+ end
343
+
344
+ # ===Internal
345
+ def _make_query query
346
+ return query unless query && query.class == Hash
347
+ query.inject([]) do |s, (key, value)|
348
+ s << CGI::escape(key) + "=" + CGI::escape(value)
349
+ end.join('&')
350
+ end
351
+
352
+ # Make a simple GET request to the provided URI.
353
+ #
354
+ # ===Parameter
355
+ #
356
+ # +uri+ :: the uri to connect to, may be a +URI+ or a +String+
357
+ # +query+ :: the query part of the +get+, may be a +String+ or +Hash+
358
+ #
359
+ # ===Usage:
360
+ #
361
+ # puts(SimpleHttp.get("www.example.com"))
362
+ # puts(SimpleHttp.get("www.example.com", "param"=>"value")
363
+ def self.get uri, query=nil
364
+ http = SimpleHttp.new uri
365
+ http.get query
366
+ end
367
+
368
+ # Make a simple +HEAD+ request
369
+ #
370
+ # ===Parameter
371
+ # see +get+
372
+ def self.head uri, query=nil
373
+ http = SimpleHttp.new uri
374
+ http.head query
375
+ end
376
+
377
+ # Make a simple +OPTIONS+ request
378
+ def self.options uri
379
+ http = SimpleHttp.new uri
380
+ http.options
381
+ end
382
+
383
+ # Make a simple +TRACE+ request
384
+ def self.trace uri
385
+ http = SimpleHttp.new uri
386
+ http.trace
387
+ end
388
+
389
+ # Make a POST request to the provided URI.
390
+ #
391
+ # ===Example:
392
+ # puts(SimpleHttp.post("www.example.com", "query"=>"my_query"))
393
+ #
394
+ # Alternatively, to post arbitrary data, all you need to do is
395
+ # set the appriate +content_type+:
396
+ #
397
+ # SimpleHttp.post("http://www.example.com/", binary_data, "img/png")
398
+
399
+ def self.post uri, query=nil, content_type='application/x-www-form-urlencoded'
400
+ http = SimpleHttp.new uri
401
+ http.post query, content_type
402
+ end
403
+
404
+ # Call the +get+ method as an instance method if you need to
405
+ # modify the default behaviour of the library, or set special
406
+ # headers:
407
+ #
408
+ # http = SimpleHttp.new "www.example.com"
409
+ # http.request_headers["X-Special"]="whatever"
410
+ # str = http.get
411
+ def get query = nil
412
+ req = Net::HTTP::Get.new( _handle_path(query) )
413
+ # puts Net::HTTP::Proxy(@proxy_host, @proxy_port, @proxy_user, @proxy_pwd).get(@uri)
414
+ _do_http req
415
+ end
416
+
417
+ #
418
+ # Call the +head+ method as an instance method.
419
+ # see +head+
420
+ def head query = nil
421
+ req = Net::HTTP::Head.new( _handle_path(query) )
422
+ # puts Net::HTTP::Proxy(@proxy_host, @proxy_port, @proxy_user, @proxy_pwd).get(@uri)
423
+ _do_http req
424
+ end
425
+
426
+ # Call http +options+ method. Returns the response
427
+ # see +options+
428
+ def options
429
+ # we don't support sending a payload in options' body.
430
+ req = Net::HTTP::Options.new(@uri.path)
431
+ _do_http req
432
+ end
433
+
434
+ # Call http +trace+ method. Returns the response
435
+ # see +trace+
436
+ def trace
437
+ # payload?
438
+ req = Net::HTTP::Trace.new(@uri.path)
439
+ _do_http req
440
+ end
441
+
442
+ #
443
+ # Post the query data to the url.
444
+ #
445
+ # The body of the request remains empty if query=nil.
446
+ #
447
+ # In case +query+ is a +Hash+, it's assumed that we are
448
+ # sending a form.
449
+ #
450
+ # In case +query+ is a +String+, it's also assumed that a
451
+ # form is being sent, UNLESS the +content_type+ parameter
452
+ # is set.
453
+ #
454
+ def post query=nil, content_type='application/x-www-form-urlencoded'
455
+ req = Net::HTTP::Post.new( _handle_path() )
456
+ req.body= _make_query query if query
457
+ req.content_type=content_type if query
458
+ req.content_length=query ? req.body.length : 0
459
+
460
+ _do_http req
461
+ end
462
+
463
+ def _handle_path query=nil
464
+ if (query = _make_query query)
465
+ @uri.query = @uri.query ? @uri.query+"&"+query : query
466
+ end
467
+ path = @uri.query ? "#{uri.path}?#{@uri.query}" : @uri.path
468
+ end
469
+
470
+ # ===Internal
471
+ # Used in the response handler to set the value of the
472
+ # response header fields.
473
+ def _update_response_headers http_response
474
+ http_response.each_header {|key, value|
475
+ self.response_headers[key]=value
476
+ }
477
+ end
478
+
479
+ end
480
+
481
+
482
+