aitch 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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="