aitch 1.0.2 → 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 +5 -5
- data/.rubocop.yml +26 -0
- data/.travis.yml +2 -5
- data/Gemfile +2 -2
- data/README.md +11 -0
- data/Rakefile +5 -1
- data/aitch.gemspec +11 -7
- data/lib/aitch.rb +12 -13
- data/lib/aitch/configuration.rb +1 -0
- data/lib/aitch/dsl.rb +4 -3
- data/lib/aitch/engines/json.rb +2 -0
- data/lib/aitch/errors.rb +1 -0
- data/lib/aitch/ext/to_query.rb +7 -5
- data/lib/aitch/location.rb +4 -3
- data/lib/aitch/namespace.rb +35 -9
- data/lib/aitch/redirect.rb +1 -0
- data/lib/aitch/request.rb +30 -21
- data/lib/aitch/response.rb +8 -4
- data/lib/aitch/response/body.rb +1 -0
- data/lib/aitch/response/description.rb +3 -2
- data/lib/aitch/response/errors.rb +2 -1
- data/lib/aitch/response_parser.rb +8 -5
- data/lib/aitch/response_parser/default_parser.rb +2 -1
- data/lib/aitch/response_parser/html_parser.rb +1 -0
- data/lib/aitch/response_parser/json_parser.rb +1 -0
- data/lib/aitch/response_parser/xml_parser.rb +1 -0
- data/lib/aitch/uri.rb +6 -3
- data/lib/aitch/utils.rb +3 -1
- data/lib/aitch/version.rb +2 -1
- data/test/aitch/aitch_test.rb +1 -0
- data/test/aitch/configuration_test.rb +2 -1
- data/test/aitch/dsl_test.rb +1 -0
- data/test/aitch/execute_test.rb +1 -0
- data/test/aitch/namespace_test.rb +2 -1
- data/test/aitch/request/client_https_test.rb +1 -0
- data/test/aitch/request/follow_redirect_test.rb +4 -3
- data/test/aitch/request/json_request_test.rb +1 -0
- data/test/aitch/request/request_class_test.rb +3 -2
- data/test/aitch/request/status_code_validation_test.rb +3 -2
- data/test/aitch/request_test.rb +31 -6
- data/test/aitch/response/custom_response_parser_test.rb +1 -0
- data/test/aitch/response/errors_test.rb +1 -0
- data/test/aitch/response/html_response_test.rb +1 -0
- data/test/aitch/response/json_response_test.rb +2 -1
- data/test/aitch/response/raw_response_test.rb +1 -0
- data/test/aitch/response/status_3xx_test.rb +1 -0
- data/test/aitch/response/status_4xx_test.rb +1 -0
- data/test/aitch/response/status_5xx_test.rb +1 -0
- data/test/aitch/response/xml_response_test.rb +1 -0
- data/test/aitch/response_parser/html_parser_test.rb +1 -0
- data/test/aitch/response_parser/json_parser_test.rb +1 -0
- data/test/aitch/response_parser/xml_parser_test.rb +1 -1
- data/test/aitch/response_test.rb +1 -1
- data/test/aitch/uri_test.rb +2 -1
- data/test/aitch/utils/symbolize_keys_test.rb +1 -0
- data/test/aitch/utils/underscore_test.rb +1 -0
- data/test/support/helpers.rb +5 -4
- data/test/test_helper.rb +3 -2
- metadata +67 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 79fcbcbeb7a0487eb6071a17cdfe2a4ffceed98d1c1358a7e5a6613d916a0256
|
4
|
+
data.tar.gz: a302171234f54b7b6607a5c8a8eda1c8b32c3b35658e65323ccd5a5cd6403ed3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f144ceb163b3a9cd1a91649b67bc5771fb5f73dcd021846147aa7b5583eeb4a13aa2d694cd7f468ca292b14e3226f09be8b0c9dd17292bfc74bc3792eabc2707
|
7
|
+
data.tar.gz: 15974c7b5905d82798affa69f3494d6ca43b32e4f7ee4b175b350994d9627a0df04af3aa626cec9424ea31ae23da626ae212f446b79c571acb6cf39afc317d81
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
inherit_gem:
|
3
|
+
rubocop-fnando: .rubocop.yml
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
TargetRubyVersion: 2.6
|
7
|
+
|
8
|
+
Layout/LineLength:
|
9
|
+
Exclude:
|
10
|
+
- test/**/*.rb
|
11
|
+
|
12
|
+
Naming/AccessorMethodName:
|
13
|
+
Exclude:
|
14
|
+
- lib/aitch/request.rb
|
15
|
+
|
16
|
+
Metrics/ClassLength:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Metrics/AbcSize:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Metrics/MethodLength:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Metrics/ParameterLists:
|
26
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -83,6 +83,17 @@ response = Aitch.get do
|
|
83
83
|
end
|
84
84
|
```
|
85
85
|
|
86
|
+
Finally, you can use keyword arguments:
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
Aitch.get(
|
90
|
+
url: "http://example.org",
|
91
|
+
params: {a: 1, b: 2},
|
92
|
+
headers: {Authorization: "Token token=abc"},
|
93
|
+
options: {follow_redirect: false}
|
94
|
+
)
|
95
|
+
```
|
96
|
+
|
86
97
|
### Response
|
87
98
|
|
88
99
|
The response object:
|
data/Rakefile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "bundler/gem_tasks"
|
3
4
|
require "rake/testtask"
|
5
|
+
require "rubocop/rake_task"
|
4
6
|
|
5
7
|
Rake::TestTask.new(:test) do |t|
|
6
8
|
t.libs << "test"
|
@@ -8,4 +10,6 @@ Rake::TestTask.new(:test) do |t|
|
|
8
10
|
t.warning = false
|
9
11
|
end
|
10
12
|
|
11
|
-
|
13
|
+
RuboCop::RakeTask.new
|
14
|
+
|
15
|
+
task default: %i[test rubocop]
|
data/aitch.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "./lib/aitch/version"
|
2
4
|
|
3
5
|
Gem::Specification.new do |spec|
|
@@ -10,19 +12,21 @@ Gem::Specification.new do |spec|
|
|
10
12
|
spec.homepage = "http://rubygems.org/gems/aitch"
|
11
13
|
spec.license = "MIT"
|
12
14
|
|
13
|
-
spec.files = `git ls-files`.split(
|
14
|
-
spec.executables = spec.files.grep(%r{^bin/}) {
|
15
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) {|f| File.basename(f) }
|
15
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
16
18
|
spec.require_paths = ["lib"]
|
17
19
|
|
18
|
-
spec.
|
19
|
-
|
20
|
-
spec.add_dependency "nokogiri", ">= 1.6.0"
|
20
|
+
spec.add_dependency "nokogiri"
|
21
21
|
|
22
|
-
spec.add_development_dependency "codeclimate-test-reporter"
|
23
22
|
spec.add_development_dependency "bundler"
|
24
|
-
spec.add_development_dependency "
|
23
|
+
spec.add_development_dependency "minitest"
|
25
24
|
spec.add_development_dependency "minitest-utils"
|
26
25
|
spec.add_development_dependency "mocha"
|
26
|
+
spec.add_development_dependency "pry-meta"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
spec.add_development_dependency "rubocop"
|
29
|
+
spec.add_development_dependency "rubocop-fnando"
|
30
|
+
spec.add_development_dependency "simplecov"
|
27
31
|
spec.add_development_dependency "webmock"
|
28
32
|
end
|
data/lib/aitch.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "net/https"
|
3
4
|
require "forwardable"
|
4
5
|
require "json"
|
@@ -38,21 +39,19 @@ module Aitch
|
|
38
39
|
extend Forwardable
|
39
40
|
|
40
41
|
def_delegators :namespace,
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
42
|
+
:configuration, :config,
|
43
|
+
:get, :get!,
|
44
|
+
:post, :post!,
|
45
|
+
:put, :put!,
|
46
|
+
:patch, :patch!,
|
47
|
+
:options, :options!,
|
48
|
+
:trace, :trace!,
|
49
|
+
:head, :head!,
|
50
|
+
:delete, :delete!,
|
51
|
+
:execute, :execute!,
|
52
|
+
:configure
|
52
53
|
end
|
53
54
|
|
54
|
-
private
|
55
|
-
|
56
55
|
def self.namespace
|
57
56
|
@namespace ||= Namespace.new
|
58
57
|
end
|
data/lib/aitch/configuration.rb
CHANGED
data/lib/aitch/dsl.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class DSL
|
4
5
|
%w[url options headers data].each do |name|
|
5
|
-
class_eval
|
6
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
6
7
|
attr_writer :#{name}
|
7
8
|
|
8
9
|
def #{name}(*args)
|
@@ -12,8 +13,8 @@ module Aitch
|
|
12
13
|
RUBY
|
13
14
|
end
|
14
15
|
|
15
|
-
|
16
|
-
|
16
|
+
alias params data
|
17
|
+
alias body data
|
17
18
|
|
18
19
|
def to_h
|
19
20
|
{
|
data/lib/aitch/engines/json.rb
CHANGED
data/lib/aitch/errors.rb
CHANGED
data/lib/aitch/ext/to_query.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "cgi"
|
3
4
|
|
4
5
|
class Object
|
@@ -39,20 +40,21 @@ class Array
|
|
39
40
|
# Calls <tt>to_param</tt> on all its elements and joins the result with
|
40
41
|
# slashes. This is used by <tt>url_for</tt> in Action Pack.
|
41
42
|
def to_param
|
42
|
-
collect
|
43
|
+
collect(&:to_param).join "/"
|
43
44
|
end
|
44
45
|
|
45
46
|
# Converts an array into a string suitable for use as a URL query string,
|
46
47
|
# using the given +key+ as the param name.
|
47
48
|
#
|
48
|
-
# [
|
49
|
+
# ["Rails", "coding"].to_query("hobbies")
|
50
|
+
# # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
|
49
51
|
def to_query(key)
|
50
52
|
prefix = "#{key}[]"
|
51
53
|
|
52
54
|
if empty?
|
53
55
|
nil.to_query(prefix)
|
54
56
|
else
|
55
|
-
collect {
|
57
|
+
collect {|value| value.to_query(prefix) }.join "&"
|
56
58
|
end
|
57
59
|
end
|
58
60
|
end
|
@@ -78,8 +80,8 @@ class Hash
|
|
78
80
|
unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
|
79
81
|
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
80
82
|
end
|
81
|
-
end.compact.sort! *
|
83
|
+
end.compact.sort! * "&"
|
82
84
|
end
|
83
85
|
|
84
|
-
|
86
|
+
alias to_param to_query
|
85
87
|
end
|
data/lib/aitch/location.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class Location
|
4
5
|
attr_reader :redirect_stack, :current_url
|
@@ -9,7 +10,7 @@ module Aitch
|
|
9
10
|
end
|
10
11
|
|
11
12
|
def location
|
12
|
-
return current_url unless current_url.match(%r
|
13
|
+
return current_url unless current_url.match(%r{\A/})
|
13
14
|
|
14
15
|
uri = find_uri_with_host
|
15
16
|
url = ["#{uri.scheme}://#{uri.hostname}"]
|
@@ -20,8 +21,8 @@ module Aitch
|
|
20
21
|
|
21
22
|
def find_uri_with_host
|
22
23
|
redirect_stack.reverse
|
23
|
-
|
24
|
-
|
24
|
+
.map {|url| ::URI.parse(url) }
|
25
|
+
.find(&:scheme)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
data/lib/aitch/namespace.rb
CHANGED
@@ -1,16 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class Namespace
|
4
|
-
def configure
|
5
|
+
def configure
|
5
6
|
yield config
|
6
7
|
end
|
7
8
|
|
8
9
|
def config
|
9
10
|
@config ||= Configuration.new
|
10
11
|
end
|
11
|
-
|
12
|
+
alias configuration config
|
13
|
+
|
14
|
+
def execute(
|
15
|
+
request_method: nil,
|
16
|
+
url: nil,
|
17
|
+
params: nil,
|
18
|
+
data: nil,
|
19
|
+
body: nil,
|
20
|
+
headers: nil,
|
21
|
+
options: nil,
|
22
|
+
&block
|
23
|
+
)
|
24
|
+
data = data || params || body || {}
|
25
|
+
headers ||= {}
|
26
|
+
options ||= {}
|
12
27
|
|
13
|
-
def execute(request_method = nil, url = nil, data = {}, headers = {}, options = {}, &block)
|
14
28
|
if block_given?
|
15
29
|
dsl = DSL.new
|
16
30
|
dsl.instance_eval(&block)
|
@@ -33,8 +47,11 @@ module Aitch
|
|
33
47
|
end
|
34
48
|
|
35
49
|
def execute!(*args, &block)
|
36
|
-
|
50
|
+
options = extract_args!(args)
|
51
|
+
response = execute(**options, &block)
|
52
|
+
|
37
53
|
raise response.error if response.error?
|
54
|
+
|
38
55
|
response
|
39
56
|
end
|
40
57
|
|
@@ -47,14 +64,23 @@ module Aitch
|
|
47
64
|
options
|
48
65
|
trace
|
49
66
|
head
|
50
|
-
].each do |
|
51
|
-
define_method(
|
52
|
-
|
67
|
+
].each do |request_method|
|
68
|
+
define_method(request_method) do |*args, &block|
|
69
|
+
options = extract_args!(args)
|
70
|
+
execute(**options.merge(request_method: request_method), &block)
|
53
71
|
end
|
54
72
|
|
55
|
-
define_method("#{
|
56
|
-
|
73
|
+
define_method("#{request_method}!") do |*args, &block|
|
74
|
+
options = extract_args!(args)
|
75
|
+
|
76
|
+
execute!(**options.merge(request_method: request_method), &block)
|
57
77
|
end
|
58
78
|
end
|
79
|
+
|
80
|
+
private def extract_args!(args)
|
81
|
+
return args.first if args.size == 1 && args.first.is_a?(Hash)
|
82
|
+
|
83
|
+
%i[url data headers options].zip(args).to_h
|
84
|
+
end
|
59
85
|
end
|
60
86
|
end
|
data/lib/aitch/redirect.rb
CHANGED
data/lib/aitch/request.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class Request
|
4
5
|
attr_accessor :request_method
|
@@ -8,6 +9,9 @@ module Aitch
|
|
8
9
|
attr_accessor :options
|
9
10
|
attr_accessor :redirects
|
10
11
|
|
12
|
+
alias params= data=
|
13
|
+
alias body= data=
|
14
|
+
|
11
15
|
def initialize(options)
|
12
16
|
self.headers = {}
|
13
17
|
self.options = {}
|
@@ -35,7 +39,8 @@ module Aitch
|
|
35
39
|
end
|
36
40
|
|
37
41
|
def content_type
|
38
|
-
headers["Content-Type"] ||
|
42
|
+
headers["Content-Type"] ||
|
43
|
+
options.fetch(:default_headers, {})["Content-Type"]
|
39
44
|
end
|
40
45
|
|
41
46
|
def request
|
@@ -63,23 +68,26 @@ module Aitch
|
|
63
68
|
def http_method_class
|
64
69
|
Net::HTTP.const_get(request_method.to_s.capitalize)
|
65
70
|
rescue NameError
|
66
|
-
raise InvalidHTTPMethodError,
|
71
|
+
raise InvalidHTTPMethodError,
|
72
|
+
"unexpected HTTP verb: #{request_method.inspect}"
|
67
73
|
end
|
68
74
|
|
69
|
-
private
|
70
|
-
def set_body(request)
|
75
|
+
private def set_body(request)
|
71
76
|
body_data = data
|
72
77
|
body_data = data.to_h if data.respond_to?(:to_h)
|
73
|
-
body_data = ResponseParser::JSONParser.engine.dump(body_data) if content_type.to_s =~ /\bjson\b/
|
74
78
|
|
75
|
-
if
|
76
|
-
|
77
|
-
else
|
78
|
-
request.body = body_data.to_s
|
79
|
+
if content_type.to_s =~ /\bjson\b/
|
80
|
+
body_data = ResponseParser::JSONParser.engine.dump(body_data)
|
79
81
|
end
|
82
|
+
|
83
|
+
request.body = if body_data.is_a?(Hash)
|
84
|
+
Utils.build_query(body_data)
|
85
|
+
else
|
86
|
+
body_data.to_s
|
87
|
+
end
|
80
88
|
end
|
81
89
|
|
82
|
-
def set_headers(request)
|
90
|
+
private def set_headers(request)
|
83
91
|
all_headers = options.fetch(:default_headers, {}).merge(headers)
|
84
92
|
|
85
93
|
all_headers.each do |name, value|
|
@@ -88,30 +96,31 @@ module Aitch
|
|
88
96
|
end
|
89
97
|
end
|
90
98
|
|
91
|
-
def set_credentials(request)
|
99
|
+
private def set_credentials(request)
|
92
100
|
return unless options[:user] || options[:password]
|
101
|
+
|
93
102
|
request.basic_auth(options[:user], options[:password])
|
94
103
|
end
|
95
104
|
|
96
|
-
def set_https(client)
|
105
|
+
private def set_https(client)
|
97
106
|
client.use_ssl = uri.scheme == "https"
|
98
107
|
client.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
99
108
|
end
|
100
109
|
|
101
|
-
def set_timeout(client)
|
110
|
+
private def set_timeout(client)
|
102
111
|
client.read_timeout = options[:timeout]
|
103
112
|
end
|
104
113
|
|
105
|
-
def set_logger(client)
|
114
|
+
private def set_logger(client)
|
106
115
|
logger = options[:logger]
|
107
116
|
client.set_debug_output(logger) if logger
|
108
117
|
end
|
109
118
|
|
110
|
-
def set_user_agent(request)
|
119
|
+
private def set_user_agent(request)
|
111
120
|
request["User-Agent"] = options[:user_agent]
|
112
121
|
end
|
113
122
|
|
114
|
-
def set_gzip(request)
|
123
|
+
private def set_gzip(request)
|
115
124
|
request["Accept-Encoding"] = "gzip,deflate"
|
116
125
|
end
|
117
126
|
|
@@ -119,7 +128,7 @@ module Aitch
|
|
119
128
|
defined?(Net::ReadTimeout) ? Net::ReadTimeout : Timeout::Error
|
120
129
|
end
|
121
130
|
|
122
|
-
def follow_redirect(response
|
131
|
+
private def follow_redirect(response)
|
123
132
|
return response unless response.redirect?
|
124
133
|
|
125
134
|
redirect = Redirect.new(options)
|
@@ -143,18 +152,18 @@ module Aitch
|
|
143
152
|
response
|
144
153
|
end
|
145
154
|
|
146
|
-
def validate_response!(response)
|
155
|
+
private def validate_response!(response)
|
147
156
|
return unless options[:expect]
|
148
157
|
|
149
158
|
expected = [options[:expect]].flatten
|
150
159
|
return if expected.include?(response.code)
|
151
160
|
|
152
161
|
descriptions = expected
|
153
|
-
|
154
|
-
|
162
|
+
.map {|code| Response.description_for_code(code) }
|
163
|
+
.join(", ")
|
155
164
|
|
156
165
|
raise StatusCodeError,
|
157
|
-
|
166
|
+
"Expected(#{descriptions}) <=> Actual(#{response.description})"
|
158
167
|
end
|
159
168
|
end
|
160
169
|
end
|
data/lib/aitch/response.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class Response
|
4
5
|
extend Forwardable
|
@@ -17,7 +18,9 @@ module Aitch
|
|
17
18
|
end
|
18
19
|
|
19
20
|
ERRORS.each do |status_code, exception|
|
20
|
-
method_name = Utils
|
21
|
+
method_name = Utils
|
22
|
+
.underscore(exception.name.split("::").last)
|
23
|
+
.gsub("_error", "")
|
21
24
|
|
22
25
|
define_method "#{method_name}?" do
|
23
26
|
code == status_code
|
@@ -35,7 +38,7 @@ module Aitch
|
|
35
38
|
def success?
|
36
39
|
code >= 200 && code <= 399
|
37
40
|
end
|
38
|
-
|
41
|
+
alias ok? success?
|
39
42
|
|
40
43
|
def redirect?
|
41
44
|
code >= 300 && code <= 399
|
@@ -75,10 +78,11 @@ module Aitch
|
|
75
78
|
|
76
79
|
def method_missing(name, *args, &block)
|
77
80
|
return headers[name.to_s] if headers.key?(name.to_s)
|
81
|
+
|
78
82
|
super
|
79
83
|
end
|
80
84
|
|
81
|
-
def respond_to_missing?(name,
|
85
|
+
def respond_to_missing?(name, _include_private = false)
|
82
86
|
headers.key?(name.to_s)
|
83
87
|
end
|
84
88
|
|
@@ -90,6 +94,6 @@ module Aitch
|
|
90
94
|
"#<#{self.class} #{description} (#{content_type})>"
|
91
95
|
end
|
92
96
|
|
93
|
-
|
97
|
+
alias to_s inspect
|
94
98
|
end
|
95
99
|
end
|
data/lib/aitch/response/body.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class Response
|
4
5
|
DESCRIPTION = {
|
@@ -56,7 +57,7 @@ module Aitch
|
|
56
57
|
504 => "Gateway Time Out",
|
57
58
|
505 => "Version Not Supported",
|
58
59
|
507 => "Insufficient Storage",
|
59
|
-
511 => "Network Authentication Required"
|
60
|
-
}
|
60
|
+
511 => "Network Authentication Required"
|
61
|
+
}.freeze
|
61
62
|
end
|
62
63
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class Response
|
4
5
|
ERRORS = {
|
@@ -35,6 +36,6 @@ module Aitch
|
|
35
36
|
505 => VersionNotSupportedError,
|
36
37
|
507 => InsufficientStorageError,
|
37
38
|
511 => NetworkAuthenticationRequiredError
|
38
|
-
}
|
39
|
+
}.freeze
|
39
40
|
end
|
40
41
|
end
|
@@ -1,24 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
module ResponseParser
|
4
|
-
|
5
|
+
def self.parsers
|
6
|
+
@parsers ||= []
|
7
|
+
end
|
5
8
|
|
6
9
|
def self.prepend(name, parser)
|
7
10
|
unregister(name)
|
8
|
-
|
11
|
+
parsers.unshift parser
|
9
12
|
end
|
10
13
|
|
11
14
|
def self.append(name, parser)
|
12
15
|
unregister(name)
|
13
|
-
|
16
|
+
parsers << parser
|
14
17
|
end
|
15
18
|
|
16
19
|
def self.unregister(name)
|
17
|
-
|
20
|
+
parsers.delete_if {|parser| parser.type == name }
|
18
21
|
end
|
19
22
|
|
20
23
|
def self.find(content_type)
|
21
|
-
|
24
|
+
parsers.find {|parser| parser.match?(content_type) }
|
22
25
|
end
|
23
26
|
|
24
27
|
append :json, JSONParser
|
data/lib/aitch/uri.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class URI
|
4
5
|
extend Forwardable
|
@@ -12,8 +13,8 @@ module Aitch
|
|
12
13
|
|
13
14
|
begin
|
14
15
|
@uri = ::URI.parse(url)
|
15
|
-
rescue ::URI::InvalidURIError =>
|
16
|
-
raise InvalidURIError,
|
16
|
+
rescue ::URI::InvalidURIError => e
|
17
|
+
raise InvalidURIError, e
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
@@ -35,7 +36,9 @@ module Aitch
|
|
35
36
|
|
36
37
|
def query
|
37
38
|
query = [@uri.query]
|
38
|
-
|
39
|
+
if !request_has_body? && @data.respond_to?(:to_a)
|
40
|
+
query << ::URI.encode_www_form(@data.to_a)
|
41
|
+
end
|
39
42
|
query = query.compact.reject(&:empty?).join("&")
|
40
43
|
|
41
44
|
"?#{query}" unless query == ""
|
data/lib/aitch/utils.rb
CHANGED
data/lib/aitch/version.rb
CHANGED
data/test/aitch/aitch_test.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "test_helper"
|
3
4
|
|
4
5
|
class ConfigurationTest < Minitest::Test
|
@@ -16,7 +17,7 @@ class ConfigurationTest < Minitest::Test
|
|
16
17
|
end
|
17
18
|
|
18
19
|
test "sets default headers" do
|
19
|
-
assert_equal
|
20
|
+
assert_equal({}, Aitch::Configuration.new.default_headers)
|
20
21
|
end
|
21
22
|
|
22
23
|
test "configures aitch" do
|
data/test/aitch/dsl_test.rb
CHANGED
data/test/aitch/execute_test.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "test_helper"
|
3
4
|
|
4
5
|
class NamespaceTest < Minitest::Test
|
@@ -7,6 +8,6 @@ class NamespaceTest < Minitest::Test
|
|
7
8
|
ns.config.user_agent = "MyLib/1.0.0"
|
8
9
|
|
9
10
|
assert_equal "MyLib/1.0.0", ns.config.user_agent
|
10
|
-
assert_match
|
11
|
+
assert_match(/^Aitch/, Aitch.config.user_agent)
|
11
12
|
end
|
12
13
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "test_helper"
|
3
4
|
|
4
5
|
class FollowRedirectTest < Minitest::Test
|
@@ -25,9 +26,9 @@ class FollowRedirectTest < Minitest::Test
|
|
25
26
|
register_uri(:get, "http://example.org/", location: "http://example.com/", status: 301)
|
26
27
|
register_uri(:get, "http://example.com/", location: "https://example.com/", status: 301)
|
27
28
|
|
28
|
-
assert_raises(Aitch::TooManyRedirectsError)
|
29
|
+
assert_raises(Aitch::TooManyRedirectsError) do
|
29
30
|
Aitch.get("http://example.org/")
|
30
|
-
|
31
|
+
end
|
31
32
|
end
|
32
33
|
|
33
34
|
test "returns only redirection urls" do
|
@@ -50,7 +51,7 @@ class FollowRedirectTest < Minitest::Test
|
|
50
51
|
register_uri(:post, "http://example.org/hi", status: 307, location: "/hello")
|
51
52
|
register_uri(:post, "http://example.org/hello", status: 200)
|
52
53
|
|
53
|
-
response = Aitch.post("http://example.org/", {a: 1},
|
54
|
+
response = Aitch.post("http://example.org/", {a: 1}, Range: "1..100")
|
54
55
|
|
55
56
|
assert_equal "http://example.org/hello", response.url
|
56
57
|
assert_equal 200, response.code
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "test_helper"
|
3
4
|
|
4
5
|
class RequestClassTest < Minitest::Test
|
5
6
|
test "raises with invalid method" do
|
6
|
-
error = assert_raises(Aitch::InvalidHTTPMethodError)
|
7
|
+
error = assert_raises(Aitch::InvalidHTTPMethodError) do
|
7
8
|
build_request(request_method: "invalid").request
|
8
|
-
|
9
|
+
end
|
9
10
|
|
10
11
|
assert_equal %[unexpected HTTP verb: "invalid"], error.message
|
11
12
|
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "test_helper"
|
3
4
|
|
4
5
|
class StatusCodeValidationTest < Minitest::Test
|
5
6
|
test "raises exception when status code isn't valid" do
|
6
7
|
register_uri(:get, "http://example.org/", status: 404)
|
7
8
|
|
8
|
-
error = assert_raises(Aitch::StatusCodeError)
|
9
|
+
error = assert_raises(Aitch::StatusCodeError) do
|
9
10
|
Aitch.get("http://example.org/", {}, {}, expect: [200])
|
10
|
-
|
11
|
+
end
|
11
12
|
|
12
13
|
assert_equal "Expected(200 OK) <=> Actual(404 Not Found)", error.message
|
13
14
|
end
|
data/test/aitch/request_test.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "test_helper"
|
3
4
|
|
4
5
|
class RequestTest < Minitest::Test
|
5
6
|
test "sets content type" do
|
6
|
-
request = build_request(content_type:
|
7
|
-
assert_equal
|
7
|
+
request = build_request(content_type: "application/json")
|
8
|
+
assert_equal "application/json", request.content_type
|
8
9
|
end
|
9
10
|
|
10
11
|
test "raises with invalid uri" do
|
@@ -25,9 +26,11 @@ class RequestTest < Minitest::Test
|
|
25
26
|
end
|
26
27
|
|
27
28
|
test "sets user agent" do
|
28
|
-
requester = build_request
|
29
|
+
requester = build_request(headers: {"User-Agent" => "CUSTOM"})
|
29
30
|
request = requester.request
|
30
|
-
|
31
|
+
|
32
|
+
assert_equal "CUSTOM", requester.headers["User-Agent"]
|
33
|
+
assert_equal "CUSTOM", request["User-Agent"]
|
31
34
|
end
|
32
35
|
|
33
36
|
test "requests gzip encoding" do
|
@@ -50,6 +53,11 @@ class RequestTest < Minitest::Test
|
|
50
53
|
assert_equal "some body", request.body
|
51
54
|
end
|
52
55
|
|
56
|
+
test "sets request body from params key" do
|
57
|
+
request = build_request(request_method: "post", params: "some body").request
|
58
|
+
assert_equal "some body", request.body
|
59
|
+
end
|
60
|
+
|
53
61
|
test "sets json body from object" do
|
54
62
|
request = build_request(
|
55
63
|
request_method: "post",
|
@@ -66,7 +74,7 @@ class RequestTest < Minitest::Test
|
|
66
74
|
request = build_request(
|
67
75
|
request_method: "post",
|
68
76
|
data: {a: 1},
|
69
|
-
options: {json_parser: JSON, default_headers: {
|
77
|
+
options: {json_parser: JSON, default_headers: {"Content-Type" => "application/json"}}
|
70
78
|
).request
|
71
79
|
|
72
80
|
expected = {a: 1}.to_json
|
@@ -121,7 +129,7 @@ class RequestTest < Minitest::Test
|
|
121
129
|
test "performs request when using dsl" do
|
122
130
|
register_uri(:post, /.+/)
|
123
131
|
|
124
|
-
|
132
|
+
Aitch.post do
|
125
133
|
url "http://example.org/some/path"
|
126
134
|
params a: 1, b: 2
|
127
135
|
headers Rendering: "0.1"
|
@@ -134,4 +142,21 @@ class RequestTest < Minitest::Test
|
|
134
142
|
assert_equal "0.1", last_request.headers["Rendering"]
|
135
143
|
assert_equal "user:pass", Base64.decode64(last_request.headers["Authorization"].split(" ").last)
|
136
144
|
end
|
145
|
+
|
146
|
+
test "performs request when using kwargs" do
|
147
|
+
register_uri(:post, /.+/)
|
148
|
+
|
149
|
+
Aitch.post(
|
150
|
+
url: "http://example.org/some/path",
|
151
|
+
data: {a: 1, b: 2},
|
152
|
+
headers: {Rendering: "0.1"},
|
153
|
+
options: {user: "user", password: "pass"}
|
154
|
+
)
|
155
|
+
|
156
|
+
assert_equal "/some/path", last_request.uri.request_uri
|
157
|
+
assert_equal :post, last_request.method
|
158
|
+
assert_equal "a=1&b=2", last_request.body
|
159
|
+
assert_equal "0.1", last_request.headers["Rendering"]
|
160
|
+
assert_equal "user:pass", Base64.decode64(last_request.headers["Authorization"].split(" ").last)
|
161
|
+
end
|
137
162
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "test_helper"
|
3
4
|
|
4
5
|
class JsonResponseTest < Minitest::Test
|
@@ -13,6 +14,6 @@ class JsonResponseTest < Minitest::Test
|
|
13
14
|
register_uri(:get, "http://example.org/", body: "[1,2,3]", content_type: "application/json")
|
14
15
|
response = Aitch.get("http://example.org/")
|
15
16
|
|
16
|
-
assert_equal [1,2,3], response.data
|
17
|
+
assert_equal [1, 2, 3], response.data
|
17
18
|
end
|
18
19
|
end
|
data/test/aitch/response_test.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "test_helper"
|
3
4
|
|
4
5
|
class ResponseTest < Minitest::Test
|
@@ -27,7 +28,6 @@ class ResponseTest < Minitest::Test
|
|
27
28
|
end
|
28
29
|
|
29
30
|
test "deflates response" do
|
30
|
-
stdio = StringIO.new
|
31
31
|
deflated = Zlib::Deflate.deflate("Hello")
|
32
32
|
|
33
33
|
register_uri(:get, "http://example.org/", body: deflated, content_encoding: "deflate")
|
data/test/aitch/uri_test.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "test_helper"
|
3
4
|
|
4
5
|
class UriTest < Minitest::Test
|
@@ -27,7 +28,7 @@ class UriTest < Minitest::Test
|
|
27
28
|
end
|
28
29
|
|
29
30
|
test "ignores data when request has body" do
|
30
|
-
|
31
|
+
assert_nil Aitch::URI.new("http://example.org/", {c: 3}, true).query
|
31
32
|
end
|
32
33
|
|
33
34
|
test "returns request uri" do
|
data/test/support/helpers.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Minitest
|
3
4
|
class Test
|
4
5
|
def add_hash_entry(source, target, from, to)
|
@@ -6,13 +7,13 @@ module Minitest
|
|
6
7
|
end
|
7
8
|
|
8
9
|
def register_uri(http_method, url, options = {})
|
9
|
-
body = options.fetch(:body,
|
10
|
+
body = options.fetch(:body, "")
|
10
11
|
status = options.fetch(:status, 200)
|
11
12
|
headers = options.fetch(:headers, {})
|
12
13
|
|
13
|
-
add_hash_entry(options, headers, :location,
|
14
|
-
add_hash_entry(options, headers, :content_type,
|
15
|
-
add_hash_entry(options, headers, :content_encoding,
|
14
|
+
add_hash_entry(options, headers, :location, "Location")
|
15
|
+
add_hash_entry(options, headers, :content_type, "Content-Type")
|
16
|
+
add_hash_entry(options, headers, :content_encoding, "Content-Encoding")
|
16
17
|
|
17
18
|
stub_request(http_method, url)
|
18
19
|
.to_return(status: status, body: body, headers: headers)
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aitch
|
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
|
- Nando Vieira
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -16,16 +16,16 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -39,7 +39,49 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest-utils
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mocha
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry-meta
|
43
85
|
requirement: !ruby/object:Gem::Requirement
|
44
86
|
requirements:
|
45
87
|
- - ">="
|
@@ -67,7 +109,7 @@ dependencies:
|
|
67
109
|
- !ruby/object:Gem::Version
|
68
110
|
version: '0'
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
112
|
+
name: rubocop
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
72
114
|
requirements:
|
73
115
|
- - ">="
|
@@ -81,7 +123,21 @@ dependencies:
|
|
81
123
|
- !ruby/object:Gem::Version
|
82
124
|
version: '0'
|
83
125
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
126
|
+
name: rubocop-fnando
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: simplecov
|
85
141
|
requirement: !ruby/object:Gem::Requirement
|
86
142
|
requirements:
|
87
143
|
- - ">="
|
@@ -116,6 +172,7 @@ extensions: []
|
|
116
172
|
extra_rdoc_files: []
|
117
173
|
files:
|
118
174
|
- ".gitignore"
|
175
|
+
- ".rubocop.yml"
|
119
176
|
- ".travis.yml"
|
120
177
|
- CHANGELOG.md
|
121
178
|
- Gemfile
|
@@ -187,15 +244,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
187
244
|
requirements:
|
188
245
|
- - ">="
|
189
246
|
- !ruby/object:Gem::Version
|
190
|
-
version: '
|
247
|
+
version: '0'
|
191
248
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
192
249
|
requirements:
|
193
250
|
- - ">="
|
194
251
|
- !ruby/object:Gem::Version
|
195
252
|
version: '0'
|
196
253
|
requirements: []
|
197
|
-
|
198
|
-
rubygems_version: 2.5.1
|
254
|
+
rubygems_version: 3.1.2
|
199
255
|
signing_key:
|
200
256
|
specification_version: 4
|
201
257
|
summary: A simple HTTP client
|