sul-dlss/dor-services-client

View on GitHub
lib/dor/services/client/versioned_service.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
# frozen_string_literal: true

module Dor
  module Services
    class Client
      # @abstract API calls to a versioned endpoint
      class VersionedService
        EXCEPTION_CLASS = {
          400 => BadRequestError,
          401 => UnauthorizedResponse,
          404 => NotFoundResponse,
          409 => ConflictResponse,
          412 => PreconditionFailedResponse
        }.freeze

        JSON_API_MIME_TYPE = 'application/vnd.api+json'

        def initialize(connection:, version:)
          @connection = connection
          @api_version = version
        end

        # Common interface for handling asynchronous results
        def async_result(url:)
          AsyncResult.new(url: url)
        end

        def with_querystring(url:, params:)
          return url if params.blank?

          "#{url}?#{params.to_query}"
        end

        private

        attr_reader :connection, :api_version

        def raise_exception_based_on_response!(response, object_identifier = nil)
          data = if response.headers.fetch('content-type', '').start_with?(JSON_API_MIME_TYPE)
                   JSON.parse(response.body)
                 else
                   {}
                 end
          exception_class = EXCEPTION_CLASS.fetch(response.status, UnexpectedResponse)
          raise exception_class.new(response: response,
                                    object_identifier: object_identifier,
                                    errors: data.fetch('errors', []))
        end

        def build_cocina_from_response(response, validate: false)
          cocina_object = Cocina::Models.build(JSON.parse(response.body), validate: validate)
          Cocina::Models.with_metadata(cocina_object, response.headers['ETag'], created: date_from_header(response, 'X-Created-At'),
                                                                                modified: date_from_header(response, 'Last-Modified'))
        end

        def build_json_from_cocina(cocina_object)
          Cocina::Models.without_metadata(cocina_object).to_json
        end

        def date_from_header(response, key)
          response.headers[key]&.to_datetime
        end
      end
    end
  end
end