httpray 1.1.1 → 1.1.2
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/Gemfile.lock +2 -3
- data/README.md +8 -2
- data/lib/httpray.rb +22 -10
- data/lib/httpray/version.rb +1 -1
- data/test/httpray_test.rb +15 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85f7ee216d286ddb7923f073086321aaad64ed36
|
4
|
+
data.tar.gz: c8a0b734b3565a1bf8a9391ce0bee417c1e015c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1f1f90d6d72dceeba9ed80b7ba01247e0043ee5933737d0f9cc17aa9f24f15393ebdd882be7c13d2afee162256eb319b0f4f562e16486b9c659ff524c276082
|
7
|
+
data.tar.gz: b84071e158ce7b043b56b77573159cd954a43983f9dfc94b56385b7acd9780303e8bca198e4c13ff281dca047dd7a6af7f1d69f834755b089dc9d4675d2b2ef7
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -43,7 +43,13 @@ socket.close
|
|
43
43
|
# use a persistent connection to keep the party rolling
|
44
44
|
# will automatically reconnect if connection is lost
|
45
45
|
uri = URI.parse("https://your.diety/pray")
|
46
|
-
ark = HTTPray::Connection.new(
|
46
|
+
ark = HTTPray::Connection.new(
|
47
|
+
uri.host,
|
48
|
+
uri.port,
|
49
|
+
1, #timeout
|
50
|
+
OpenSSL::SSL::SSLContext.new, #ssl context
|
51
|
+
1, #retries on error
|
52
|
+
10) #seconds to wait after all retries failed before trying again on a subsequent request
|
47
53
|
ark.request("POST", uri,
|
48
54
|
{"Content-Type" => "application/prayer"},
|
49
55
|
"Why did it have to be snakes?")
|
@@ -58,7 +64,7 @@ ark.request("POST", uri,
|
|
58
64
|
|
59
65
|
HTTPray has minimal convenience and sanitization features because I didn't need them. All that it does is fill in the Host, User-Agent, Accept, and Content-Length headers for you. The body must be a string, so convert it yourself first. The URI can be a `URI` or a `String` that will go through `URI.parse`. You're welcome.
|
60
66
|
|
61
|
-
If you're using `Connection` with TLS you need to provide an `OpenSSL::SSL::SSLContext` when creating the connection. `HTTPray.request!` is more forgiving and if you don't give it one it will create it for you if needed.
|
67
|
+
If you're using `Connection` with TLS you need to provide an `OpenSSL::SSL::SSLContext` when creating the connection. `HTTPray.request!` is more forgiving and if you don't give it one it will create it for you if needed. `Connection` also has some fancy retry and circuit breaker logic so you can assume your request always writes even if it doesn't without major performance impacts.
|
62
68
|
|
63
69
|
Timeout support does not extend to the response since you just get back a `Socket`. You're own your own for how you want to handle that.
|
64
70
|
|
data/lib/httpray.rb
CHANGED
@@ -6,6 +6,7 @@ require_relative 'httpray/version'
|
|
6
6
|
|
7
7
|
module HTTPray
|
8
8
|
class Timeout < StandardError; end
|
9
|
+
class CircuitBreakerError < StandardError; end
|
9
10
|
|
10
11
|
DEFAULT_HEADERS = {
|
11
12
|
"User-Agent" => "HTTPray #{VERSION}",
|
@@ -14,12 +15,14 @@ module HTTPray
|
|
14
15
|
}.freeze
|
15
16
|
|
16
17
|
class Connection
|
17
|
-
def initialize(host, port, timeout = 1, ssl_context = nil, retry_count = 1)
|
18
|
+
def initialize(host, port, timeout = 1, ssl_context = nil, retry_count = 1, retry_circuit_breaker_interval = 10)
|
18
19
|
@host = host
|
19
20
|
@port = port
|
20
21
|
@timeout = timeout
|
21
22
|
@ssl_context = ssl_context
|
22
23
|
@retry_count = retry_count
|
24
|
+
@retry_circuit_breaker_interval = retry_circuit_breaker_interval
|
25
|
+
@next_retry_time = Time.now - @retry_circuit_breaker_interval
|
23
26
|
@socket = connect
|
24
27
|
end
|
25
28
|
|
@@ -29,12 +32,13 @@ module HTTPray
|
|
29
32
|
@socket
|
30
33
|
end
|
31
34
|
|
35
|
+
def reconnect
|
36
|
+
@socket = connect unless @socket && !socket.closed?
|
37
|
+
end
|
38
|
+
|
32
39
|
def request!(method, uri, headers = {}, body = nil)
|
33
40
|
tries ||= 0
|
34
|
-
|
35
|
-
IO.select([@socket], [@socket], [@socket], @timeout) if @socket
|
36
|
-
rescue; end
|
37
|
-
@socket = connect unless @socket && !@socket.closed?
|
41
|
+
reconnect
|
38
42
|
socket = @socket
|
39
43
|
uri = URI.parse(uri) unless URI === uri
|
40
44
|
|
@@ -48,11 +52,19 @@ module HTTPray
|
|
48
52
|
socket.write_nonblock "\r\n"
|
49
53
|
socket.write_nonblock body if body
|
50
54
|
socket
|
51
|
-
rescue
|
52
|
-
@socket.close
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
rescue => error
|
56
|
+
@socket.close unless @socket.closed?
|
57
|
+
now = Time.now
|
58
|
+
if now > @next_retry_time
|
59
|
+
if tries < @retry_count
|
60
|
+
tries += 1
|
61
|
+
retry
|
62
|
+
else
|
63
|
+
@next_retry_time = now + @retry_circuit_breaker_interval
|
64
|
+
raise error
|
65
|
+
end
|
66
|
+
else
|
67
|
+
raise HTTPray::CircuitBreakerError
|
56
68
|
end
|
57
69
|
end
|
58
70
|
|
data/lib/httpray/version.rb
CHANGED
data/test/httpray_test.rb
CHANGED
@@ -106,4 +106,19 @@ class HTTPrayTest < MiniTest::Test
|
|
106
106
|
ark.request("GET", uri, {"Connection" => ""})
|
107
107
|
end
|
108
108
|
end
|
109
|
+
def test_retries_stopped_by_circuit_breaker
|
110
|
+
uri = URI.parse("http://httpbin.org/deny")
|
111
|
+
ark = HTTPray::Connection.new(uri.host, uri.port, 1, nil, 0, 2)
|
112
|
+
# force retries to expire
|
113
|
+
ark.socket.stub(:write_nonblock, lambda { |*args| raise "Broken pipe" }) do
|
114
|
+
assert_raises RuntimeError do; ark.request("GET", uri, {"Connection" => ""}); end
|
115
|
+
end
|
116
|
+
ark.stub(:reconnect, ark.socket) do #prevent reconnect of closed socket from previous error
|
117
|
+
ark.socket.stub(:write_nonblock, lambda { |*args| raise "Broken pipe" }) do
|
118
|
+
assert_raises HTTPray::CircuitBreakerError do; ark.request("GET", uri, {"Connection" => ""}); end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
sleep(2)
|
122
|
+
ark.request("GET", uri, {"Connection" => ""})
|
123
|
+
end
|
109
124
|
end
|