httpray 1.0.4 → 1.1.0
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/lib/httpray/version.rb +1 -1
- data/lib/httpray.rb +76 -37
- data/test/httpray_test.rb +43 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9797174918b5b0dc9fc4ed93712eb645aea8b623
|
4
|
+
data.tar.gz: e45eb180606696eed1a43c08de52aac61ce6f4bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82e916c0ef86af848840745586b7d2083776cf060559a98e3b4acb883f40417d74e43ec72a12d6e2eccf71f13ded205cbc03f5607f9c5e598f6049398a002f29
|
7
|
+
data.tar.gz: 0d41608e36c89f91999c1e5f252173e0aaeb555f6c0bc5a4805b0cf2b170d2ff28233f4e25b0cb642e2ea449d213677c02719956de35b917a8c40191d04c275f
|
data/lib/httpray/version.rb
CHANGED
data/lib/httpray.rb
CHANGED
@@ -12,57 +12,96 @@ module HTTPray
|
|
12
12
|
"Accept" => "*/*"
|
13
13
|
}.freeze
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
expire_time = Time.now + timeout
|
24
|
-
begin
|
25
|
-
raise Timeout if Time.now > expire_time
|
26
|
-
socket.connect_nonblock(socket_address)
|
27
|
-
rescue IO::WaitReadable, IO::WaitWritable
|
28
|
-
select_timeout = expire_time - Time.now
|
29
|
-
select_timeout = 0 if select_timeout < 0
|
30
|
-
IO.select([socket], [socket], [socket], select_timeout)
|
31
|
-
retry
|
15
|
+
class Connection
|
16
|
+
def initialize(host, port, timeout = 1, ssl_context = nil)
|
17
|
+
@host = host
|
18
|
+
@port = port
|
19
|
+
@timeout = timeout
|
20
|
+
@ssl_context = ssl_context
|
21
|
+
@socket = connect
|
32
22
|
end
|
33
23
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
socket
|
38
|
-
|
39
|
-
|
24
|
+
# public
|
25
|
+
|
26
|
+
def socket
|
27
|
+
@socket
|
28
|
+
end
|
29
|
+
|
30
|
+
def request!(method, uri, headers = {}, body = nil)
|
31
|
+
begin
|
32
|
+
IO.select([@socket], [@socket], [@socket], @timeout) if @socket
|
33
|
+
rescue; end
|
34
|
+
@socket = connect unless @socket && !@socket.closed?
|
35
|
+
socket = @socket
|
36
|
+
uri = URI.parse(uri) unless URI === uri
|
37
|
+
|
38
|
+
headers = DEFAULT_HEADERS.merge(headers).merge("Host" => uri.host)
|
39
|
+
headers["Content-Length"] = body.bytesize if body
|
40
|
+
|
41
|
+
socket.write_nonblock "#{method} #{uri.request_uri} HTTP/1.0\r\n"
|
42
|
+
headers.each do |header, value|
|
43
|
+
socket.write_nonblock "#{header}: #{value}\r\n"
|
44
|
+
end
|
45
|
+
socket.write_nonblock "\r\n"
|
46
|
+
socket.write_nonblock body if body
|
47
|
+
socket
|
48
|
+
end
|
49
|
+
|
50
|
+
def request(*args)
|
51
|
+
socket = request!(*args)
|
52
|
+
yield(socket) if block_given?
|
53
|
+
end
|
54
|
+
|
55
|
+
# private
|
56
|
+
|
57
|
+
def connect2
|
58
|
+
address = Socket.getaddrinfo(@host, nil, Socket::AF_INET).first[3]
|
59
|
+
socket_address = Socket.pack_sockaddr_in(@port, address)
|
60
|
+
|
61
|
+
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
62
|
+
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
63
|
+
|
64
|
+
expire_time = Time.now + @timeout
|
40
65
|
begin
|
41
66
|
raise Timeout if Time.now > expire_time
|
42
|
-
socket.connect_nonblock
|
67
|
+
socket.connect_nonblock(socket_address)
|
43
68
|
rescue IO::WaitReadable, IO::WaitWritable
|
44
69
|
select_timeout = expire_time - Time.now
|
45
70
|
select_timeout = 0 if select_timeout < 0
|
46
|
-
IO.select([socket
|
71
|
+
IO.select([socket], [socket], [socket], select_timeout)
|
47
72
|
retry
|
48
73
|
end
|
49
|
-
end
|
50
74
|
|
51
|
-
|
52
|
-
|
75
|
+
original_socket = socket
|
76
|
+
if @ssl_context
|
77
|
+
socket = OpenSSL::SSL::SSLSocket.new(socket, @ssl_context)
|
78
|
+
socket.hostname = @host
|
79
|
+
socket.sync_close = true
|
80
|
+
begin
|
81
|
+
raise Timeout if Time.now > expire_time
|
82
|
+
socket.connect_nonblock
|
83
|
+
rescue IO::WaitReadable, IO::WaitWritable
|
84
|
+
select_timeout = expire_time - Time.now
|
85
|
+
select_timeout = 0 if select_timeout < 0
|
86
|
+
IO.select([socket.io], [socket.io], [socket.io], select_timeout)
|
87
|
+
retry
|
88
|
+
end
|
89
|
+
end
|
90
|
+
return socket, original_socket
|
91
|
+
end
|
53
92
|
|
54
|
-
|
55
|
-
|
56
|
-
socket
|
93
|
+
def connect
|
94
|
+
socket, _ = connect2
|
95
|
+
socket
|
57
96
|
end
|
58
|
-
socket.write_nonblock "\r\n"
|
59
|
-
socket.write_nonblock body if body
|
60
|
-
return socket, original_socket
|
61
97
|
end
|
62
98
|
|
63
|
-
def self.request!(
|
64
|
-
|
65
|
-
|
99
|
+
def self.request!(method, uri, headers = {}, body = nil, timeout = 1, ssl_context = nil)
|
100
|
+
uri = URI.parse(uri) unless URI === uri
|
101
|
+
ssl_context = nil
|
102
|
+
ssl_context = OpenSSL::SSL::SSLContext.new if uri.scheme == "https"
|
103
|
+
ark = Connection.new(uri.host, uri.port, timeout, ssl_context)
|
104
|
+
ark.request!(method, uri, headers, body)
|
66
105
|
end
|
67
106
|
|
68
107
|
def self.request(*args)
|
data/test/httpray_test.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
2
|
require 'lib/httpray'
|
3
|
+
require 'benchmark'
|
4
|
+
require 'net/http'
|
3
5
|
|
4
|
-
class HTTPrayTest < MiniTest::
|
6
|
+
class HTTPrayTest < MiniTest::Test
|
5
7
|
def test_request_timesout_with_short_timeout
|
6
8
|
assert_raises HTTPray::Timeout do
|
7
9
|
HTTPray.request("GET", "httppppp://httpbin.org/status/200", {}, nil, 0)
|
@@ -42,9 +44,10 @@ class HTTPrayTest < MiniTest::Unit::TestCase
|
|
42
44
|
end
|
43
45
|
end
|
44
46
|
def test_original_socket_closed_with_ssl
|
45
|
-
|
46
|
-
|
47
|
-
|
47
|
+
uri = URI.parse("https://httpbin.org/get")
|
48
|
+
ark = HTTPray::Connection.new(uri.host, uri.port, 1, OpenSSL::SSL::SSLContext.new)
|
49
|
+
ark.socket.close
|
50
|
+
socket, original_socket = ark.connect2
|
48
51
|
refute_same socket, original_socket
|
49
52
|
refute socket.closed?
|
50
53
|
refute original_socket.closed?
|
@@ -53,9 +56,10 @@ class HTTPrayTest < MiniTest::Unit::TestCase
|
|
53
56
|
assert original_socket.closed?
|
54
57
|
end
|
55
58
|
def test_original_socket_closed_without_ssl
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
+
uri = URI.parse("http://httpbin.org/get")
|
60
|
+
ark = HTTPray::Connection.new(uri.host, uri.port, 1, nil)
|
61
|
+
ark.socket.close
|
62
|
+
socket, original_socket = ark.connect2
|
59
63
|
assert_same socket, original_socket
|
60
64
|
refute socket.closed?
|
61
65
|
refute original_socket.closed?
|
@@ -63,4 +67,36 @@ class HTTPrayTest < MiniTest::Unit::TestCase
|
|
63
67
|
assert socket.closed?
|
64
68
|
assert original_socket.closed?
|
65
69
|
end
|
70
|
+
def test_faster_than_net_http
|
71
|
+
uri = URI.parse("http://httpbin.org/delay/1")
|
72
|
+
net_http_time = Benchmark.realtime do
|
73
|
+
2.times { Net::HTTP.get(uri) }
|
74
|
+
end
|
75
|
+
httpray_time = Benchmark.realtime do
|
76
|
+
2.times { HTTPray.request("GET", uri) }
|
77
|
+
end
|
78
|
+
assert httpray_time < net_http_time
|
79
|
+
end
|
80
|
+
def test_persistent_connection_faster_than_ephemeral
|
81
|
+
uri = URI.parse("http://httpbin.org/delay/1")
|
82
|
+
persistent_time = Benchmark.realtime do
|
83
|
+
ark = HTTPray::Connection.new(uri.host, uri.port)
|
84
|
+
3.times { ark.request("GET", uri) }
|
85
|
+
end
|
86
|
+
ephemeral_time = Benchmark.realtime do
|
87
|
+
3.times { HTTPray.request("GET", uri) }
|
88
|
+
end
|
89
|
+
assert persistent_time < ephemeral_time
|
90
|
+
end
|
91
|
+
def test_reconnects_on_request_if_necessary
|
92
|
+
uri = URI.parse("http://httpbin.org/get")
|
93
|
+
ark = HTTPray::Connection.new(uri.host, uri.port, 1, nil)
|
94
|
+
original_socket = ark.socket
|
95
|
+
ark.request("GET", uri)
|
96
|
+
assert_same original_socket, ark.socket
|
97
|
+
ark.socket.close
|
98
|
+
assert original_socket.closed?
|
99
|
+
ark.request("GET", uri)
|
100
|
+
refute_same original_socket, ark.socket
|
101
|
+
end
|
66
102
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: httpray
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- G Gordon Worley III
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-07-
|
11
|
+
date: 2017-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Fire-and-forget HTTP requests for Ruby
|
14
14
|
email:
|