dadatas 0.1.7 → 0.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: e597deb0aed70594dff13cf1b8b1afa73dd392e6b9482f4c5abecfd80d5d2404
4
- data.tar.gz: 2eb74fd8d77bb454071a6105c4a4836d4109a0827dd24ee965041af16c3967dc
3
+ metadata.gz: 16ae5296d65bbeb306942498533a7657e3aacc8e2baeb50b86f0758aac4ba572
4
+ data.tar.gz: a58ea80c9f9c01226911dc83a0edc7d956eab8442c5f34b52ea274b77e86ec6e
5
5
  SHA512:
6
- metadata.gz: 7c5db4f3d29cbc4ed12e7bea56e32d445a612702863c6b22ae290587100204fcbac36aced3907dcd78bb4da79a7596619b62a115d449f3f02ecd1bc00f22ad4d
7
- data.tar.gz: 5d94c926718d6e7bd511fe08d11c5305dd59d4ed6acec00dcca854cb121a346ba00c57885e7d9ef7a49d406e2b1d01d038fdc965a37523e30710a4e465cb26a9
6
+ metadata.gz: c4733e251a5b71b7f2b1977bea5713bce2ec94b2f22ccc4c8f0c7ef425d59bc04918da59e16680b913eda9df755044a7f793b1199f3204a3663db267cb7affd3
7
+ data.tar.gz: acd248fb765cdf03cc121543bc040b2b17cf5add8d8705a40abb353ca71468f4f9c2dad5fd771e94b54343f649e6b13a824f6f75a086388ff9ecc52d4f4b886c
data/.rubocop.yml CHANGED
@@ -12,6 +12,10 @@ Style/StringLiteralsInInterpolation:
12
12
 
13
13
  Layout/LineLength:
14
14
  Max: 110
15
+
16
+ Metrics/BlockLength:
17
+ Exclude:
18
+ - 'spec/**/*'
15
19
  Metrics/MethodLength:
16
20
  Max: 20
17
21
  Metrics/AbcSize:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.2.0 - 2026-10-30
4
+
5
+ * `Suggestion#proxy` returns the DaData document unchanged for a server-side browser proxy.
6
+ * Paths are limited to suggest/findById and address, party, bank, country. The host stays on suggestions.dadata.ru.
7
+ * Requests time out and do not follow redirects. The token is not written to a logger, and it is removed from error bodies.
8
+ * Faraday dependency is `>= 0.17, < 2`, so the gem loads next to Faraday 0.x.
9
+ * Runtime no longer loads byebug.
10
+
3
11
  ## 0.1.7 - 2022-09-28
4
12
 
5
13
  * Add geo method suggestion address
data/Gemfile CHANGED
@@ -4,6 +4,6 @@ source 'https://rubygems.org'
4
4
 
5
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
6
 
7
- gem 'faraday', '~> 1.8.0'
7
+ gem 'faraday', '>= 0.17', '< 2'
8
8
 
9
9
  gemspec
data/README.md CHANGED
@@ -131,6 +131,19 @@ dadata.country(query: "Россия")
131
131
  => [true, [{:value=>"Россия", :unrestricted_value=>"Российская Федерация", :data=>{:code=>"643", :alfa2=>"RU", :alfa3=>"RUS", :name_short=>"Россия", :name=>"Российская Федерация", :req_value=>"Россия"}}]]
132
132
  ```
133
133
 
134
+ ## Прокси для браузера
135
+
136
+ `proxy` нужен, когда токен остаётся на сервере, а виджету нужен исходный документ DaData (`suggestions`), без `req_value` и без признака `[true, ...]`.
137
+
138
+ Путь берётся только из белого списка. Редирект не следует. В лог заголовки не пишутся.
139
+
140
+ ```ruby
141
+ dadata = Dadatas::Suggestion.new(api_key: 'YOURKEY')
142
+ ok, body = dadata.proxy('suggest', 'address', 'query' => 'москва', 'count' => 5)
143
+ # ok => true
144
+ # body => { "suggestions" => [{ "value" => "г Москва", ... }] }
145
+ ```
146
+
134
147
  ## Использование Clean
135
148
 
136
149
  ```ruby
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
- require 'faraday'
4
+ require 'dadatas/transport'
5
5
 
6
6
  module Dadatas
7
7
  # Call API DADATA
@@ -16,10 +16,10 @@ module Dadatas
16
16
 
17
17
  def call
18
18
  response = perform_request(url, params)
19
+ return unavailable unless response.respond_to?(:status)
20
+ return response_handler(response) if response.status == 200
19
21
 
20
- return response_handler(response) if response.status.eql?(200)
21
-
22
- error_response(response, response.body)
22
+ error_response(response, redact(response.body))
23
23
  end
24
24
 
25
25
  def response_handler(response)
@@ -31,7 +31,7 @@ module Dadatas
31
31
 
32
32
  return special_success(response_body[:location]) if location_condition?(response_body)
33
33
 
34
- error_response(response, response_body)
34
+ error_response(response, redact(response.body))
35
35
  end
36
36
 
37
37
  def location_condition?(response_body)
@@ -55,19 +55,24 @@ module Dadatas
55
55
  [response.any?, response]
56
56
  end
57
57
 
58
- def header
59
- {
60
- 'Content-Type' => 'application/json',
61
- 'Accept' => 'application/json',
62
- 'Authorization' => "Token #{@config[:api_key]}",
63
- 'X-Secret' => @config[:secret_key].to_s
64
- }
58
+ private
59
+
60
+ def perform_request(request_url, request_params)
61
+ transport = Transport.new(api_key: config[:api_key], secret_key: config[:secret_key])
62
+ transport.post(request_url, request_params)
65
63
  end
66
64
 
67
- def perform_request(url, params)
68
- Faraday.post(url, params.to_json, header)
69
- rescue StandardError => e
70
- e
65
+ def unavailable
66
+ [false, { code: nil, message: 'request failed' }]
67
+ end
68
+
69
+ def redact(text)
70
+ value = text.to_s
71
+ [config[:api_key], config[:secret_key]].each do |secret|
72
+ secret = secret.to_s
73
+ value = value.gsub(secret, '') if secret.length >= 16
74
+ end
75
+ value
71
76
  end
72
77
  end
73
78
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'dadatas/api_call'
4
- require 'byebug'
4
+ require 'dadatas/transport'
5
5
 
6
6
  module Dadatas
7
7
  # Suggestion API
@@ -18,6 +18,11 @@ module Dadatas
18
18
  address_by_geo: 'geolocate/address'
19
19
  }.freeze
20
20
 
21
+ PROXY_PATHS = {
22
+ 'suggest' => %w[address party bank country].freeze,
23
+ 'findById' => %w[address party bank].freeze
24
+ }.freeze
25
+
21
26
  attr_reader :config
22
27
 
23
28
  def initialize(config)
@@ -26,7 +31,7 @@ module Dadatas
26
31
 
27
32
  TYPES.each_key do |type|
28
33
  define_method(type) do |args = nil|
29
- call_method(Dadatas::Suggestion::TYPES[type], **args)
34
+ call_method(Dadatas::Suggestion::TYPES[type], **(args || {}))
30
35
  end
31
36
  end
32
37
 
@@ -34,6 +39,18 @@ module Dadatas
34
39
  call_method('findById/address', query: fias_id)
35
40
  end
36
41
 
42
+ # Browser proxy. Returns the DaData document unchanged: [true, { "suggestions" => [...] }].
43
+ # kind and type are a whitelist, so the host cannot be replaced by the caller.
44
+ def proxy(kind, type, payload = {})
45
+ path = proxy_path(kind, type)
46
+ return proxy_failure unless path
47
+ return proxy_failure unless payload.is_a?(Hash)
48
+
49
+ proxy_body(transport.post(URI.join(BASE_URL, path), payload))
50
+ rescue JSON::ParserError
51
+ proxy_failure
52
+ end
53
+
37
54
  private
38
55
 
39
56
  def call_method(method, **query_data)
@@ -43,5 +60,29 @@ module Dadatas
43
60
  query_data
44
61
  ).call
45
62
  end
63
+
64
+ def proxy_path(kind, type)
65
+ kind = kind.to_s
66
+ type = type.to_s
67
+ return unless PROXY_PATHS[kind]&.include?(type)
68
+
69
+ "#{kind}/#{type}"
70
+ end
71
+
72
+ def proxy_body(response)
73
+ return proxy_failure unless response.respond_to?(:status)
74
+ return proxy_failure(response.status) unless response.status == 200
75
+
76
+ parsed = JSON.parse(response.body)
77
+ parsed.is_a?(Hash) ? [true, parsed] : proxy_failure(response.status)
78
+ end
79
+
80
+ def transport
81
+ Transport.new(api_key: config[:api_key], secret_key: config[:secret_key])
82
+ end
83
+
84
+ def proxy_failure(code = nil)
85
+ [false, { code: code }]
86
+ end
46
87
  end
47
88
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'faraday'
5
+
6
+ module Dadatas
7
+ # HTTP call to a fixed DaData URL. Redirects are not followed.
8
+ # Faraday's response logger is not attached, so the token is not written.
9
+ class Transport
10
+ TIMEOUT = 5
11
+ OPEN_TIMEOUT = 3
12
+
13
+ def initialize(api_key:, secret_key: nil)
14
+ @api_key = api_key.to_s
15
+ @secret_key = secret_key
16
+ end
17
+
18
+ def post(url, params)
19
+ connection.post(url) do |request|
20
+ request.options.timeout = TIMEOUT
21
+ request.options.open_timeout = OPEN_TIMEOUT
22
+ request.headers.update(headers)
23
+ request.body = params.is_a?(String) ? params : JSON.generate(params)
24
+ end
25
+ rescue Faraday::TimeoutError, Faraday::ConnectionFailed, Net::OpenTimeout, Net::ReadTimeout
26
+ nil
27
+ end
28
+
29
+ private
30
+
31
+ def connection
32
+ @connection ||= Faraday.new do |faraday|
33
+ faraday.adapter Faraday.default_adapter
34
+ end
35
+ end
36
+
37
+ def headers
38
+ result = {
39
+ 'Content-Type' => 'application/json',
40
+ 'Accept' => 'application/json',
41
+ 'Authorization' => "Token #{@api_key}"
42
+ }
43
+ result['X-Secret'] = @secret_key.to_s unless @secret_key.nil?
44
+ result
45
+ end
46
+ end
47
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dadatas
4
- VERSION = '0.1.7'
4
+ VERSION = '0.2.0'
5
5
  end
metadata CHANGED
@@ -1,29 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dadatas
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Hitchens
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2022-09-28 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: faraday
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - "~>"
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0.17'
19
+ - - "<"
18
20
  - !ruby/object:Gem::Version
19
- version: 1.8.0
21
+ version: '2'
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
23
25
  requirements:
24
- - - "~>"
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0.17'
29
+ - - "<"
25
30
  - !ruby/object:Gem::Version
26
- version: 1.8.0
31
+ version: '2'
27
32
  - !ruby/object:Gem::Dependency
28
33
  name: bundler
29
34
  requirement: !ruby/object:Gem::Requirement
@@ -134,7 +139,6 @@ dependencies:
134
139
  - - "~>"
135
140
  - !ruby/object:Gem::Version
136
141
  version: '3.14'
137
- description:
138
142
  email:
139
143
  - m.seleznev@sendit.ru
140
144
  executables: []
@@ -152,11 +156,11 @@ files:
152
156
  - Rakefile
153
157
  - bin/console
154
158
  - bin/setup
155
- - dadatas.gemspec
156
159
  - lib/dadatas.rb
157
160
  - lib/dadatas/api_call.rb
158
161
  - lib/dadatas/clean.rb
159
162
  - lib/dadatas/suggestion.rb
163
+ - lib/dadatas/transport.rb
160
164
  - lib/dadatas/version.rb
161
165
  - sig/dadatas.rbs
162
166
  homepage: https://github.com/sendit-ru/dadatas
@@ -166,7 +170,6 @@ metadata:
166
170
  homepage_uri: https://github.com/sendit-ru/dadatas
167
171
  source_code_uri: https://github.com/sendit-ru/dadatas
168
172
  changelog_uri: https://github.com/sendit-ru/dadatas/blob/master/CHANGELOG.md
169
- post_install_message:
170
173
  rdoc_options: []
171
174
  require_paths:
172
175
  - lib
@@ -181,8 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
184
  - !ruby/object:Gem::Version
182
185
  version: '0'
183
186
  requirements: []
184
- rubygems_version: 3.2.22
185
- signing_key:
187
+ rubygems_version: 3.6.9
186
188
  specification_version: 4
187
189
  summary: Dadata.ru API integration
188
190
  test_files: []
data/dadatas.gemspec DELETED
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'lib/dadatas/version'
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = 'dadatas'
7
- spec.version = Dadatas::VERSION
8
- spec.authors = ['Michael Hitchens']
9
- spec.email = ['m.seleznev@sendit.ru']
10
-
11
- spec.summary = 'Dadata.ru API integration'
12
- spec.homepage = 'https://github.com/sendit-ru/dadatas'
13
- spec.license = 'MIT'
14
- spec.required_ruby_version = '>= 2.6.0'
15
-
16
- spec.metadata = {
17
- 'homepage_uri' => spec.homepage,
18
- 'source_code_uri' => spec.homepage,
19
- 'changelog_uri' => 'https://github.com/sendit-ru/dadatas/blob/master/CHANGELOG.md'
20
- }
21
-
22
- # Specify which files should be added to the gem when it is released.
23
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
- `git ls-files -z`.split("\x0").reject do |f|
26
- (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
27
- end
28
- end
29
- spec.bindir = 'exe'
30
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
- spec.require_paths = ['lib']
32
-
33
- # Requires Ruby faraday to http request
34
- spec.add_dependency 'faraday', '~> 1.8.0'
35
-
36
- spec.add_development_dependency 'bundler', '>= 2.2.33', '< 3.0'
37
- spec.add_development_dependency 'byebug'
38
- spec.add_development_dependency 'faker', '~> 2.19.0'
39
- spec.add_development_dependency 'rake', '~> 13.0'
40
- spec.add_development_dependency 'rspec', '>= 1.17', '~> 3.0'
41
- spec.add_development_dependency 'rubocop', '~> 1.21'
42
- spec.add_development_dependency 'webmock', '~> 3.14'
43
- end