Class: LunaPark::Http::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/luna_park/http/client.rb

Overview

Client are useful for organize a repository where the source of the date is the http-server, you should to inherit from this class. And interpret all the necessary endpoints as logical methods.

For example: You have api endpoint, which get list of all users (GET api.example.com/users), as part of json api. Then you should define ‘Client` in your `Users` domain and define `all` method which get list of all users.

module Users
  class Client < LunaPark::Http::Client
    def all
      response = get! json_request(
          title: 'Get users',
          url: 'http://api.example.com/users',
        )
      response.json_parse || []
    end
  end
end

Handle errors in the simple way

But how to handle http errors? You have two ways: simple and flexible. In first case you realize all request with bang-methods (get!, post!, put!, etc.). And if something went wrong client raise Errors::Http exception.

# Server is unavailable
client = Users::Clients.new
client.all # => raise LunaPark::Errors::Http (Service Unavailable)
# And your clients will see server error.

Handle errors in the flexible way

But if you have different cases based on different HTTP codes, you should choose flexible way.

For example: You develop application for a delivery service. And you should realize Orders domain. The Orders domain makes payment requests to the microservice responsible for transactions.

Transactions microservice on payment endpoint has four uses cases, based on Http codes:

  • 201 - payment is successfully created.

  • 400 - request, has wrong structure, validation error.

  • 422 - business logic error (small balance for example).

    {"error":"Not enough funds in your account"}
    
  • 500 - server error

Your transaction service client should process this code is:

  • 200 - return true

  • 422 - forward business logic error message to your customer

  • in others ways show server error to your client, and you your should notify developers about that.

Examples:

module Payments
  class Client < LunaPark::Http::Client
    def create(account:, money:)
      response = post json_request(
        title: 'Make payment for order',
        url: 'http://api.transactions.example.com/payments',
        data: {account: , money: money}
      )
      case response.code
      when 200 then true
      when 422 then raise Error::Business.new(response.body.parse_json(payload_key: error), action: :catch)
      else raise Errors::Http.new(response.status, notify: true, response: response)
      end
    end
  end
end

# In your checkout scenario, payment is being made
module Orders
  module Scenarios
    class Checkout < LunaPark::UseCases::Scenario
      def call!
        # ...
        payments.create(account: 42, money: Values::Money.new(100, :usd))
        # ...
      end
    end
  end
end

# In endpoint,  if the client does not have enough money on his balance
checkout.call
checkout.success?     # => false
checkout.fail_message # => "Not enough funds in your account"

Constant Summary collapse

DEFAULT_OPEN_TIMEOUT =
60
DEFAULT_READ_TIMEOUT =
60
DEFAULT_DRIVER =
LunaPark::Http::Send
DEFAULT_METHOD =
:get

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.driver(driver = nil) ⇒ Object

Set default diver for this Client

Examples:

set driver

class Users < Client
  driver URI::Send
end

Foobar.driver # => URI::Send


298
299
300
# File 'lib/luna_park/http/client.rb', line 298

def driver(driver = nil)
  driver.nil? ? @driver || DEFAULT_DRIVER : @driver = driver
end

.open_timeout(timeout = nil) ⇒ Object

Set default open_timeout for this Client

Examples:

set open_timeout

class Users < Client
  open_timeout URI::Send
end

Foobar.open_timeout # => URI::Send


310
311
312
# File 'lib/luna_park/http/client.rb', line 310

def open_timeout(timeout = nil)
  timeout.nil? ? @open_timeout || DEFAULT_OPEN_TIMEOUT : @open_timeout = timeout
end

.read_timeout(timeout = nil) ⇒ Object

Set default read_timeout for this Client

Examples:

set read_timeout

class Users < Client
  read_timeout URI::Send
end

Foobar.read_timeout     # => URI::Send


322
323
324
# File 'lib/luna_park/http/client.rb', line 322

def read_timeout(timeout = nil)
  timeout.nil? ? @read_timeout || DEFAULT_READ_TIMEOUT : @read_timeout = timeout
end

Instance Method Details

#delete(request) ⇒ Object

Send DELETE request. Always return response even if the response is not successful.

See Also:



217
218
219
220
# File 'lib/luna_park/http/client.rb', line 217

def delete(request)
  request.method = :delete
  request.call
end

#delete!(request) ⇒ Object

Send DELETE request. Raise Errors::Http on bad response.

See Also:



264
265
266
267
# File 'lib/luna_park/http/client.rb', line 264

def delete!(request)
  request.method = :delete
  request.call!
end

#form_request(title:, url:, method: nil, body: nil, headers: nil, data: nil, **opts) ⇒ LunaPark::Http::Request

Build plain request

rubocop:disable Metrics/ParameterLists

Examples:

request = form_request(
  title: 'get users list',
  url: 'http://api.example.com/users'
)

request # => <LunaPark::Http::Request @title="get users list"
  # @url="http://api.example.com/users" @method="get"
  # @headers={ 'Content-Type' => 'application/x-www-form-urlencoded' }
  # @body="" @sent_at="">

Parameters:

  • title (String)

    business description for request

  • url (String)

    request url

  • method (String, Symbol) (defaults to: nil)

    http method (get, post, etc)

  • body (NilClass, String) (defaults to: nil)

    http request body

  • headers (Hash) (defaults to: nil)

    http headers

Returns:



121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/luna_park/http/client.rb', line 121

def form_request(title:, url:, method: nil, body: nil, headers: nil, data: nil, **opts)
  form_body = body || data # * we have no a good generator for `x-www-form-urlencoded` type, but Driver has

  build_request(
    title: title,
    url: url,
    method: method,
    body: form_body,
    headers: headers,
    content_type: 'application/x-www-form-urlencoded',
    **opts
  )
end

#get(request) ⇒ LunaPark::Http::Response

Send GET request. Always return response even if the response is not successful.

Examples:

success response

get json_request(title: 'Hi world', url: 'http://example.com/hi')
  # => <LunaPark::Http::Response @code=200
  #   @body="{"version":1,"data":"Hello World!"}" @headers={:content_type=>"application/json",
  #   :connection=>"close", :server=>"thin"} @cookies={}>

server is unavailable

get json_request(title: 'Hi world', url: 'http://example.com/hi')
  # => <LunaPark::Http::Response @code=503
  #   @body="" @headers={} @cookies={}>

Returns:



189
190
191
192
# File 'lib/luna_park/http/client.rb', line 189

def get(request)
  request.method = :get
  request.call
end

#get!(request) ⇒ LunaPark::Http::Response

Send GET request. Raise Errors::Http on bad response.

Examples:

success response

get json_request(title: 'Hi world', url: 'http://example.com/hi')
  # => <LunaPark::Http::Response @code=200
  #   @body="{"version":1,"data":"Hello World!"}" @headers={:content_type=>"application/json",
  #   :connection=>"close", :server=>"thin"} @cookies={}>

server is unavailable

get json_request(title: 'Hi world', url: 'http://example.com/hi')
  # => raise LunaPark::Errors::Http

Returns:

Raises:



236
237
238
239
# File 'lib/luna_park/http/client.rb', line 236

def get!(request)
  request.method = :get
  request.call!
end

#json_request(title:, url:, method: nil, body: nil, data: nil, headers: nil, **opts) ⇒ LunaPark::Http::Request

Build form request. Body will convert to json format automatically.

rubocop:disable Metrics/ParameterLists

Examples:

request = json_request(
  title: 'Ping pong',
  url: 'http://api.example.com/ping',
  data: { message: 'ping' }
)

request # => <LunaPark::Http::Request
        #     @title="Ping pong"
        #     @url="http://api.example.com/ping" @method="get"
        #     @headers={ 'Content-Type' => 'application/json' }
        #     @body="{"message":"ping"}" @sent_at=""
        #    >

Parameters:

  • title (String)

    business description for request

  • url (String)

    request url

  • method (String, Symbol) (defaults to: nil)

    http method (get, post, etc)

  • body (NilClass, String, Hash) (defaults to: nil)

    http request body

  • headers (Hash) (defaults to: nil)

    http headers

Returns:



160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/luna_park/http/client.rb', line 160

def json_request(title:, url:, method: nil, body: nil, data: nil, headers: nil, **opts)
  json_body = body || data && JSON.generate(data)

  build_request(
    title: title,
    url: url,
    method: method,
    body: json_body,
    headers: headers,
    content_type: 'application/json',
    **opts
  )
end

#patch(request) ⇒ Object

Send PATCH request. Always return response even if the response is not successful.

See Also:



210
211
212
213
# File 'lib/luna_park/http/client.rb', line 210

def patch(request)
  request.method = :patch
  request.call
end

#patch!(request) ⇒ Object

Send PATCh request. Raise Errors::Http on bad response.

See Also:



257
258
259
260
# File 'lib/luna_park/http/client.rb', line 257

def patch!(request)
  request.method = :patch
  request.call!
end

#post(request) ⇒ Object

Send POST request. Always return response even if the response is not successful.

See Also:



196
197
198
199
# File 'lib/luna_park/http/client.rb', line 196

def post(request)
  request.method = :post
  request.call
end

#post!(request) ⇒ Object

Send POST request. Raise Errors::Http on bad response.

See Also:



243
244
245
246
# File 'lib/luna_park/http/client.rb', line 243

def post!(request)
  request.method = :post
  request.call!
end

#put(request) ⇒ Object

Send PUT request. Always return response even if the response is not successful.

See Also:



203
204
205
206
# File 'lib/luna_park/http/client.rb', line 203

def put(request)
  request.method = :put
  request.call
end

#put!(request) ⇒ Object

Send PUT request. Raise Errors::Http on bad response.

See Also:



250
251
252
253
# File 'lib/luna_park/http/client.rb', line 250

def put!(request)
  request.method = :put
  request.call!
end