lib/peddler/api.rb in peddler-3.0.0.beta1 vs lib/peddler/api.rb in peddler-3.0.0

- old
+ new

@@ -1,59 +1,82 @@ # frozen_string_literal: true require "http" +require "peddler/endpoint" require "peddler/error" -require "peddler/region" +require "peddler/version" module Peddler # Wraps an Amazon Selling Partner API (SP-API) class API - # @return [Peddler::Region] - attr_reader :region + class CannotSandbox < StandardError; end + class MustSandbox < StandardError; end + # @return [Peddler::Endpoint] + attr_reader :endpoint + # @return [String] attr_reader :access_token # @param [String] aws_region # @param [String] access_token def initialize(aws_region, access_token) - @region = Region.new(aws_region) + @endpoint = Endpoint.find(aws_region) @access_token = access_token + @sandbox = false end - def endpoint - @endpoint ||= region.endpoint + # @return [URI::HTTPS] + def endpoint_uri + sandbox? ? endpoint.sandbox : endpoint.production end # @see https://developer-docs.amazon.com/sp-api/docs/the-selling-partner-api-sandbox # @return [self] def sandbox - @endpoint = endpoint.sub(/(?:sandbox.)?sellingpartnerapi/, "sandbox.sellingpartnerapi") + @sandbox = true self end + # @return [Boolean] + def sandbox? + @sandbox + end + + # @raise [CannotSandbox] if in a sandbox environment + def cannot_sandbox! + raise CannotSandbox, "cannot run in a sandbox" if sandbox? + end + + # @raise [MustSandbox] unless in a sandbox environment + def must_sandbox! + raise MustSandbox, "must run in a sandbox" unless sandbox? + end + # @see https://developer-docs.amazon.com/sp-api/docs/include-a-user-agent-header-in-all-requests # @see https://developer-docs.amazon.com/amazon-shipping/docs/connecting-to-the-selling-partner-api#step-3-add-headers-to-the-uri # @return [HTTP::Client] def http @http ||= HTTP.headers( - "Host" => endpoint_host, + "Host" => endpoint_uri.host, "User-Agent" => user_agent, "X-Amz-Access-Token" => access_token, "X-Amz-Date" => timestamp, ) end - # Retries with a rate limit when the API returns a 429 + # Throttles with a rate limit and retries when the API returns a 429 # - # @param [Float] delay The delay in seconds before retrying + # @param [Float] rate_limit The delay in seconds before retrying # @return [self] - def rate_limit(rate) - # HTTP v6.0 will implement retriable + def meter(rate_limit) + # HTTP v6.0 will implement retriable. Until then, point to their GitHub repo, or it's a no-op. # https://github.com/httprb/http/pull/790 - retriable(delay: 1.0 / rate, retry_statuses: [429]) if @http.respond_to?(:retriable) + delay = sandbox? ? 0.2 : 1.0 / rate_limit + retriable(delay: delay, retry_statuses: [429]) if @http.respond_to?(:retriable) + self end # @!method use(*features) # Turn on [HTTP](https://github.com/httprb/http) features @@ -85,25 +108,25 @@ define_method(method) do |path, **options| if options[:body] && !options[:body].is_a?(String) options[:json] = options.delete(:body) end - response = http.send(method, [endpoint, path].join, **options) + uri = endpoint_uri.tap do |uri| + uri.path = path + end + response = http.send(method, uri, **options) + if response.status.client_error? error = Error.build(response) raise error if error end response end end private - - def endpoint_host - URI.parse(endpoint).host - end def user_agent "Peddler/#{Peddler::VERSION} (Language=Ruby; #{Socket.gethostname})" end