http_client 0.5.4-java → 0.6-java
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.
- checksums.yaml +4 -4
- data/http_client.gemspec +1 -1
- data/lib/http_client.rb +33 -63
- data/lib/http_client/connection_cleaner.rb +44 -0
- data/lib/http_client/response.rb +42 -0
- data/test/http_client_test.rb +4 -2
- metadata +3 -3
- data/vendor/httpasyncclient-4.0.jar +0 -0
- data/vendor/httpcore-nio-4.3.jar +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 403b72483fce3976cad0e4c0580d64fbfc01b22d
|
|
4
|
+
data.tar.gz: e55edf2579bd90611d0f841fc1cfc2fc47fc30cf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e2f9f19f8ee7755a6076321631bd6704a8064c8c9bb62205c5a633495939f4fecbf7c6f46b74ee9a714a96d4d611bb0e83372044db2c8c6e6502e2376801e184
|
|
7
|
+
data.tar.gz: f6dbd3ff72d6df7bfc0717ed0d65743880187586425e7f204717d1c100a8e9a75a7676a118170347079a62461ccff24a0f626a8714061154aebaf0dc47380415
|
data/http_client.gemspec
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = "http_client"
|
|
3
|
-
s.version = "0.
|
|
3
|
+
s.version = "0.6"
|
|
4
4
|
s.date = "2013-11-08"
|
|
5
5
|
s.summary = "HTTP client for JRuby"
|
|
6
6
|
s.description = "This library wraps the Apache HTTPClient (4.3) in a simple fashion. The library is intended to be used in a multithreaded environment."
|
data/lib/http_client.rb
CHANGED
|
@@ -6,6 +6,8 @@ require "java"
|
|
|
6
6
|
%w[httpcore-4.3 httpclient-4.3.1 httpmime-4.3.1 commons-logging-1.1.3].each do |jar|
|
|
7
7
|
require File.expand_path("../../vendor/#{jar}.jar", __FILE__)
|
|
8
8
|
end
|
|
9
|
+
require "http_client/response"
|
|
10
|
+
require "http_client/connection_cleaner"
|
|
9
11
|
|
|
10
12
|
class HttpClient
|
|
11
13
|
import org.apache.http.impl.client.HttpClients
|
|
@@ -36,49 +38,15 @@ class HttpClient
|
|
|
36
38
|
class Timeout < Error; end
|
|
37
39
|
class IOError < Error; end
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def initialize(closeable_response)
|
|
43
|
-
@status = closeable_response.status_line.status_code
|
|
44
|
-
@headers = closeable_response.get_all_headers.inject({}) do |headers, header|
|
|
45
|
-
headers[header.name] = header.value
|
|
46
|
-
headers
|
|
47
|
-
end
|
|
48
|
-
@body = read_body(closeable_response)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def success?
|
|
52
|
-
@status >= 200 && @status <= 206
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def json_body(options = {})
|
|
56
|
-
@json_body ||= JSON.parse(body, options)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
private
|
|
60
|
-
|
|
61
|
-
def read_body(closeable_response)
|
|
62
|
-
return "" unless entity = closeable_response.entity
|
|
63
|
-
return "" unless entity.is_chunked? || entity.content_length > 0
|
|
64
|
-
if content_encoding = entity.content_encoding
|
|
65
|
-
entity = case content_encoding.value
|
|
66
|
-
when "gzip", "x-gzip" then
|
|
67
|
-
GzipDecompressingEntity.new(entity)
|
|
68
|
-
when "deflate" then
|
|
69
|
-
DeflateDecompressingEntity.new(entity)
|
|
70
|
-
else
|
|
71
|
-
entity
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
EntityUtils.to_string(entity, "UTF-8")
|
|
75
|
-
end
|
|
41
|
+
@lock = Mutex.new
|
|
42
|
+
def self.connection_cleaner
|
|
43
|
+
@lock.synchronize { @connection_cleaner ||= ConnectionCleaner.new }
|
|
76
44
|
end
|
|
77
45
|
|
|
78
|
-
attr_reader :client, :
|
|
46
|
+
attr_reader :client, :config
|
|
79
47
|
|
|
80
|
-
def initialize(
|
|
81
|
-
|
|
48
|
+
def initialize(config = {})
|
|
49
|
+
@config = {
|
|
82
50
|
:use_connection_pool => false,
|
|
83
51
|
:max_connections => 20,
|
|
84
52
|
:max_connections_per_route => nil,
|
|
@@ -87,14 +55,13 @@ class HttpClient
|
|
|
87
55
|
:connection_request_timeout => 100,
|
|
88
56
|
:connect_timeout => 1000,
|
|
89
57
|
:socket_timeout => 2000,
|
|
58
|
+
:max_idle => 5,
|
|
59
|
+
:use_connection_cleaner => true,
|
|
90
60
|
:default_request_options => {}
|
|
91
|
-
}.merge(
|
|
92
|
-
@request_config = create_request_config
|
|
93
|
-
@connection_manager = create_connection_manager
|
|
61
|
+
}.merge(config)
|
|
62
|
+
@request_config = create_request_config
|
|
63
|
+
@connection_manager = create_connection_manager
|
|
94
64
|
@client = HttpClients.create_minimal(@connection_manager)
|
|
95
|
-
@max_retries = options[:max_retries]
|
|
96
|
-
@response_class = options[:response_class]
|
|
97
|
-
@default_request_options = options[:default_request_options]
|
|
98
65
|
end
|
|
99
66
|
|
|
100
67
|
def get(uri, options = {})
|
|
@@ -140,7 +107,7 @@ class HttpClient
|
|
|
140
107
|
end
|
|
141
108
|
|
|
142
109
|
def pool_stats
|
|
143
|
-
|
|
110
|
+
return unless @connection_manager.is_a?(PoolingHttpClientConnectionManager)
|
|
144
111
|
total_stats = @connection_manager.total_stats
|
|
145
112
|
Hash(
|
|
146
113
|
:idle => total_stats.available,
|
|
@@ -150,7 +117,7 @@ class HttpClient
|
|
|
150
117
|
)
|
|
151
118
|
end
|
|
152
119
|
|
|
153
|
-
def cleanup_connections(max_idle =
|
|
120
|
+
def cleanup_connections(max_idle = config[:max_idle])
|
|
154
121
|
@connection_manager.close_idle_connections(max_idle, TimeUnit::SECONDS)
|
|
155
122
|
end
|
|
156
123
|
|
|
@@ -161,10 +128,10 @@ class HttpClient
|
|
|
161
128
|
private
|
|
162
129
|
|
|
163
130
|
def execute(request)
|
|
164
|
-
retries = max_retries
|
|
131
|
+
retries = config[:max_retries]
|
|
165
132
|
begin
|
|
166
133
|
closeable_response = client.execute(request)
|
|
167
|
-
response_class.new(closeable_response)
|
|
134
|
+
config[:response_class].new(closeable_response)
|
|
168
135
|
rescue ConnectTimeoutException, SocketTimeoutException => e
|
|
169
136
|
retry if (retries -= 1) > 0
|
|
170
137
|
raise Timeout, "#{e.message}"
|
|
@@ -181,7 +148,7 @@ private
|
|
|
181
148
|
def create_request(method_class, uri, options)
|
|
182
149
|
request = method_class.new(uri)
|
|
183
150
|
request.config = @request_config
|
|
184
|
-
options = default_request_options.merge(options)
|
|
151
|
+
options = config[:default_request_options].merge(options)
|
|
185
152
|
set_basic_auth(request, options[:basic_auth])
|
|
186
153
|
options[:headers].each do |name, value|
|
|
187
154
|
request.set_header(name.to_s.gsub("_", "-"), value)
|
|
@@ -209,23 +176,26 @@ private
|
|
|
209
176
|
end
|
|
210
177
|
end
|
|
211
178
|
|
|
212
|
-
def create_request_config
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
179
|
+
def create_request_config
|
|
180
|
+
request_config = RequestConfig.custom
|
|
181
|
+
request_config.set_stale_connection_check_enabled(true)
|
|
182
|
+
request_config.set_connection_request_timeout(config[:connection_request_timeout])
|
|
183
|
+
request_config.set_connect_timeout(config[:connect_timeout])
|
|
184
|
+
request_config.set_socket_timeout(config[:socket_timeout])
|
|
185
|
+
request_config.build
|
|
219
186
|
end
|
|
220
187
|
|
|
221
|
-
def create_connection_manager
|
|
222
|
-
|
|
188
|
+
def create_connection_manager
|
|
189
|
+
config[:use_connection_pool] ? create_pooling_connection_manager : BasicHttpClientConnectionManager.new
|
|
223
190
|
end
|
|
224
191
|
|
|
225
|
-
def create_pooling_connection_manager
|
|
192
|
+
def create_pooling_connection_manager
|
|
226
193
|
connection_manager = PoolingHttpClientConnectionManager.new
|
|
227
|
-
connection_manager.max_total =
|
|
228
|
-
connection_manager.default_max_per_route =
|
|
194
|
+
connection_manager.max_total = config[:max_connections]
|
|
195
|
+
connection_manager.default_max_per_route = config[:max_connections_per_route] || config[:max_connections]
|
|
196
|
+
connection_manager.max_total = config[:max_connections]
|
|
197
|
+
connection_manager.default_max_per_route = config[:max_connections_per_route] || config[:max_connections]
|
|
198
|
+
self.class.connection_cleaner.register(self) if config[:use_connection_cleaner]
|
|
229
199
|
connection_manager
|
|
230
200
|
end
|
|
231
201
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require "weakref"
|
|
2
|
+
|
|
3
|
+
class HttpClient
|
|
4
|
+
|
|
5
|
+
class ConnectionCleaner
|
|
6
|
+
|
|
7
|
+
attr_reader :min_idle
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@lock = Mutex.new
|
|
11
|
+
@references = []
|
|
12
|
+
@thread = Thread.new { work until @shutdown }
|
|
13
|
+
@min_idle = 5
|
|
14
|
+
@shutdown = false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def register(client)
|
|
18
|
+
@lock.synchronize do
|
|
19
|
+
@min_idle = [@min_idle, [1, client.config[:max_idle]].max].min
|
|
20
|
+
@references.push(WeakRef.new(client))
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def work
|
|
25
|
+
sleep min_idle
|
|
26
|
+
@lock.synchronize do
|
|
27
|
+
@references = @references.map do |client|
|
|
28
|
+
begin
|
|
29
|
+
client.cleanup_connections
|
|
30
|
+
client
|
|
31
|
+
rescue
|
|
32
|
+
nil
|
|
33
|
+
end
|
|
34
|
+
end.compact
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def shutdown
|
|
39
|
+
@shutdown = true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class HttpClient
|
|
2
|
+
|
|
3
|
+
class Response
|
|
4
|
+
attr_reader :status, :body, :headers
|
|
5
|
+
|
|
6
|
+
def initialize(closeable_response)
|
|
7
|
+
@status = closeable_response.status_line.status_code
|
|
8
|
+
@headers = closeable_response.all_headers.inject({}) do |headers, header|
|
|
9
|
+
headers[header.name] = header.value
|
|
10
|
+
headers
|
|
11
|
+
end
|
|
12
|
+
@body = read_body(closeable_response)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def success?
|
|
16
|
+
status >= 200 && status <= 206
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def json_body(options = {})
|
|
20
|
+
@json_body ||= JSON.parse(body, options)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def read_body(closeable_response)
|
|
26
|
+
return "" unless entity = closeable_response.entity
|
|
27
|
+
return "" unless entity.is_chunked? || entity.content_length > 0
|
|
28
|
+
if content_encoding = entity.content_encoding
|
|
29
|
+
entity = case content_encoding.value
|
|
30
|
+
when "gzip", "x-gzip" then
|
|
31
|
+
GzipDecompressingEntity.new(entity)
|
|
32
|
+
when "deflate" then
|
|
33
|
+
DeflateDecompressingEntity.new(entity)
|
|
34
|
+
else
|
|
35
|
+
entity
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
EntityUtils.to_string(entity, "UTF-8")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
data/test/http_client_test.rb
CHANGED
|
@@ -6,7 +6,9 @@ require "minitest/pride"
|
|
|
6
6
|
require "minitest/autorun"
|
|
7
7
|
require "json"
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
# Rubygems would do this for us when loading the gem
|
|
10
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
|
11
|
+
require "http_client"
|
|
10
12
|
|
|
11
13
|
def Hash(h); h; end
|
|
12
14
|
|
|
@@ -86,7 +88,7 @@ class HttpClientTest < Minitest::Test
|
|
|
86
88
|
end
|
|
87
89
|
|
|
88
90
|
# # Content-Type precedence
|
|
89
|
-
#
|
|
91
|
+
#
|
|
90
92
|
# client.post("http://httpbin.org/post",
|
|
91
93
|
# :headers => {
|
|
92
94
|
# :content_type => "application/xml"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: http_client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: '0.6'
|
|
5
5
|
platform: java
|
|
6
6
|
authors:
|
|
7
7
|
- Lukas Rieder
|
|
@@ -22,12 +22,12 @@ files:
|
|
|
22
22
|
- LICENSE
|
|
23
23
|
- README.md
|
|
24
24
|
- lib/http_client.rb
|
|
25
|
+
- lib/http_client/connection_cleaner.rb
|
|
26
|
+
- lib/http_client/response.rb
|
|
25
27
|
- test/http_client_test.rb
|
|
26
28
|
- vendor/commons-logging-1.1.3.jar
|
|
27
|
-
- vendor/httpasyncclient-4.0.jar
|
|
28
29
|
- vendor/httpclient-4.3.1.jar
|
|
29
30
|
- vendor/httpcore-4.3.jar
|
|
30
|
-
- vendor/httpcore-nio-4.3.jar
|
|
31
31
|
- vendor/httpmime-4.3.1.jar
|
|
32
32
|
homepage: https://github.com/Overbryd/http_client
|
|
33
33
|
licenses:
|
|
Binary file
|
data/vendor/httpcore-nio-4.3.jar
DELETED
|
Binary file
|