http_client 0.5.4-java → 0.6-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|