Class: Apia::Rack

Inherits:
Object
  • Object
show all
Defined in:
lib/apia/rack.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, api, namespace, **options) ⇒ Rack

Returns a new instance of Rack.



12
13
14
15
16
17
# File 'lib/apia/rack.rb', line 12

def initialize(app, api, namespace, **options)
  @app = app
  @api = api
  @namespace = '/' + namespace.sub(/\A\/+/, '').sub(/\/+\z/, '')
  @options = options
end

Class Method Details

.error_triplet(code, description: nil, detail: {}, status: 500, headers: {}) ⇒ Array

Return a triplet for a given error using the standard error schema

Parameters:

  • code (String)
  • description (String) (defaults to: nil)
  • detail (Hash) (defaults to: {})
  • status (Integer) (defaults to: 500)
  • headers (Hash) (defaults to: {})

Returns:

  • (Array)


181
182
183
184
185
186
187
188
189
# File 'lib/apia/rack.rb', line 181

def error_triplet(code, description: nil, detail: {}, status: 500, headers: {})
  json_triplet({
                 error: {
                   code: code,
                   description: description,
                   detail: detail
                 }
               }, status: status, headers: headers.merge('x-api-schema' => 'json-error'))
end

.json_triplet(body, status: 200, headers: {}) ⇒ Array

Return a JSON-ready triplet for the given body.

Parameters:

  • body (Hash, Array)
  • status (Integer) (defaults to: 200)
  • headers (Hash) (defaults to: {})

Returns:

  • (Array)


164
165
166
167
168
169
170
171
# File 'lib/apia/rack.rb', line 164

def json_triplet(body, status: 200, headers: {})
  body_as_json = body.to_json
  [
    status,
    headers.merge('content-type' => 'application/json', 'content-length' => body_as_json.bytesize.to_s),
    [body_as_json]
  ]
end

Instance Method Details

#apiApia::API

Return the API object

Returns:



46
47
48
49
50
51
# File 'lib/apia/rack.rb', line 46

def api
  return Object.const_get(@api) if @api.is_a?(String) && development?
  return @cached_api ||= Object.const_get(@api) if @api.is_a?(String)

  @api
end

#call(env) ⇒ Array

Actually make the request

Parameters:

  • env (Hash)

Returns:

  • (Array)

    a rack triplet



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/apia/rack.rb', line 57

def call(env)
  if @options[:hosts]&.none? { |host| host == env['HTTP_HOST'] }
    return @app.call(env)
  end

  unless env['PATH_INFO'] =~ /\A#{Regexp.escape(@namespace)}\/([a-z].*)\z/i
    return @app.call(env)
  end

  api_path = Regexp.last_match(1)

  triplet = handle_request(env, api_path)
  add_cors_headers(env, triplet)
  triplet
end

#development?Boolean

Is this supposed to be running in development? This will validate the whole API on each request as well as being more verbose about internal server errors that are encountered.

Returns:

  • (Boolean)


24
25
26
27
28
29
# File 'lib/apia/rack.rb', line 24

def development?
  env_is_dev = ENV['RACK_ENV'] == 'development'
  return true if env_is_dev && @options[:development].nil?

  @options[:development] == true
end

#find_route(method, path) ⇒ nil, Hash

Parse a given full path and return nil if it doesn’t match our namespace or return a hash with the controller and endpoint named as available.

Parameters:

  • path (String)

    /core/v1/controller/endpoint

Returns:

  • (nil, Hash)


37
38
39
40
41
# File 'lib/apia/rack.rb', line 37

def find_route(method, path)
  return if api.nil?

  api.definition.route_set.find(method.to_s.downcase.to_sym, path).first
end