lib/nylas/http_client.rb in nylas-4.2.4 vs lib/nylas/http_client.rb in nylas-4.3.0
- old
+ new
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
module Nylas
# Plain HTTP client that can be used to interact with the Nylas API sans any type casting.
- class HttpClient
+ class HttpClient # rubocop:disable Metrics/ClassLength
HTTP_CODE_TO_EXCEPTIONS = {
400 => InvalidRequest,
402 => MessageRejected,
403 => AccessDenied,
404 => ResourceNotFound,
@@ -13,10 +15,19 @@
501 => EndpointNotYetImplemented,
502 => BadGateway,
503 => ServiceUnavailable
}.freeze
+ ENDPOINT_TIMEOUTS = {
+ "/oauth/authorize" => 345,
+ "/messages/search" => 350,
+ "/threads/search" => 350,
+ "/delta" => 3650,
+ "/delta/longpoll" => 3650,
+ "/delta/streaming" => 3650
+ }.freeze
+
include Logging
attr_accessor :api_server, :service_domain
attr_writer :default_headers
attr_reader :access_token
attr_reader :app_id
@@ -32,10 +43,11 @@
def initialize(app_id:, app_secret:, access_token: nil, api_server: "https://api.nylas.com",
service_domain: "api.nylas.com")
unless api_server.include?("://")
raise "When overriding the Nylas API server address, you must include https://"
end
+
@api_server = api_server
@access_token = access_token
@app_secret = app_secret
@app_id = app_id
@service_domain = service_domain
@@ -54,28 +66,37 @@
# @param headers [Hash] (Optional, defaults to {}) - Additional HTTP headers to include in the payload.
# @param query [Hash] (Optional, defaults to {}) - Hash of names and values to include in the query
# section of the URI fragment
# @param payload [String,Hash] (Optional, defaults to nil) - Body to send with the request.
# @return [Array Hash Stringn]
+ # rubocop:disable Metrics/MethodLength
def execute(method:, path: nil, headers: {}, query: {}, payload: nil)
- request = build_request(method: method, path: path, headers: headers, query: query, payload: payload)
+ timeout = ENDPOINT_TIMEOUTS.fetch(path, 230)
+ request = build_request(
+ method: method,
+ path: path,
+ headers: headers,
+ query: query,
+ payload: payload,
+ timeout: timeout
+ )
rest_client_execute(**request) do |response, _request, result|
response = parse_response(response)
handle_failed_response(result: result, response: response)
response
end
end
+ # rubocop:enable Metrics/MethodLength
inform_on :execute, level: :debug,
also_log: { result: true, values: %i[method url path headers query payload] }
- def build_request(method:, path: nil, headers: {}, query: {}, payload: nil)
+ def build_request(method:, path: nil, headers: {}, query: {}, payload: nil, timeout: nil)
headers[:params] = query
url ||= url_for_path(path)
resulting_headers = default_headers.merge(headers)
- { method: method, url: url, payload: payload, headers: resulting_headers }
+ { method: method, url: url, payload: payload, headers: resulting_headers, timeout: timeout }
end
- # rubocop:enable Metrics/ParameterLists
# Syntactical sugar for making GET requests via the API.
# @see #execute
def get(path: nil, headers: {}, query: {})
execute(method: :get, path: path, query: query, headers: headers)
@@ -96,22 +117,15 @@
# Syntactical sugar for making DELETE requests via the API.
# @see #execute
def delete(path: nil, payload: nil, headers: {}, query: {})
execute(method: :delete, path: path, headers: headers, query: query, payload: payload)
end
- # rubocop:enable Metrics/ParameterList
- private def rest_client_execute(method:, url:, headers:, payload:, &block)
- ::RestClient::Request.execute(method: method, url: url, payload: payload,
- headers: headers, &block)
- end
- inform_on :rest_client_execute, level: :debug,
- also_log: { result: true, values: %i[method url headers payload] }
-
def default_headers
@default_headers ||= {
"X-Nylas-API-Wrapper" => "ruby",
+ "X-Nylas-Client-Id" => @app_id,
"User-Agent" => "Nylas Ruby SDK #{Nylas::VERSION} - #{RUBY_VERSION}",
"Content-types" => "application/json"
}
end
@@ -125,19 +139,30 @@
def url_for_path(path)
protocol, domain = api_server.split("//")
"#{protocol}//#{access_token}:@#{domain}#{path}"
end
- private def handle_failed_response(result:, response:)
+ private
+
+ def rest_client_execute(method:, url:, headers:, payload:, timeout:, &block)
+ ::RestClient::Request.execute(method: method, url: url, payload: payload,
+ headers: headers, timeout: timeout, &block)
+ end
+
+ inform_on :rest_client_execute, level: :debug,
+ also_log: { result: true, values: %i[method url headers payload] }
+
+ def handle_failed_response(result:, response:)
http_code = result.code.to_i
handle_anticipated_failure_mode(http_code: http_code, response: response)
raise UnexpectedResponse, result.msg if result.is_a?(Net::HTTPClientError)
end
- private def handle_anticipated_failure_mode(http_code:, response:)
+ def handle_anticipated_failure_mode(http_code:, response:)
return if http_code == 200
return unless response.is_a?(Hash)
+
exception = HTTP_CODE_TO_EXCEPTIONS.fetch(http_code, APIError)
raise exception.new(response[:type], response[:message], response.fetch(:server_error, nil))
end
end
end