Class: Apia::Endpoint

Inherits:
Object
  • Object
show all
Extended by:
Defineable
Includes:
CallableWithEnvironment
Defined in:
lib/apia/endpoint.rb

Class Method Summary collapse

Methods included from Defineable

create, inspect, method_missing, name, respond_to_missing?

Methods included from CallableWithEnvironment

#call, #call_with_error_handling, #initialize, #method_missing, #respond_to_missing?

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Apia::CallableWithEnvironment

Class Method Details

.catch_errors(response, environment) ⇒ void

This method returns an undefined value.

Catch any runtime errors and update the given response with the appropriate values.

Parameters:



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/apia/endpoint.rb', line 95

def catch_errors(response, environment)
  yield
rescue Apia::RuntimeError => e
  # If the error was triggered by the authenticator, the cors headers wont yet have been merged
  # so ensure cors headers are merged here
  response.headers.merge!(environment.cors.to_headers)

  catch_errors(response, environment) do
    response.body = { error: e.hash }
    response.status = e.http_status
    response.headers['x-api-schema'] = 'json-error'
  end
end

.collate_objects(set) ⇒ void

This method returns an undefined value.

Collate all objects that this endpoint references and add them to the given object set

Parameters:



30
31
32
33
34
35
36
37
38
39
40
# File 'lib/apia/endpoint.rb', line 30

def collate_objects(set)
  set.add_object(definition.argument_set)

  definition.potential_errors.each do |error|
    set.add_object(error)
  end

  definition.fields.each_value do |field|
    set.add_object(field.type.klass) if field.type.usable_for_field?
  end
end

.definitionApia::Definitions::Endpoint

Return the definition object for the endpoint



21
22
23
# File 'lib/apia/endpoint.rb', line 21

def definition
  @definition ||= Definitions::Endpoint.new(Helpers.class_name_to_id(name))
end

.execute(request) ⇒ Apia::Response

Run this request by providing a request to execute it with.

Parameters:

Returns:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/apia/endpoint.rb', line 46

def execute(request)
  response = Response.new(request, self)
  environment = RequestEnvironment.new(request, response)

  catch_errors(response, environment) do
    # Determine an authenticator for this endpoint
    request.authenticator = definition.authenticator || request.controller&.definition&.authenticator || request.api&.definition&.authenticator

    # Execute the authentication before the request happens
    request.authenticator&.execute(environment)

    # Add the CORS headers to the response before the endpoint is called. The endpoint
    # cannot influence the CORS headers.
    response.headers.merge!(environment.cors.to_headers)

    # OPTIONS requests always return 200 OK and no body.
    if request.options?
      response.status = 200
      response.body = ''
      return response
    end

    # Determine if we're permitted to run the action based on the endpoint's scopes
    if request.authenticator && !request.authenticator.authorized_scope?(environment, definition.scopes)
      environment.raise_error Apia::ScopeNotGrantedError, scopes: definition.scopes
    end

    # Process arguments into the request. This happens after the authentication
    # stage because a) authenticators shouldn't be using endpoint specific args
    # and b) the argument conditions may need to know the identity.
    request.arguments = definition.argument_set.create_from_request(request)

    # Call the action for the endpoint
    endpoint_instance = new(environment)
    endpoint_instance.call_with_error_handling

    # We're going to call this here because we want to cache the actual values of
    # the output within the catch_errors block.
    response.hash
  end

  response
end

.include_field?(*args) ⇒ Boolean

Should a given field be included

Returns:

  • (Boolean)


111
112
113
# File 'lib/apia/endpoint.rb', line 111

def include_field?(*args)
  definition.fields.spec.include_field?(*args)
end

.test {|request| ... } ⇒ Object

Allow an endpoint to be executed with a mocked request.

Yields:

  • (request)


117
118
119
120
121
122
# File 'lib/apia/endpoint.rb', line 117

def test
  request = Apia::MockRequest.empty
  request.endpoint = self
  yield request if block_given?
  execute(request)
end