# frozen_string_literal: true module Qismo # # HTTP response handler # # @!attribute http_code [Integer] # @!attribute http_headers [HTTP::Headers] # @!attribute http_body [String] # @!attribute http_raw_body [String] # @!attribute error [Error] class Response include Qismo::Helpers::BaseHelper # @return [Integer] bad request constant BAD_REQUEST = 400 # @return [Integer] unauthorized constant UNAUTHORIZED = 401 # @return [Integer] payment required constant PAYMENT_REQUIRED = 402 # @return [Integer] forbidden constant FORBIDDEN = 403 # @return [Integer] not found constant NOT_FOUND = 404 # @return [Integer] rate limit exceeded constant RATE_LIMIT_EXCEEDED = 429 # @return [Integer] internal server error constant INTERNAL_SERVER_ERROR = 500 attr_reader :http_code, :http_headers, :http_body, :http_raw_body, :error # # Response # # @param resp [HTTP::Response] # def initialize(resp) @http_code = resp.code @http_headers = parse_headers(resp) @http_body = parse_body(resp) @http_raw_body = resp.to_s @error = parse_error(resp) end def ok? (200..299).member?(@http_code) end alias_method :success?, :ok? def raise_for_error if @error.nil? return end raise @error end private def parse_body(resp) safe_parse_json(resp.to_s) end def parse_headers(resp) safe_parse_json(resp.headers.to_h) end def parse_error(resp) return nil if resp.status.ok? || resp.status.informational? || resp.status.redirect? if resp.status.server_error? return InternalServerError.new( "Qiscus internal server error", http_code: resp.code, http_headers: safe_parse_json(resp.headers.to_h), http_body: safe_parse_json(resp.to_s), http_raw_body: resp.to_s ) end if resp.status.client_error? code = resp.code headers = safe_parse_json(resp.headers.to_h) raw_body = resp.to_s klass = case code when BAD_REQUEST then BadRequest.new when UNAUTHORIZED then Unauthorized.new when PAYMENT_REQUIRED then PaymentRequired.new when FORBIDDEN then Forbidden.new when NOT_FOUND then NotFound.new when RATE_LIMIT_EXCEEDED then RateLimitExceeded.new else ClientError.new end if code == BAD_REQUEST && raw_body.downcase.include?("wrong email or password") klass = Unauthorized.new end klass.http_code = code klass.http_headers = headers klass.http_raw_body = raw_body klass.http_body = safe_parse_json(raw_body) klass.message = klass.class.to_s if klass.http_body.is_a?(Hash) http_body = klass.http_body error_message = if http_body["errors"].is_a?(String) http_body["errors"] elsif http_body["errors"].is_a?(Hash) && http_body.dig("errors", "message").is_a?(String) http_body["errors"]["message"] else klass.class.to_s end klass.message = error_message klass.message = error if klass.message.is_a?(String) else klass.message = klass.http_body end klass end end end end