aitch 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|