Class: WebFunction::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/webfunction/request.rb

Overview

A request allows you to invoke a Web Function endpoint via an HTTP client.

Examples:

request = WebFunction::Request.new("https://api.example.com/endpoint")
request.execute # => { "a" => 1 }

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, bearer_auth: nil, version: nil, args: {}) ⇒ Request

Returns a new instance of Request.



11
12
13
14
15
16
# File 'lib/webfunction/request.rb', line 11

def initialize(url, bearer_auth: nil, version: nil, args: {})
  @url = url
  @bearer_auth = bearer_auth
  @version = version
  @args = args || {}
end

Class Attribute Details

.http_client ⇒ Object

The HTTP client used to execute the request.

To provide a custom HTTP client instead of the default (which uses Excon), set this to any object responding to #call. For example, a Proc or a lambda.

The contract is:

client.call(url, headers, body)
  • url: [String] The full URL to post to (not just the hostname or path).
  • headers:[Hash<String,String>] HTTP headers, e.g. { "Content-Type" => "application/json" }
  • body: [String] The JSON body to post.

The client must return a two-element Array: [status, body]:

  • status: [Integer] HTTP status code (e.g. 200, 400, 500)
  • body: [String] Raw response body as a string

Examples:

WebFunction::Endpoint.http_client = ->(url, headers, args) {
  http_response = MyHTTP.post(url, headers: headers, body: JSON.generate(args))
  [http_response.status, http_response.body]
}


43
44
45
# File 'lib/webfunction/request.rb', line 43

def http_client
  @http_client
end

Instance Attribute Details

#args ⇒ Hash (readonly)

The arguments to send to the request.

Returns:

  • (Hash) —

    The arguments to send to the request



87
88
89
# File 'lib/webfunction/request.rb', line 87

def args
  @args
end

#bearer_auth ⇒ String (readonly)

The bearer authentication token.

Returns:

  • (String) —

    The bearer authentication token



75
76
77
# File 'lib/webfunction/request.rb', line 75

def bearer_auth
  @bearer_auth
end

#url ⇒ String (readonly)

The URL of the request.

Returns:

  • (String) —

    The URL of the request



69
70
71
# File 'lib/webfunction/request.rb', line 69

def url
  @url
end

#version ⇒ String (readonly)

The API version to use.

Returns:

  • (String) —

    The API version to use



81
82
83
# File 'lib/webfunction/request.rb', line 81

def version
  @version
end

Class Method Details

.execute(url, bearer_auth: nil, version: nil, args: {}) ⇒ Object, Page

Executes a request.

Parameters:

  • url (String) —

    The URL of the request

  • bearer_auth (String) (defaults to: nil) —

    The bearer authentication token

  • version (String) (defaults to: nil) —

    The API version to use

  • args (Hash) (defaults to: {}) —

    The arguments to send to the request

Returns:

  • (Object, Page) —

    The response returned by the request. Paginated responses are wrapped in a Page.



54
55
56
57
# File 'lib/webfunction/request.rb', line 54

def execute(url, bearer_auth: nil, version: nil, args: {})
  request = new(url, bearer_auth: bearer_auth, version: version, args: args)
  request.execute
end

Instance Method Details

#as_pipeline_step ⇒ Hash

Returns the request as a pipeline step.

Returns:

  • (Hash) —

    The request as a pipeline step



116
117
118
119
120
121
122
# File 'lib/webfunction/request.rb', line 116

def as_pipeline_step
  {
    url: @url,
    headers: headers,
    body: @args,
  }
end

#execute ⇒ Object, Page

Executes the request.

When the response matches the pagination contract (page, next, and previous keys), it is wrapped in a Page so callers can navigate with Page#next_page and Page#previous_page.

Returns:

  • (Object, Page) —

    The response returned by the request

Raises:



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/webfunction/request.rb', line 136

def execute
  status, body = self.class.http_client.call(@url, headers, JSON.generate(@args))

  unless [200, 400].include?(status)
    raise WebFunction::UnexpectedStatusCodeError.new("Unexpected status code (#{status})",
      details: {
        status_code: status,
        raw_body: body,
      },
    )
  end

  begin
    result = JSON.parse(body)
  rescue JSON::ParserError => e
    raise WebFunction::JsonParseError.new(e.message,
      details: {
        status_code: status,
        raw_body: body,
        original_exception: e,
      },
    )
  end

  if status == 400
    code = "WFN_BAD_REQUEST_ERROR"
    message = "Bad request"
    details = { body: result }

    if result.is_a?(Array) && result.length == 3 && result[0].is_a?(String) && result[1].is_a?(String)
      code = result[0]
      message = result[1]
      details = result[2]
    end

    raise WebFunction::BadRequestError.new(message, code: code, details: details)
  end

  Page.wrap(result, request: self)
end

#headers ⇒ Hash

The headers to send to the request.

Returns:

  • (Hash) —

    The headers to send to the request



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/webfunction/request.rb', line 93

def headers
  headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
    "User-Agent": "webfunction/#{WebFunction::VERSION}",
    "Accept-Encoding": "gzip",
  }

  if @bearer_auth
    headers["Authorization"] = "Bearer #{@bearer_auth}"
  end

  if @version
    headers["Api-Version"] = @version
  end

  headers
end