httpray 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 40bd4048bb72f0169b178246b13b20f86504eba4
4
+ data.tar.gz: 28642af4d6aeb959c948d24e6fb122e17cccb197
5
+ SHA512:
6
+ metadata.gz: 5ea297d70ed2aaf3acf4dda9ad65248a0158a49340d509394c3ce7631497486ad930a035ad43a9b0686e26a6edae6886a20b36fa0828cbfdf7c37682bbb3bc3f
7
+ data.tar.gz: bb5d0f9279feeb73b69d2a13eb54ad0516ef7ff8bef36437a701761176cd66dec66c286daac11184e795bb747a0534e001a13335446f7dab6a1495cfd2b2d522
data/.gitignore ADDED
@@ -0,0 +1,54 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
51
+
52
+ # vim temp files
53
+ *.swp
54
+ *.un~
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 2.1.5
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,18 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ HTTPray (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+
10
+ PLATFORMS
11
+ ruby
12
+
13
+ DEPENDENCIES
14
+ HTTPray!
15
+ bundler (>= 1.2)
16
+
17
+ BUNDLED WITH
18
+ 1.13.6
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 G Gordon Worley III
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # httpray
2
+ Non-blocking HTTP library for Ruby
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/HTTPray.svg)](https://badge.fury.io/rb/HTTPray)
5
+
6
+ Started out the same as the [fire-and-forget](https://github.com/mattetti/fire-and-forget) gem but with a more exposed interface, TLS support, and a better name. Added ideas from [tcp_timeout](https://github.com/lann/tcp-timeout-ruby) and accidentally ended up creating a light-weight, non-blocking HTTP client.
7
+
8
+ It differs from other Ruby HTTP libraries that support async because it doesn't use Threads, making HTTPray much less resource intensive to use since it instead directly implements HTTP/HTTPS 1.0 using `Socket` and `IO#select` for timeouts. You can optionally ask to be handed back the socket before it is closed in case you want to listen for a response, but that's not really what you're here for, and it creates a Fiber.
9
+
10
+ Great for use with sending data to HTTP endpoints for which you are willing to accept a UDP-style best-effort approach, but with the added guarantee of TCP that the packets made it to the server. Only the server will know what it did with the data, though!
11
+
12
+ ## Install
13
+
14
+ ```ruby
15
+ gem "httpray"
16
+ ```
17
+
18
+ ## Use
19
+
20
+ ```ruby
21
+ require 'httpray'
22
+
23
+ # def HTTParty.request!(method, uri, headers = {}, body = "", timeout = 1, ssl_context = nil)
24
+
25
+ # send an HTTP request and don't listen for the response
26
+ HTTPray.request(
27
+ "POST",
28
+ "https://your.diety/prayers",
29
+ {"Content-Type" => "application/prayer"},
30
+ "It's me, Margret",
31
+ 1) # timeout in seconds
32
+
33
+ # party with a response
34
+ HTTPray.request("GET", "https://your.diety/answered_prayers") do |socket|
35
+ socket.gets
36
+ end
37
+
38
+ # party dangerously (you have to close your own socket!)
39
+ socket = HTTPray.request!("GET", "https://your.diety/answered_prayers")
40
+ puts socket.gets
41
+ socket.close
42
+ ```
43
+
44
+ ## Help
45
+
46
+ 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. You can also pass an `OpenSSL::SSL::SSLContext` if you want more control over how TLS is used, but if you don't provide one it will be created for you if needed.
47
+
48
+ 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.
49
+
50
+ If you want it to be easier to use, feel free to submit pull requests. As long as you don't break existing functionality I will probably accept them.
51
+
52
+ ## Tests
53
+
54
+ There are some tests that exercise the code paths. You can run them with:
55
+
56
+ ```bash
57
+ ruby -I . test/httparty_test.rb
58
+ ```
59
+
60
+ Unfortunately they have to hit real network endpoints, so they won't work without a network.
data/httpray.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'httpray/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "httpray"
7
+ spec.version = HTTPray::VERSION
8
+ spec.authors = ["G Gordon Worley III"]
9
+ spec.email = ["gworley3@gmail.com"]
10
+ spec.description = %q{Fire-and-forget HTTP requests for Ruby}
11
+ spec.summary = %q{Like UDP but for HTTP over TCP}
12
+ spec.homepage = "https://github.com/gworley3/httpray"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.post_install_message = "HTT🙏 for mercy"
21
+ end
@@ -0,0 +1,3 @@
1
+ module HTTPray
2
+ VERSION = "1.0.2".freeze
3
+ end
data/lib/httpray.rb ADDED
@@ -0,0 +1,76 @@
1
+ require 'uri'
2
+ require 'openssl'
3
+ require 'socket'
4
+
5
+ require_relative 'httpray/version'
6
+
7
+ module HTTPray
8
+ class Timeout < StandardError; end
9
+
10
+ DEFAULT_HEADERS = {
11
+ "User-Agent" => "HTTPray #{VERSION}",
12
+ "Accept" => "*/*"
13
+ }.freeze
14
+
15
+ def self.request2!(method, uri, headers = {}, body = "", timeout = 1, ssl_context = nil)
16
+ uri = URI.parse(uri) unless URI === uri
17
+ address = Socket.getaddrinfo(uri.host, nil, Socket::AF_INET).first[3]
18
+ socket_address = Socket.pack_sockaddr_in(uri.port, address)
19
+
20
+ socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
21
+ socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
22
+
23
+ begin
24
+ socket.connect_nonblock(socket_address)
25
+ rescue Errno::EINPROGRESS
26
+ if IO.select(nil, [socket], [socket], timeout)
27
+ begin
28
+ socket.connect_nonblock(socket_address)
29
+ rescue Errno::EISCONN
30
+ # connected
31
+ end
32
+ else
33
+ raise Timeout
34
+ end
35
+ end
36
+
37
+ original_socket = socket
38
+ if uri.scheme == "https"
39
+ ssl_context ||= OpenSSL::SSL::SSLContext.new
40
+ socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
41
+ socket.hostname = uri.host
42
+ socket.sync_close = true
43
+ socket.connect
44
+ end
45
+
46
+ headers = DEFAULT_HEADERS.merge(headers).merge(
47
+ "Host" => uri.host,
48
+ "Content-Length" => body.bytesize)
49
+
50
+ if IO.select(nil, [socket], [socket], 1)
51
+ socket.puts "#{method} #{uri.request_uri} HTTP/1.0\r\n"
52
+ headers.each do |header, value|
53
+ socket.puts "#{header}: #{value}\r\n"
54
+ end
55
+ socket.puts "\r\n"
56
+ socket.puts body
57
+
58
+ yield(socket) if block_given?
59
+ else
60
+ raise Timeout
61
+ end
62
+ return socket, original_socket
63
+ end
64
+
65
+ def self.request!(*args)
66
+ socket, _ = request2!(*args)
67
+ socket
68
+ end
69
+
70
+ def self.request(*args)
71
+ socket = request!(*args)
72
+ yield(socket) if block_given?
73
+ ensure
74
+ socket.close if socket && !socket.closed?
75
+ end
76
+ end
@@ -0,0 +1,56 @@
1
+ require 'minitest/autorun'
2
+ require 'lib/httpray'
3
+
4
+ class HTTPrayTest < MiniTest::Unit::TestCase
5
+ def test_request_timesout_with_bad_address
6
+ assert_raises HTTPray::Timeout do
7
+ HTTPray.request("GET", "httppppp://httpbin.org/status/200")
8
+ end
9
+ end
10
+ def test_request_sends
11
+ HTTPray.request("GET", "http://httpbin.org/get")
12
+ assert true
13
+ end
14
+ def test_request_receives_response
15
+ HTTPray.request("GET", "http://httpbin.org/status/200") do |socket|
16
+ assert_equal "HTTP/1.1 200 OK\r\n", socket.gets
17
+ end
18
+ end
19
+ def test_secure_request_sends
20
+ HTTPray.request("GET", "https://httpbin.org/get")
21
+ assert true
22
+ end
23
+ def test_all_options_accepted
24
+ HTTPray.request(
25
+ "POST",
26
+ "https://httpbin.org/post",
27
+ {"Content-Type" => "application/x-www-form-urlencoded"},
28
+ "q=httpray",
29
+ 5,
30
+ OpenSSL::SSL::SSLContext.new) do |socket|
31
+ assert_equal "HTTP/1.1 200 OK\r\n", socket.gets
32
+ end
33
+ end
34
+ def test_original_socket_closed_with_ssl
35
+ socket, original_socket = HTTPray.request2!(
36
+ "GET",
37
+ "https://httpbin.org/delay/10")
38
+ refute_same socket, original_socket
39
+ refute socket.closed?
40
+ refute original_socket.closed?
41
+ socket.close
42
+ assert socket.closed?
43
+ assert original_socket.closed?
44
+ end
45
+ def test_original_socket_closed_without_ssl
46
+ socket, original_socket = HTTPray.request2!(
47
+ "GET",
48
+ "http://httpbin.org/delay/10")
49
+ assert_same socket, original_socket
50
+ refute socket.closed?
51
+ refute original_socket.closed?
52
+ socket.close
53
+ assert socket.closed?
54
+ assert original_socket.closed?
55
+ end
56
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: httpray
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - G Gordon Worley III
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Fire-and-forget HTTP requests for Ruby
14
+ email:
15
+ - gworley3@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".tool-versions"
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - LICENSE
25
+ - README.md
26
+ - httpray.gemspec
27
+ - lib/httpray.rb
28
+ - lib/httpray/version.rb
29
+ - test/httpray_test.rb
30
+ homepage: https://github.com/gworley3/httpray
31
+ licenses:
32
+ - MIT
33
+ metadata: {}
34
+ post_install_message: "HTT\U0001F64F for mercy"
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 2.2.2
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: Like UDP but for HTTP over TCP
54
+ test_files:
55
+ - test/httpray_test.rb