aitch 1.2.2 → 2.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/.github/workflows/tests.yml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +8 -0
- data/README.md +6 -1
- data/aitch.gemspec +3 -1
- data/lib/aitch/configuration.rb +21 -2
- data/lib/aitch/ext/string.rb +20 -0
- data/lib/aitch/ext/to_query.rb +70 -66
- data/lib/aitch/headers.rb +45 -0
- data/lib/aitch/location.rb +1 -1
- data/lib/aitch/request.rb +21 -11
- data/lib/aitch/response.rb +3 -5
- data/lib/aitch/utils.rb +3 -1
- data/lib/aitch/version.rb +1 -1
- data/lib/aitch.rb +2 -0
- data/test/aitch/configuration_test.rb +8 -1
- data/test/aitch/headers_test.rb +40 -0
- data/test/aitch/request_test.rb +9 -2
- data/test/aitch/response/errors_test.rb +1 -1
- data/test/aitch/response/status_3xx_test.rb +11 -2
- data/test/aitch/response_parser/xml_parser_test.rb +2 -2
- data/test/aitch/to_query_test.rb +2 -0
- data/test/support/helpers.rb +2 -3
- metadata +35 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 722d82e16f8558e3b413e03aee56424d1975de6ff41b9dd6493a86f5fd02e94a
|
|
4
|
+
data.tar.gz: 300f21a267ba36d3ba6b8c0b7e3e2db4ce7477daa0527253673b7c38c06a538b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 57e36cb6a2dbfd023dbc2c32fb4c56387bbfda4d23de23073bcd2e0db687e2b7e78f180203df7b963754c7fe2f360f69a76bc6679f97cf0cbd418621b27b496e
|
|
7
|
+
data.tar.gz: 51b3b156046f961169b3ce28659458f75d8559f6b404d12e4c48b420f556e9bf03b06311bfad4cda47c46f32c36b47989b54aa8c8318eda4136d619c63325165
|
data/.github/workflows/tests.yml
CHANGED
|
@@ -15,12 +15,12 @@ jobs:
|
|
|
15
15
|
strategy:
|
|
16
16
|
fail-fast: false
|
|
17
17
|
matrix:
|
|
18
|
-
ruby: ["
|
|
18
|
+
ruby: ["3.0", "3.1", "3.2"]
|
|
19
19
|
|
|
20
20
|
steps:
|
|
21
|
-
- uses: actions/checkout@
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
22
|
|
|
23
|
-
- uses: actions/cache@
|
|
23
|
+
- uses: actions/cache@v3
|
|
24
24
|
with:
|
|
25
25
|
path: vendor/bundle
|
|
26
26
|
key: >
|
|
@@ -31,7 +31,7 @@ jobs:
|
|
|
31
31
|
hashFiles('aitch.gemspec') }}
|
|
32
32
|
|
|
33
33
|
- name: Set up Ruby
|
|
34
|
-
uses:
|
|
34
|
+
uses: ruby/setup-ruby@v1
|
|
35
35
|
with:
|
|
36
36
|
ruby-version: ${{ matrix.ruby }}
|
|
37
37
|
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
- **2.1.0**
|
|
4
|
+
- Add support for retries.
|
|
5
|
+
- Change headers to have its own class, abstracting keys (strings, symbols,
|
|
6
|
+
casing).
|
|
7
|
+
- Move core extensions to refinements.
|
|
8
|
+
- **2.0.0**
|
|
9
|
+
- Fix error when content type is not available on response.
|
|
10
|
+
- Stop supporting old ruby versions (require 3.0+).
|
|
3
11
|
- **1.2.2**
|
|
4
12
|
- Transform header key before assigning values.
|
|
5
13
|
- **1.2.1**
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Aitch
|
|
2
2
|
|
|
3
|
-
[](https://github.com/fnando/aitch/actions/workflows/tests.yml)
|
|
4
4
|
[](https://codeclimate.com/github/fnando/aitch)
|
|
5
5
|
[](https://rubygems.org/gems/aitch)
|
|
6
6
|
[](https://rubygems.org/gems/aitch)
|
|
@@ -43,6 +43,11 @@ Aitch.configure do |config|
|
|
|
43
43
|
# Set default headers.
|
|
44
44
|
config.default_headers = {}
|
|
45
45
|
|
|
46
|
+
# Set number of retries.
|
|
47
|
+
# See Net::HTTP#max_retries to know which errors trigger a new request
|
|
48
|
+
# attempt.
|
|
49
|
+
config.retries = 1
|
|
50
|
+
|
|
46
51
|
# Set follow redirect.
|
|
47
52
|
config.follow_redirect = true
|
|
48
53
|
|
data/aitch.gemspec
CHANGED
|
@@ -11,16 +11,18 @@ Gem::Specification.new do |spec|
|
|
|
11
11
|
spec.summary = spec.description
|
|
12
12
|
spec.homepage = "http://rubygems.org/gems/aitch"
|
|
13
13
|
spec.license = "MIT"
|
|
14
|
-
spec.required_ruby_version = Gem::Requirement.new(">=
|
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
|
|
15
15
|
spec.metadata["rubygems_mfa_required"] = "true"
|
|
16
16
|
|
|
17
17
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
|
18
18
|
spec.executables = spec.files.grep(%r{^bin/}) {|f| File.basename(f) }
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
20
|
|
|
21
|
+
spec.add_dependency "base64"
|
|
21
22
|
spec.add_dependency "nokogiri"
|
|
22
23
|
|
|
23
24
|
spec.add_development_dependency "bundler"
|
|
25
|
+
spec.add_development_dependency "csv"
|
|
24
26
|
spec.add_development_dependency "minitest"
|
|
25
27
|
spec.add_development_dependency "minitest-utils"
|
|
26
28
|
spec.add_development_dependency "mocha"
|
data/lib/aitch/configuration.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Aitch
|
|
|
9
9
|
attr_accessor :timeout
|
|
10
10
|
|
|
11
11
|
# Set default headers.
|
|
12
|
-
|
|
12
|
+
attr_reader :default_headers
|
|
13
13
|
|
|
14
14
|
# Set follow redirect.
|
|
15
15
|
attr_accessor :follow_redirect
|
|
@@ -17,6 +17,20 @@ module Aitch
|
|
|
17
17
|
# Set redirection limit.
|
|
18
18
|
attr_accessor :redirect_limit
|
|
19
19
|
|
|
20
|
+
# Set number of retries. This will be set as `Net::HTTP#max_retries`.
|
|
21
|
+
# Defaults to 1 (ruby's default). Retries are triggered for the following
|
|
22
|
+
# errors:
|
|
23
|
+
#
|
|
24
|
+
# - `Net::ReadTimeout`
|
|
25
|
+
# - `IOError`
|
|
26
|
+
# - `EOFError`
|
|
27
|
+
# - `Errno::ECONNRESET`
|
|
28
|
+
# - `Errno::ECONNABORTED`
|
|
29
|
+
# - `Errno::EPIPE`
|
|
30
|
+
# - `OpenSSL::SSL::SSLError`
|
|
31
|
+
# - `Timeout::Error`
|
|
32
|
+
attr_accessor :retries
|
|
33
|
+
|
|
20
34
|
# Set the user agent.
|
|
21
35
|
attr_accessor :user_agent
|
|
22
36
|
|
|
@@ -28,13 +42,18 @@ module Aitch
|
|
|
28
42
|
|
|
29
43
|
def initialize
|
|
30
44
|
@timeout = 10
|
|
45
|
+
@retries = 1
|
|
31
46
|
@redirect_limit = 5
|
|
32
47
|
@follow_redirect = true
|
|
33
48
|
@user_agent = "Aitch/#{Aitch::VERSION} (http://rubygems.org/gems/aitch)"
|
|
34
|
-
@default_headers =
|
|
49
|
+
@default_headers = Headers.new
|
|
35
50
|
@base_url = nil
|
|
36
51
|
end
|
|
37
52
|
|
|
53
|
+
def default_headers=(headers)
|
|
54
|
+
@default_headers = Headers.new(headers)
|
|
55
|
+
end
|
|
56
|
+
|
|
38
57
|
def to_h
|
|
39
58
|
instance_variables.each_with_object({}) do |name, buffer|
|
|
40
59
|
buffer[name.to_s.tr("@", "").to_sym] = instance_variable_get(name)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aitch
|
|
4
|
+
module Ext
|
|
5
|
+
refine String do
|
|
6
|
+
def dasherize
|
|
7
|
+
unicode_normalize(:nfkd)
|
|
8
|
+
.delete("'")
|
|
9
|
+
.gsub(/[^\x00-\x7F]/, "")
|
|
10
|
+
.gsub(/([a-z\d])([A-Z])/, '\1-\2')
|
|
11
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1-\2')
|
|
12
|
+
.gsub(/[^-\w]+/xim, "-")
|
|
13
|
+
.tr("_", "-")
|
|
14
|
+
.gsub(/-+/xm, "-")
|
|
15
|
+
.gsub(/^-?(.*?)-?$/, '\1')
|
|
16
|
+
.downcase
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/aitch/ext/to_query.rb
CHANGED
|
@@ -2,80 +2,84 @@
|
|
|
2
2
|
|
|
3
3
|
require "cgi"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
module Aitch
|
|
6
|
+
module Ext
|
|
7
|
+
refine Object do
|
|
8
|
+
# Alias of <tt>to_s</tt>.
|
|
9
|
+
def to_param
|
|
10
|
+
to_s
|
|
11
|
+
end
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
end
|
|
13
|
+
# Converts an object into a string suitable for use as a URL query string,
|
|
14
|
+
# using the given <tt>key</tt> as the param name.
|
|
15
|
+
def to_query(key)
|
|
16
|
+
"#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
end
|
|
20
|
+
refine NilClass do
|
|
21
|
+
# Returns +self+.
|
|
22
|
+
def to_param
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
end
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
end
|
|
27
|
+
refine TrueClass do
|
|
28
|
+
# Returns +self+.
|
|
29
|
+
def to_param
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
end
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
end
|
|
34
|
+
refine FalseClass do
|
|
35
|
+
# Returns +self+.
|
|
36
|
+
def to_param
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
end
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
refine Array do
|
|
42
|
+
# Converts an array into a string suitable for use as a URL query string,
|
|
43
|
+
# using the given +key+ as the param name.
|
|
44
|
+
#
|
|
45
|
+
# ["Rails", "coding"].to_query("hobbies")
|
|
46
|
+
# # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
|
|
47
|
+
def to_query(key)
|
|
48
|
+
prefix = "#{key}[]"
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
if empty?
|
|
51
|
+
nil.to_query(prefix)
|
|
52
|
+
else
|
|
53
|
+
collect {|value| value.to_query(prefix) }.join "&"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
52
56
|
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
58
|
+
refine Hash do
|
|
59
|
+
# Returns a string representation of the receiver suitable for use as a URL
|
|
60
|
+
# query string:
|
|
61
|
+
#
|
|
62
|
+
# {name: 'David', nationality: 'Danish'}.to_query
|
|
63
|
+
# # => "name=David&nationality=Danish"
|
|
64
|
+
#
|
|
65
|
+
# An optional namespace can be passed to enclose key names:
|
|
66
|
+
#
|
|
67
|
+
# {name: 'David', nationality: 'Danish'}.to_query('user')
|
|
68
|
+
# # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
|
|
69
|
+
#
|
|
70
|
+
# The string pairs "key=value" that conform the query string
|
|
71
|
+
# are sorted lexicographically in ascending order.
|
|
72
|
+
#
|
|
73
|
+
# This method is also aliased as +to_param+.
|
|
74
|
+
def to_query(namespace = nil)
|
|
75
|
+
filter_map do |key, value|
|
|
76
|
+
unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
|
|
77
|
+
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
|
78
|
+
end
|
|
79
|
+
end.sort! * "&"
|
|
76
80
|
end
|
|
77
|
-
end.compact.sort! * "&"
|
|
78
|
-
end
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
alias_method :to_param, :to_query
|
|
83
|
+
end
|
|
84
|
+
end
|
|
81
85
|
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aitch
|
|
4
|
+
class Headers
|
|
5
|
+
extend Forwardable
|
|
6
|
+
include Enumerable
|
|
7
|
+
|
|
8
|
+
using Ext
|
|
9
|
+
|
|
10
|
+
def_delegators :@store, :each, :empty?, :any?
|
|
11
|
+
|
|
12
|
+
def initialize(input = {})
|
|
13
|
+
@store = {}
|
|
14
|
+
input.to_h.each {|key, value| self[key] = value }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def delete(key)
|
|
18
|
+
@store.delete(normalize_key(key))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def [](key)
|
|
22
|
+
@store[normalize_key(key)]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def []=(key, value)
|
|
26
|
+
@store[normalize_key(key)] = value
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def key?(key)
|
|
30
|
+
@store.key?(normalize_key(key))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def ==(other)
|
|
34
|
+
@store == Headers.new(other).to_h
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def to_h
|
|
38
|
+
@store.dup
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private def normalize_key(key)
|
|
42
|
+
key.to_s.dasherize
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
data/lib/aitch/location.rb
CHANGED
data/lib/aitch/request.rb
CHANGED
|
@@ -2,21 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
module Aitch
|
|
4
4
|
class Request
|
|
5
|
-
attr_accessor :request_method, :url, :data, :
|
|
5
|
+
attr_accessor :request_method, :url, :data, :options, :redirects
|
|
6
|
+
attr_reader :headers
|
|
6
7
|
|
|
7
|
-
CONTENT_TYPE = "
|
|
8
|
-
USER_AGENT = "
|
|
9
|
-
ACCEPT_ENCODING = "
|
|
8
|
+
CONTENT_TYPE = "content-type"
|
|
9
|
+
USER_AGENT = "user-agent"
|
|
10
|
+
ACCEPT_ENCODING = "accept-encoding"
|
|
10
11
|
GZIP_DEFLATE = "gzip,deflate"
|
|
11
12
|
HTTPS = "https"
|
|
12
|
-
|
|
13
|
-
JSON_RE = /\bjson\b/.freeze
|
|
13
|
+
JSON_RE = /\bjson\b/
|
|
14
14
|
|
|
15
15
|
alias params= data=
|
|
16
16
|
alias body= data=
|
|
17
17
|
|
|
18
18
|
def initialize(options)
|
|
19
|
-
|
|
19
|
+
@headers = Headers.new
|
|
20
20
|
self.options = {}
|
|
21
21
|
self.redirects = []
|
|
22
22
|
|
|
@@ -27,6 +27,10 @@ module Aitch
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def headers=(headers)
|
|
31
|
+
@headers = Headers.new(headers)
|
|
32
|
+
end
|
|
33
|
+
|
|
30
34
|
def perform
|
|
31
35
|
response = Response.new(options, client.request(request))
|
|
32
36
|
response.url = url
|
|
@@ -43,7 +47,7 @@ module Aitch
|
|
|
43
47
|
|
|
44
48
|
def content_type
|
|
45
49
|
headers[CONTENT_TYPE] ||
|
|
46
|
-
options.fetch(:default_headers, {})[CONTENT_TYPE]
|
|
50
|
+
Headers.new(options.fetch(:default_headers, {}))[CONTENT_TYPE]
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
def request
|
|
@@ -60,6 +64,7 @@ module Aitch
|
|
|
60
64
|
@client ||= Net::HTTP.new(uri.host, uri.port).tap do |client|
|
|
61
65
|
set_https(client)
|
|
62
66
|
set_timeout(client)
|
|
67
|
+
set_max_retries(client)
|
|
63
68
|
set_logger(client)
|
|
64
69
|
end
|
|
65
70
|
end
|
|
@@ -99,11 +104,12 @@ module Aitch
|
|
|
99
104
|
end
|
|
100
105
|
|
|
101
106
|
private def set_headers(request)
|
|
102
|
-
all_headers = options.fetch(:default_headers, {})
|
|
107
|
+
all_headers = Headers.new(options.fetch(:default_headers, {}))
|
|
108
|
+
.to_h
|
|
109
|
+
.merge(headers.to_h)
|
|
103
110
|
|
|
104
111
|
all_headers.each do |name, value|
|
|
105
|
-
value = value.respond_to?(:call)
|
|
106
|
-
name = name.to_s.split(HEADER_SEPARATOR_RE).map(&:capitalize).join("-")
|
|
112
|
+
value = value.call if value.respond_to?(:call)
|
|
107
113
|
request[name] = value.to_s
|
|
108
114
|
end
|
|
109
115
|
end
|
|
@@ -136,6 +142,10 @@ module Aitch
|
|
|
136
142
|
request[ACCEPT_ENCODING] = GZIP_DEFLATE
|
|
137
143
|
end
|
|
138
144
|
|
|
145
|
+
private def set_max_retries(client)
|
|
146
|
+
client.max_retries = options.fetch(:retries, 1)
|
|
147
|
+
end
|
|
148
|
+
|
|
139
149
|
def timeout_exception
|
|
140
150
|
defined?(Net::ReadTimeout) ? Net::ReadTimeout : Timeout::Error
|
|
141
151
|
end
|
data/lib/aitch/response.rb
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Aitch
|
|
4
4
|
class Response
|
|
5
|
-
extend Forwardable
|
|
6
|
-
|
|
7
5
|
JSON_STR = "json"
|
|
8
6
|
XML_STR = "xml"
|
|
9
7
|
HTML_STR = "html"
|
|
@@ -11,10 +9,9 @@ module Aitch
|
|
|
11
9
|
DOUBLE_COLON = "::"
|
|
12
10
|
SPACE_STR = " "
|
|
13
11
|
ERROR_SUFFIX = "_error"
|
|
14
|
-
X_RE = /^x
|
|
12
|
+
X_RE = /^x-/
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
attr_accessor :redirected_from, :url
|
|
14
|
+
attr_accessor :redirected_from, :url, :content_type
|
|
18
15
|
|
|
19
16
|
def self.description_for_code(code)
|
|
20
17
|
[code, DESCRIPTION[code]].compact.join(SPACE_STR)
|
|
@@ -24,6 +21,7 @@ module Aitch
|
|
|
24
21
|
@options = options
|
|
25
22
|
@http_response = http_response
|
|
26
23
|
@redirected_from = options.fetch(:redirected_from, [])
|
|
24
|
+
@content_type = http_response.content_type.to_s
|
|
27
25
|
end
|
|
28
26
|
|
|
29
27
|
ERRORS.each do |status_code, exception|
|
data/lib/aitch/utils.rb
CHANGED
data/lib/aitch/version.rb
CHANGED
data/lib/aitch.rb
CHANGED
|
@@ -16,8 +16,10 @@ end
|
|
|
16
16
|
require "aitch/utils"
|
|
17
17
|
require "aitch/uri"
|
|
18
18
|
require "aitch/dsl"
|
|
19
|
+
require "aitch/ext/string"
|
|
19
20
|
require "aitch/namespace"
|
|
20
21
|
require "aitch/location"
|
|
22
|
+
require "aitch/headers"
|
|
21
23
|
require "aitch/configuration"
|
|
22
24
|
require "aitch/errors"
|
|
23
25
|
require "aitch/engines/json"
|
|
@@ -7,6 +7,10 @@ class ConfigurationTest < Minitest::Test
|
|
|
7
7
|
assert_equal 10, Aitch::Configuration.new.timeout
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
test "sets default retries" do
|
|
11
|
+
assert_equal 1, Aitch::Configuration.new.retries
|
|
12
|
+
end
|
|
13
|
+
|
|
10
14
|
test "sets default user agent" do
|
|
11
15
|
user_agent = "Aitch/#{Aitch::VERSION} (http://rubygems.org/gems/aitch)"
|
|
12
16
|
|
|
@@ -18,7 +22,10 @@ class ConfigurationTest < Minitest::Test
|
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
test "sets default headers" do
|
|
21
|
-
|
|
25
|
+
config = Aitch::Configuration.new
|
|
26
|
+
config.default_headers = {content_type: "application/json"}
|
|
27
|
+
|
|
28
|
+
assert_equal({"content-type" => "application/json"}, config.default_headers.to_h)
|
|
22
29
|
end
|
|
23
30
|
|
|
24
31
|
test "configures aitch" do
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class HeadersTest < Minitest::Test
|
|
6
|
+
let(:headers) { Aitch::Headers.new }
|
|
7
|
+
|
|
8
|
+
test "normalizes header name" do
|
|
9
|
+
headers[:content_type] = "application/json"
|
|
10
|
+
|
|
11
|
+
assert_equal "application/json", headers["Content-Type"]
|
|
12
|
+
assert_equal "application/json", headers[:content_type]
|
|
13
|
+
assert_equal "application/json", headers["content-type"]
|
|
14
|
+
assert_equal({"content-type" => "application/json"}, headers.to_h)
|
|
15
|
+
assert headers == {"content-type" => "application/json"} # rubocop:disable Minitest/AssertEqual, Minitest/AssertOperator
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
test "implements key?" do
|
|
19
|
+
headers[:content_type] = "application/json"
|
|
20
|
+
|
|
21
|
+
assert headers.key?("Content-Type")
|
|
22
|
+
assert headers.key?("content-type")
|
|
23
|
+
assert headers.key?(:content_type)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
test "implements empty?" do
|
|
27
|
+
assert_empty headers
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test "implements any?" do
|
|
31
|
+
refute headers.any?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
test "implements delete" do
|
|
35
|
+
headers[:content_type] = "application/json"
|
|
36
|
+
headers.delete("Content-Type")
|
|
37
|
+
|
|
38
|
+
assert_empty headers
|
|
39
|
+
end
|
|
40
|
+
end
|
data/test/aitch/request_test.rb
CHANGED
|
@@ -9,6 +9,13 @@ class RequestTest < Minitest::Test
|
|
|
9
9
|
assert_equal "application/json", request.content_type
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
test "sets retries" do
|
|
13
|
+
request = build_request(options: {retries: 3})
|
|
14
|
+
|
|
15
|
+
assert_equal 3, request.options[:retries]
|
|
16
|
+
assert_equal 3, request.client.max_retries
|
|
17
|
+
end
|
|
18
|
+
|
|
12
19
|
test "raises with invalid uri" do
|
|
13
20
|
assert_raises(Aitch::InvalidURIError) { build_request(url: "\\").uri }
|
|
14
21
|
end
|
|
@@ -139,7 +146,7 @@ class RequestTest < Minitest::Test
|
|
|
139
146
|
test "sets headers from underscored headers" do
|
|
140
147
|
request = build_request(headers: {content_type: "text/plain"}).request
|
|
141
148
|
|
|
142
|
-
assert_equal "text/plain", request["
|
|
149
|
+
assert_equal "text/plain", request["content-type"]
|
|
143
150
|
end
|
|
144
151
|
|
|
145
152
|
test "executes headers with callable protocol" do
|
|
@@ -150,7 +157,7 @@ class RequestTest < Minitest::Test
|
|
|
150
157
|
|
|
151
158
|
test "sets basic auth credentials" do
|
|
152
159
|
request = build_request(options: {user: "USER", password: "PASS"}).request
|
|
153
|
-
credentials = Base64.decode64(request["Authorization"].gsub(
|
|
160
|
+
credentials = Base64.decode64(request["Authorization"].gsub("Basic ", ""))
|
|
154
161
|
|
|
155
162
|
assert_equal "USER:PASS", credentials
|
|
156
163
|
end
|
|
@@ -8,7 +8,7 @@ class ErrorsTest < Minitest::Test
|
|
|
8
8
|
|
|
9
9
|
test "detects response as #{name}" do
|
|
10
10
|
config = {}
|
|
11
|
-
http_response = stub(code: code)
|
|
11
|
+
http_response = stub(code: code, content_type: "text/html")
|
|
12
12
|
response = Aitch::Response.new(config, http_response)
|
|
13
13
|
|
|
14
14
|
assert response.public_send("#{name}?")
|
|
@@ -6,11 +6,20 @@ class Status3xxTest < Minitest::Test
|
|
|
6
6
|
setup { Aitch.configuration.follow_redirect = false }
|
|
7
7
|
|
|
8
8
|
test "sets default redirected from" do
|
|
9
|
-
|
|
9
|
+
response =
|
|
10
|
+
Aitch::Response.new({}, stub("response", content_type: "text/html"))
|
|
11
|
+
|
|
12
|
+
assert_empty response.redirected_from
|
|
10
13
|
end
|
|
11
14
|
|
|
12
15
|
test "uses provided redirected from" do
|
|
13
|
-
|
|
16
|
+
response =
|
|
17
|
+
Aitch::Response.new(
|
|
18
|
+
{redirected_from: ["URL"]},
|
|
19
|
+
stub("response", content_type: "text/html")
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
assert_equal ["URL"], response.redirected_from
|
|
14
23
|
end
|
|
15
24
|
|
|
16
25
|
test "has body" do
|
|
@@ -11,7 +11,7 @@ class XmlParserTest < Minitest::Test
|
|
|
11
11
|
test "converts ISO-8859-1 to UTF-8" do
|
|
12
12
|
xml = Aitch::ResponseParser::XMLParser.load(File.read("./test/fixtures/iso8859-1.xml"))
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
assert_includes xml.to_xml, %[<?xml version="1.0" encoding="
|
|
14
|
+
assert_match "UTF-8", xml.encoding
|
|
15
|
+
assert_includes xml.to_xml, %[<?xml version="1.0" encoding="UTF-8"?>]
|
|
16
16
|
end
|
|
17
17
|
end
|
data/test/aitch/to_query_test.rb
CHANGED
data/test/support/helpers.rb
CHANGED
|
@@ -9,14 +9,13 @@ module Minitest
|
|
|
9
9
|
def register_uri(http_method, url, options = {})
|
|
10
10
|
body = options.fetch(:body, "")
|
|
11
11
|
status = options.fetch(:status, 200)
|
|
12
|
-
headers = options.fetch(:headers,
|
|
12
|
+
headers = options.fetch(:headers, Aitch::Headers.new)
|
|
13
13
|
|
|
14
14
|
add_hash_entry(options, headers, :location, "Location")
|
|
15
15
|
add_hash_entry(options, headers, :content_type, "Content-Type")
|
|
16
16
|
add_hash_entry(options, headers, :content_encoding, "Content-Encoding")
|
|
17
17
|
|
|
18
|
-
stub_request(http_method, url)
|
|
19
|
-
.to_return(status: status, body: body, headers: headers)
|
|
18
|
+
stub_request(http_method, url).to_return(status:, body:, headers:)
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
def last_request
|
metadata
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aitch
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nando Vieira
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: base64
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
13
26
|
- !ruby/object:Gem::Dependency
|
|
14
27
|
name: nokogiri
|
|
15
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -38,6 +51,20 @@ dependencies:
|
|
|
38
51
|
- - ">="
|
|
39
52
|
- !ruby/object:Gem::Version
|
|
40
53
|
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: csv
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
41
68
|
- !ruby/object:Gem::Dependency
|
|
42
69
|
name: minitest
|
|
43
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -186,7 +213,9 @@ files:
|
|
|
186
213
|
- lib/aitch/dsl.rb
|
|
187
214
|
- lib/aitch/engines/json.rb
|
|
188
215
|
- lib/aitch/errors.rb
|
|
216
|
+
- lib/aitch/ext/string.rb
|
|
189
217
|
- lib/aitch/ext/to_query.rb
|
|
218
|
+
- lib/aitch/headers.rb
|
|
190
219
|
- lib/aitch/location.rb
|
|
191
220
|
- lib/aitch/namespace.rb
|
|
192
221
|
- lib/aitch/redirect.rb
|
|
@@ -207,6 +236,7 @@ files:
|
|
|
207
236
|
- test/aitch/configuration_test.rb
|
|
208
237
|
- test/aitch/dsl_test.rb
|
|
209
238
|
- test/aitch/execute_test.rb
|
|
239
|
+
- test/aitch/headers_test.rb
|
|
210
240
|
- test/aitch/namespace_test.rb
|
|
211
241
|
- test/aitch/request/client_https_test.rb
|
|
212
242
|
- test/aitch/request/follow_redirect_test.rb
|
|
@@ -240,7 +270,6 @@ licenses:
|
|
|
240
270
|
- MIT
|
|
241
271
|
metadata:
|
|
242
272
|
rubygems_mfa_required: 'true'
|
|
243
|
-
post_install_message:
|
|
244
273
|
rdoc_options: []
|
|
245
274
|
require_paths:
|
|
246
275
|
- lib
|
|
@@ -248,15 +277,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
248
277
|
requirements:
|
|
249
278
|
- - ">="
|
|
250
279
|
- !ruby/object:Gem::Version
|
|
251
|
-
version:
|
|
280
|
+
version: 3.0.0
|
|
252
281
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
253
282
|
requirements:
|
|
254
283
|
- - ">="
|
|
255
284
|
- !ruby/object:Gem::Version
|
|
256
285
|
version: '0'
|
|
257
286
|
requirements: []
|
|
258
|
-
rubygems_version: 3.
|
|
259
|
-
signing_key:
|
|
287
|
+
rubygems_version: 3.6.9
|
|
260
288
|
specification_version: 4
|
|
261
289
|
summary: A simple HTTP client
|
|
262
290
|
test_files: []
|