http-request 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +6 -0
- data/VERSION +1 -0
- data/lib/http_request.rb +197 -0
- metadata +69 -0
data/README
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/lib/http_request.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
# +-------------------------------------------------------------------------------+
|
2
|
+
# | HttpRequest |
|
3
|
+
# +-------------------------------------------------------------------------------+
|
4
|
+
# | Author: NuLayer Inc. / www.nulayer.com |
|
5
|
+
# +-------------------------------------------------------------------------------+
|
6
|
+
# | BSD LICENSE |
|
7
|
+
# | Copyright (c) 2007-2010, NuLayer Inc. |
|
8
|
+
# | All rights reserved. |
|
9
|
+
# | |
|
10
|
+
# | Redistribution and use in source and binary forms, with or without |
|
11
|
+
# | modification, are permitted provided that the following conditions are met: |
|
12
|
+
# | * Redistributions of source code must retain the above copyright |
|
13
|
+
# | notice, this list of conditions and the following disclaimer. |
|
14
|
+
# | * Redistributions in binary form must reproduce the above copyright |
|
15
|
+
# | notice, this list of conditions and the following disclaimer in the |
|
16
|
+
# | documentation and/or other materials provided with the distribution. |
|
17
|
+
# | * Neither the name of the <organization> nor the |
|
18
|
+
# | names of its contributors may be used to endorse or promote products |
|
19
|
+
# | derived from this software without specific prior written permission. |
|
20
|
+
# | |
|
21
|
+
# | THIS SOFTWARE IS PROVIDED BY NuLayer Inc. "AS IS" AND ANY |
|
22
|
+
# | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
23
|
+
# | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
24
|
+
# | DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
|
25
|
+
# | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
26
|
+
# | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
27
|
+
# | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
28
|
+
# | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
29
|
+
# | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
30
|
+
# | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
31
|
+
# +-------------------------------------------------------------------------------+
|
32
|
+
|
33
|
+
require 'net/http'
|
34
|
+
|
35
|
+
class HttpRequest
|
36
|
+
VERSION = '1.0.0'
|
37
|
+
|
38
|
+
class HTTPError < StandardError; end
|
39
|
+
class UnexpectedError < StandardError; end
|
40
|
+
|
41
|
+
class UnreachableError < HTTPError; end
|
42
|
+
class ConnectionResetError < HTTPError; end
|
43
|
+
class TimeoutError < HTTPError; end
|
44
|
+
class RedirectError < HTTPError; end
|
45
|
+
|
46
|
+
attr_accessor :uri
|
47
|
+
attr_accessor :header
|
48
|
+
attr_accessor :body
|
49
|
+
attr_accessor :status
|
50
|
+
|
51
|
+
|
52
|
+
def self.head(url, options={})
|
53
|
+
http = HttpRequest.new(url)
|
54
|
+
http.head(options)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.get(url, options={})
|
58
|
+
http = HttpRequest.new(url)
|
59
|
+
http.get(options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.user_agent=(user_agent)
|
63
|
+
@user_agent = user_agent
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.user_agent
|
67
|
+
@user_agent
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def initialize(url)
|
72
|
+
self.uri = url
|
73
|
+
end
|
74
|
+
|
75
|
+
def head(options={})
|
76
|
+
request(:head, options)
|
77
|
+
end
|
78
|
+
|
79
|
+
def get(options={})
|
80
|
+
request(:get, options)
|
81
|
+
end
|
82
|
+
|
83
|
+
def request(type, options={})
|
84
|
+
user_agent = options[:user_agent] || HttpRequest.user_agent || 'HttpRequest'
|
85
|
+
timeout = (options[:timeout] || 10).to_i
|
86
|
+
redirect_limit = options[:redirect_limit] || 5
|
87
|
+
output_file = options[:output_file]
|
88
|
+
content_max = options[:content_max]
|
89
|
+
|
90
|
+
# Check if we're in a redirecting loop
|
91
|
+
if redirect_limit == 0
|
92
|
+
raise RedirectError, "HTTP redirect too deep: #{uri.to_s}"
|
93
|
+
end
|
94
|
+
|
95
|
+
# Prepare the request
|
96
|
+
req_path = uri.path
|
97
|
+
req_path += "?#{uri.query}" if !uri.query.nil?
|
98
|
+
|
99
|
+
req_klass = (type == :head ? Net::HTTP::Head : Net::HTTP::Get)
|
100
|
+
req = req_klass.new(req_path, { 'User-Agent' => user_agent })
|
101
|
+
|
102
|
+
# HTTP request block
|
103
|
+
@retries = 3
|
104
|
+
begin
|
105
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
106
|
+
|
107
|
+
http.open_timeout = timeout
|
108
|
+
http.read_timeout = timeout
|
109
|
+
|
110
|
+
http.start do |http|
|
111
|
+
http.request(req) do |response|
|
112
|
+
# Save the header
|
113
|
+
self.header = response.header
|
114
|
+
self.body = nil
|
115
|
+
|
116
|
+
# Restrict downloading of content
|
117
|
+
download_content = true
|
118
|
+
if !content_max.nil? && header['content-length'].to_i > content_max
|
119
|
+
download_content = false
|
120
|
+
end
|
121
|
+
|
122
|
+
# Get the body
|
123
|
+
if download_content
|
124
|
+
if output_file
|
125
|
+
open(output_file, "w") do |f|
|
126
|
+
response.read_body { |data| f.write(data) }
|
127
|
+
end
|
128
|
+
else
|
129
|
+
self.body = response.read_body
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Handle URL Redirection
|
134
|
+
if response.kind_of?(Net::HTTPRedirection)
|
135
|
+
update_uri_location(header['location'])
|
136
|
+
request type, options.merge({ :redirect_limit => redirect_limit-1 })
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
rescue ::Errno::ENETUNREACH
|
141
|
+
raise UnreachableError, "network is unreachable: #{uri.to_s}"
|
142
|
+
rescue ::Errno::ECONNRESET, ::Errno::ECONNREFUSED, ::SocketError
|
143
|
+
raise ConnectionResetError, "connection reset by peer: #{uri.to_s}"
|
144
|
+
rescue ::Timeout::Error
|
145
|
+
raise TimeoutError, "connection timed out: #{uri.to_s}"
|
146
|
+
rescue ::Errno::EINTR => ex
|
147
|
+
# Transmission was interrupted, retry the request just once.
|
148
|
+
# This usually occurs because the process received a signal.
|
149
|
+
@retries -= 1
|
150
|
+
if @retries >= 0
|
151
|
+
retry
|
152
|
+
else
|
153
|
+
raise ex
|
154
|
+
end
|
155
|
+
rescue HTTPError => ex
|
156
|
+
# Catch exceptions that may be raised above -- not sure why we have to do this
|
157
|
+
raise ex
|
158
|
+
rescue => ex
|
159
|
+
raise UnexpectedError, "#{ex.inspect} -- #{uri.to_s}"
|
160
|
+
ensure
|
161
|
+
http.finish rescue nil
|
162
|
+
http = nil
|
163
|
+
end
|
164
|
+
|
165
|
+
return self
|
166
|
+
end
|
167
|
+
|
168
|
+
def header=(header)
|
169
|
+
return if header.nil?
|
170
|
+
@header = header
|
171
|
+
self.status = header.code.to_i
|
172
|
+
end
|
173
|
+
|
174
|
+
def reset!
|
175
|
+
self.header = nil
|
176
|
+
self.body = nil
|
177
|
+
self.status = nil
|
178
|
+
end
|
179
|
+
|
180
|
+
def uri=(url)
|
181
|
+
@uri = URI.parse(url)
|
182
|
+
@uri.path = '/' if @uri.path.empty?
|
183
|
+
reset!
|
184
|
+
end
|
185
|
+
|
186
|
+
def update_uri_location(location)
|
187
|
+
if header['location'].to_s[0].to_s.chr == '/'
|
188
|
+
url = "#{uri.scheme}://#{uri.host}"
|
189
|
+
url += ":#{uri.port}" if uri.port != 80 && uri.port != 443
|
190
|
+
url += location
|
191
|
+
else
|
192
|
+
url = location
|
193
|
+
end
|
194
|
+
|
195
|
+
self.uri = url
|
196
|
+
end
|
197
|
+
end
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: http-request
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Peter Kieltyka
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-07-21 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Simple HTTP client built with Net/HTTP
|
22
|
+
email:
|
23
|
+
- peter.kieltyka@nulayer.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- README
|
32
|
+
- VERSION
|
33
|
+
- lib/http_request.rb
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://nulayer.com
|
36
|
+
licenses: []
|
37
|
+
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
version: "0"
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 1
|
58
|
+
- 3
|
59
|
+
- 6
|
60
|
+
version: 1.3.6
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 1.3.7
|
65
|
+
signing_key:
|
66
|
+
specification_version: 3
|
67
|
+
summary: Simple HTTP client built with Net/HTTP
|
68
|
+
test_files: []
|
69
|
+
|