aitch 1.1.0 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79fcbcbeb7a0487eb6071a17cdfe2a4ffceed98d1c1358a7e5a6613d916a0256
4
- data.tar.gz: a302171234f54b7b6607a5c8a8eda1c8b32c3b35658e65323ccd5a5cd6403ed3
3
+ metadata.gz: a3f4cd3269e5b709f85e34148b2ed6aad4a9080f9903dc625d4840d8ffc2293a
4
+ data.tar.gz: d97a344ec31e5f6ba528f1d359b96aa2860ab51e1cdde507d5cbc0557e9a75a4
5
5
  SHA512:
6
- metadata.gz: f144ceb163b3a9cd1a91649b67bc5771fb5f73dcd021846147aa7b5583eeb4a13aa2d694cd7f468ca292b14e3226f09be8b0c9dd17292bfc74bc3792eabc2707
7
- data.tar.gz: 15974c7b5905d82798affa69f3494d6ca43b32e4f7ee4b175b350994d9627a0df04af3aa626cec9424ea31ae23da626ae212f446b79c571acb6cf39afc317d81
6
+ metadata.gz: a11acc6e165677b372cd4c9a07b9fd33640611a056fb1c437917ffa1d89ab0520bcaf9943cd5e8f72a3f088942a8f7b9d968a59ec7207dc6a061f54364216aba
7
+ data.tar.gz: a0228f9d4719ee0fddd2932fece69c454062d40f4526612b41044168198f7ec91478267163e343a995ceb5f8bbcdc1d4d228d8edb73a9845b5aa0d08145581c9
@@ -0,0 +1,3 @@
1
+ ---
2
+ github: [fnando]
3
+ custom: ["https://www.paypal.me/nandovieira/🍕"]
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: Tests
3
+
4
+ on:
5
+ pull_request:
6
+ branches:
7
+ - main
8
+ push:
9
+ branches:
10
+ - main
11
+ jobs:
12
+ build:
13
+ name: Tests with Ruby ${{ matrix.ruby }}
14
+ runs-on: "ubuntu-latest"
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ ruby: ["2.7.x", "2.6.x", "2.5.x", "3.0.x", "3.1.x"]
19
+
20
+ steps:
21
+ - uses: actions/checkout@v1
22
+
23
+ - uses: actions/cache@v2
24
+ with:
25
+ path: vendor/bundle
26
+ key: >
27
+ ${{ runner.os }}-${{ matrix.ruby }}-gems-${{
28
+ hashFiles('aitch.gemspec') }}
29
+ restore-keys: >
30
+ ${{ runner.os }}-${{ matrix.ruby }}-gems-${{
31
+ hashFiles('aitch.gemspec') }}
32
+
33
+ - name: Set up Ruby
34
+ uses: actions/setup-ruby@v1
35
+ with:
36
+ ruby-version: ${{ matrix.ruby }}
37
+
38
+ - name: Install gem dependencies
39
+ env:
40
+ RAILS_ENV: test
41
+ run: |
42
+ gem install bundler
43
+ bundle config path vendor/bundle
44
+ bundle update --jobs 4 --retry 3
45
+
46
+ - name: Run Tests
47
+ env:
48
+ RAILS_ENV: test
49
+ run: |
50
+ bundle exec rake
data/.rubocop.yml CHANGED
@@ -3,7 +3,7 @@ inherit_gem:
3
3
  rubocop-fnando: .rubocop.yml
4
4
 
5
5
  AllCops:
6
- TargetRubyVersion: 2.6
6
+ TargetRubyVersion: 2.5
7
7
 
8
8
  Layout/LineLength:
9
9
  Exclude:
data/README.md CHANGED
@@ -1,24 +1,24 @@
1
1
  # Aitch
2
2
 
3
- [![Build Status](https://travis-ci.org/fnando/aitch.png)](https://travis-ci.org/fnando/aitch)
3
+ [![Tests](https://github.com/fnando/aitch/workflows/Tests/badge.svg)](https://github.com/fnando/aitch)
4
4
  [![Code Climate](https://codeclimate.com/github/fnando/aitch/badges/gpa.svg)](https://codeclimate.com/github/fnando/aitch)
5
- [![Test Coverage](https://codeclimate.com/github/fnando/aitch/badges/coverage.svg)](https://codeclimate.com/github/fnando/aitch)
6
- [![RubyGems](https://badge.fury.io/rb/aitch.png)](https://rubygems.org/gems/aitch)
5
+ [![Gem Version](https://img.shields.io/gem/v/aitch.svg)](https://rubygems.org/gems/aitch)
6
+ [![Gem Downloads](https://img.shields.io/gem/dt/aitch.svg)](https://rubygems.org/gems/aitch)
7
7
 
8
8
  A simple HTTP client.
9
9
 
10
10
  Features:
11
11
 
12
- * Supports Gzip|Deflate response
13
- * Automatically parses JSON, HTML and XML responses
14
- * Automatically follows redirect
12
+ - Supports Gzip|Deflate response
13
+ - Automatically parses JSON, HTML and XML responses
14
+ - Automatically follows redirect
15
15
 
16
16
  ## Installation
17
17
 
18
18
  Add this line to your application's Gemfile:
19
19
 
20
20
  ```ruby
21
- gem 'aitch'
21
+ gem "aitch"
22
22
  ```
23
23
 
24
24
  And then execute:
@@ -54,6 +54,9 @@ Aitch.configure do |config|
54
54
 
55
55
  # Set the logger.
56
56
  config.logger = nil
57
+
58
+ # Set the base url.
59
+ config.base_url = nil
57
60
  end
58
61
  ```
59
62
 
@@ -115,7 +118,8 @@ response.data # Parsed response body
115
118
 
116
119
  #### Parsing JSON, XML and HTML with Nokogiri
117
120
 
118
- If your response is a JSON, XML or a HTML content type, we'll automatically convert the response into the appropriate object.
121
+ If your response is a JSON, XML or a HTML content type, we'll automatically
122
+ convert the response into the appropriate object.
119
123
 
120
124
  ```ruby
121
125
  response = Aitch.get("http://simplesideias.com.br")
@@ -159,7 +163,8 @@ The request:
159
163
  Aitch.get("http://example.org")
160
164
  ```
161
165
 
162
- If the redirect limit is exceeded, then the `Aitch::TooManyRedirectsError` exception is raised.
166
+ If the redirect limit is exceeded, then the `Aitch::TooManyRedirectsError`
167
+ exception is raised.
163
168
 
164
169
  ### Basic auth
165
170
 
@@ -207,7 +212,8 @@ Request.get("http://example.org")
207
212
 
208
213
  ### Validating responses
209
214
 
210
- When you know the kind of response you're expecting, you can validate it by specifying the `expect` option.
215
+ When you know the kind of response you're expecting, you can validate it by
216
+ specifying the `expect` option.
211
217
 
212
218
  ```ruby
213
219
  Aitch.get do
@@ -216,7 +222,8 @@ Aitch.get do
216
222
  end
217
223
  ```
218
224
 
219
- If this request receives anything other than `200`, it will raise a `Aitch::StatusCodeError` exception.
225
+ If this request receives anything other than `200`, it will raise a
226
+ `Aitch::StatusCodeError` exception.
220
227
 
221
228
  ```
222
229
  Expect(200 OK) <=> Actual(404 Not Found)
@@ -226,7 +233,10 @@ You can also provide a list of accepted statuses, like `expect: [200, 201]`.
226
233
 
227
234
  ### Response Parsers
228
235
 
229
- You can register new response parsers by using `Aitch::ResponseParser.register(name, parser)`, where parser must implement the methods `match?(content_type)` and `load(response_body)`. This is how you could load CSV values.
236
+ You can register new response parsers by using
237
+ `Aitch::ResponseParser.register(name, parser)`, where parser must implement the
238
+ methods `match?(content_type)` and `load(response_body)`. This is how you could
239
+ load CSV values.
230
240
 
231
241
  ```ruby
232
242
  require "csv"
@@ -248,7 +258,8 @@ end
248
258
  Aitch::ResponseParser.prepend(:csv, CSVParser)
249
259
  ```
250
260
 
251
- The default behavior is returning the response body. You can replace it as the following:
261
+ The default behavior is returning the response body. You can replace it as the
262
+ following:
252
263
 
253
264
  ```ruby
254
265
  module DefaultParser
@@ -272,13 +283,31 @@ Aitch::ResponseParser.append(:default, DefaultParser)
272
283
 
273
284
  Aitch comes with response parsers for HTML, XML and JSON.
274
285
 
275
- By default, the JSON parser will be `JSON`. To set it to something else, use `Aitch::ResponseParser::JSONParser.engine`.
286
+ By default, the JSON parser will be `JSON`. To set it to something else, use
287
+ `Aitch::ResponseParser::JSONParser.engine`.
276
288
 
277
289
  ```ruby
278
290
  require "oj"
279
291
  Aitch::ResponseParser::JSONParser.engine = Oj
280
292
  ```
281
293
 
294
+ ### Setting the base url
295
+
296
+ When you're creating a wrapper for an API, usually the hostname is the same for
297
+ the whole API. In this case, you can avoid having to pass it around all the time
298
+ by setting `Aitch::Configuration#base_url`. This option is meant to be used when
299
+ you instantiate a new namespace.
300
+
301
+ ```ruby
302
+ Client = Aitch::Namespace.new
303
+
304
+ Client.configure do |config|
305
+ config.base_url = "https://api.example.com"
306
+ end
307
+
308
+ Client.get("/users")
309
+ ```
310
+
282
311
  ## Contributing
283
312
 
284
313
  1. Fork it
data/aitch.gemspec CHANGED
@@ -11,6 +11,7 @@ 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(">= 2.5.0")
14
15
 
15
16
  spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
16
17
  spec.executables = spec.files.grep(%r{^bin/}) {|f| File.basename(f) }
@@ -23,12 +23,16 @@ module Aitch
23
23
  # Set the logger.
24
24
  attr_accessor :logger
25
25
 
26
+ # Set the base url.
27
+ attr_accessor :base_url
28
+
26
29
  def initialize
27
30
  @timeout = 10
28
31
  @redirect_limit = 5
29
32
  @follow_redirect = true
30
33
  @user_agent = "Aitch/#{Aitch::VERSION} (http://rubygems.org/gems/aitch)"
31
34
  @default_headers = {}
35
+ @base_url = nil
32
36
  end
33
37
 
34
38
  def to_h
@@ -37,12 +37,6 @@ class FalseClass
37
37
  end
38
38
 
39
39
  class Array
40
- # Calls <tt>to_param</tt> on all its elements and joins the result with
41
- # slashes. This is used by <tt>url_for</tt> in Action Pack.
42
- def to_param
43
- collect(&:to_param).join "/"
44
- end
45
-
46
40
  # Converts an array into a string suitable for use as a URL query string,
47
41
  # using the given +key+ as the param name.
48
42
  #
@@ -10,7 +10,7 @@ module Aitch
10
10
  end
11
11
 
12
12
  def location
13
- return current_url unless current_url.match(%r{\A/})
13
+ return current_url unless current_url.match?(%r{\A/}) # rubocop:disable Performance/StartWith
14
14
 
15
15
  uri = find_uri_with_host
16
16
  url = ["#{uri.scheme}://#{uri.hostname}"]
@@ -25,7 +25,7 @@ module Aitch
25
25
  headers ||= {}
26
26
  options ||= {}
27
27
 
28
- if block_given?
28
+ if block
29
29
  dsl = DSL.new
30
30
  dsl.instance_eval(&block)
31
31
  args = dsl.to_h
@@ -38,10 +38,8 @@ module Aitch
38
38
  }
39
39
  end
40
40
 
41
- args.merge!(
42
- request_method: request_method,
43
- options: config.to_h.merge(Utils.symbolize_keys(args[:options]))
44
- )
41
+ args[:request_method] = request_method
42
+ args[:options] = config.to_h.merge(Utils.symbolize_keys(args[:options]))
45
43
 
46
44
  Request.new(args).perform
47
45
  end
data/lib/aitch/request.rb CHANGED
@@ -2,12 +2,7 @@
2
2
 
3
3
  module Aitch
4
4
  class Request
5
- attr_accessor :request_method
6
- attr_accessor :url
7
- attr_accessor :data
8
- attr_accessor :headers
9
- attr_accessor :options
10
- attr_accessor :redirects
5
+ attr_accessor :request_method, :url, :data, :headers, :options, :redirects
11
6
 
12
7
  alias params= data=
13
8
  alias body= data=
@@ -62,7 +57,15 @@ module Aitch
62
57
  end
63
58
 
64
59
  def uri
65
- @uri ||= URI.new(url, data, http_method_class::REQUEST_HAS_BODY)
60
+ @uri ||= begin
61
+ normalized_url = if url.start_with?("/") && options[:base_url]
62
+ File.join(options[:base_url], url)
63
+ else
64
+ url
65
+ end
66
+
67
+ URI.new(normalized_url, data, http_method_class::REQUEST_HAS_BODY)
68
+ end
66
69
  end
67
70
 
68
71
  def http_method_class
@@ -76,7 +79,7 @@ module Aitch
76
79
  body_data = data
77
80
  body_data = data.to_h if data.respond_to?(:to_h)
78
81
 
79
- if content_type.to_s =~ /\bjson\b/
82
+ if content_type.to_s.match?(/\bjson\b/)
80
83
  body_data = ResponseParser::JSONParser.engine.dump(body_data)
81
84
  end
82
85
 
@@ -83,7 +83,7 @@ module Aitch
83
83
  end
84
84
 
85
85
  def respond_to_missing?(name, _include_private = false)
86
- headers.key?(name.to_s)
86
+ headers.key?(name.to_s) || super
87
87
  end
88
88
 
89
89
  def description
data/lib/aitch/uri.rb CHANGED
@@ -6,15 +6,15 @@ module Aitch
6
6
 
7
7
  def_delegators :@uri, :host, :port, :scheme
8
8
 
9
- def initialize(url, data = {}, request_has_body = false)
9
+ def initialize(url, data = {}, request_has_body = false) # rubocop:disable Style/OptionalBooleanParameter
10
10
  @url = url
11
11
  @data = data
12
12
  @request_has_body = request_has_body
13
13
 
14
14
  begin
15
15
  @uri = ::URI.parse(url)
16
- rescue ::URI::InvalidURIError => e
17
- raise InvalidURIError, e
16
+ rescue ::URI::InvalidURIError => error
17
+ raise InvalidURIError, error
18
18
  end
19
19
  end
20
20
 
data/lib/aitch/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aitch
4
- VERSION = "1.1.0"
4
+ VERSION = "1.2.0"
5
5
  end
@@ -159,4 +159,17 @@ class RequestTest < Minitest::Test
159
159
  assert_equal "0.1", last_request.headers["Rendering"]
160
160
  assert_equal "user:pass", Base64.decode64(last_request.headers["Authorization"].split(" ").last)
161
161
  end
162
+
163
+ test "uses base url" do
164
+ register_uri(:get, /.+/)
165
+
166
+ client = Aitch::Namespace.new
167
+ client.configure {|c| c.base_url = "https://example.com" }
168
+
169
+ client.get("/some/path")
170
+
171
+ assert_equal "/some/path", last_request.uri.request_uri
172
+ assert_equal "example.com", last_request.uri.host
173
+ assert_equal "https", last_request.uri.scheme
174
+ end
162
175
  end
@@ -6,10 +6,6 @@ require "csv"
6
6
  class CustomResponseParserTest < Minitest::Test
7
7
  setup do
8
8
  parser = Class.new do
9
- def self.type
10
- :csv
11
- end
12
-
13
9
  def self.match?(content_type)
14
10
  content_type =~ /csv/
15
11
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+ require "csv"
5
+
6
+ class DefaultResponseParserTest < Minitest::Test
7
+ test "returns application/custom" do
8
+ register_uri(:get, "http://example.org/file.custom", body: "1,2,3", content_type: "application/custom")
9
+ response = Aitch.get("http://example.org/file.custom")
10
+
11
+ assert_instance_of String, response.data
12
+ assert_equal %[1,2,3], response.data
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class ToQueryTest < Minitest::Test
6
+ test "converts array" do
7
+ assert_equal "hobbies%5B%5D=Rails&hobbies%5B%5D=coding",
8
+ %w[Rails coding].to_query("hobbies")
9
+ assert_equal "hobbies%5B%5D=",
10
+ [].to_query("hobbies")
11
+ end
12
+
13
+ test "converts hash" do
14
+ assert_equal "name=David&nationality=Danish",
15
+ {name: "David", nationality: "Danish"}.to_query
16
+
17
+ assert_equal "user%5Bname%5D=David&user%5Bnationality%5D=Danish",
18
+ {name: "David", nationality: "Danish"}.to_query("user")
19
+ end
20
+
21
+ test "converts booleans" do
22
+ assert_equal "done=false&ready=true",
23
+ {ready: true, done: false}.to_query
24
+
25
+ assert_equal "states%5B%5D=true&states%5B%5D=false",
26
+ [true, false].to_query("states")
27
+ end
28
+ end
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.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-18 00:00:00.000000000 Z
11
+ date: 2022-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -171,9 +171,10 @@ executables: []
171
171
  extensions: []
172
172
  extra_rdoc_files: []
173
173
  files:
174
+ - ".github/FUNDING.yml"
175
+ - ".github/workflows/tests.yml"
174
176
  - ".gitignore"
175
177
  - ".rubocop.yml"
176
- - ".travis.yml"
177
178
  - CHANGELOG.md
178
179
  - Gemfile
179
180
  - LICENSE.txt
@@ -214,6 +215,7 @@ files:
214
215
  - test/aitch/request/status_code_validation_test.rb
215
216
  - test/aitch/request_test.rb
216
217
  - test/aitch/response/custom_response_parser_test.rb
218
+ - test/aitch/response/default_response_parser_test.rb
217
219
  - test/aitch/response/errors_test.rb
218
220
  - test/aitch/response/html_response_test.rb
219
221
  - test/aitch/response/json_response_test.rb
@@ -226,6 +228,7 @@ files:
226
228
  - test/aitch/response_parser/json_parser_test.rb
227
229
  - test/aitch/response_parser/xml_parser_test.rb
228
230
  - test/aitch/response_test.rb
231
+ - test/aitch/to_query_test.rb
229
232
  - test/aitch/uri_test.rb
230
233
  - test/aitch/utils/symbolize_keys_test.rb
231
234
  - test/aitch/utils/underscore_test.rb
@@ -236,7 +239,7 @@ homepage: http://rubygems.org/gems/aitch
236
239
  licenses:
237
240
  - MIT
238
241
  metadata: {}
239
- post_install_message:
242
+ post_install_message:
240
243
  rdoc_options: []
241
244
  require_paths:
242
245
  - lib
@@ -244,15 +247,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
244
247
  requirements:
245
248
  - - ">="
246
249
  - !ruby/object:Gem::Version
247
- version: '0'
250
+ version: 2.5.0
248
251
  required_rubygems_version: !ruby/object:Gem::Requirement
249
252
  requirements:
250
253
  - - ">="
251
254
  - !ruby/object:Gem::Version
252
255
  version: '0'
253
256
  requirements: []
254
- rubygems_version: 3.1.2
255
- signing_key:
257
+ rubygems_version: 3.3.17
258
+ signing_key:
256
259
  specification_version: 4
257
260
  summary: A simple HTTP client
258
261
  test_files:
@@ -268,6 +271,7 @@ test_files:
268
271
  - test/aitch/request/status_code_validation_test.rb
269
272
  - test/aitch/request_test.rb
270
273
  - test/aitch/response/custom_response_parser_test.rb
274
+ - test/aitch/response/default_response_parser_test.rb
271
275
  - test/aitch/response/errors_test.rb
272
276
  - test/aitch/response/html_response_test.rb
273
277
  - test/aitch/response/json_response_test.rb
@@ -280,6 +284,7 @@ test_files:
280
284
  - test/aitch/response_parser/json_parser_test.rb
281
285
  - test/aitch/response_parser/xml_parser_test.rb
282
286
  - test/aitch/response_test.rb
287
+ - test/aitch/to_query_test.rb
283
288
  - test/aitch/uri_test.rb
284
289
  - test/aitch/utils/symbolize_keys_test.rb
285
290
  - test/aitch/utils/underscore_test.rb
data/.travis.yml DELETED
@@ -1,20 +0,0 @@
1
- ---
2
- language: ruby
3
- script: "bundle exec rake"
4
- before_install: gem install bundler
5
- cache: bundler
6
- sudo: false
7
-
8
- rvm:
9
- - "2.7"
10
-
11
- gemfile:
12
- - Gemfile
13
-
14
- notifications:
15
- email: false
16
-
17
- addons:
18
- code_climate:
19
- repo_token:
20
- secure: "j/AjAG1u7NtdldftKUXnTMKC7CPd2R/O55ejzZnJi5IlHKKKZgJla1Z0YHTsGr75JQS7Q00D0L3TOSY8fLhV6fXO3Gn+9ShKTFRV5+iUtzlV0AWKBw+uENKNJH4jn1FhCoV8Th0I6OKtq98PqZ/hLR2J+/Uv3oCBwyriyJqag2U="