class Flon::API
This class is Flon's Rack application.
Constants
- DEFAULT_RESPONSE_HEADERS
Public Class Methods
new(api)
click to toggle source
Creates a new {API} object with the given API
.
@param [Object] api the API
to use; its class must respond to router and
the result must be a {Router}.
@return [API] the newly constructed object
# File lib/flon/api.rb, line 82 def initialize(api) raise ArgumentError, "given API's class does not respond to #routes" unless valid_api?(api) @api = api @router = api.class.router end
Public Instance Methods
call(env)
click to toggle source
Implements the Rack interface.
@param [Hash] env a rack environment @return [Array] a rack-suitable response
# File lib/flon/api.rb, line 93 def call(env) request = Rack::Request.new(env) method = http_method_to_symbol(request.request_method) path = request.path_info response = case (match = @router.match(method, path)) when :bad_path then Response.new(404, '"404 Not Found"') when :bad_method then Response.new(405, '"405 Method Not Allowed"') else dispatch(method, request, match) end rack_response(method, response) end
Private Instance Methods
call_action(action, request)
click to toggle source
# File lib/flon/api.rb, line 139 def call_action(action, request) responsify(call_respect_arity(action.bind(@api), request)) end
call_respect_arity(method, *args)
click to toggle source
# File lib/flon/api.rb, line 151 def call_respect_arity(method, *args) arity = method.arity arity.negative? ? method.call(*args) : method.call(*args[0...arity]) end
dispatch(method, rack_request, match)
click to toggle source
# File lib/flon/api.rb, line 110 def dispatch(method, rack_request, match) if receives_body?(method) body = normalise_body(rack_request) return Response.new(415, '"415 Unsupported Media Type"') if body == :fail else body = nil end request = Request.new(method, rack_request, match.params, body) call_action(match.action, request) end
http_method_to_symbol(http_method)
click to toggle source
# File lib/flon/api.rb, line 168 def http_method_to_symbol(http_method) http_method.downcase.to_sym end
normalise_body(request)
click to toggle source
# File lib/flon/api.rb, line 122 def normalise_body(request) body = request.body.read return body if body.empty? return :fail unless request.get_header('Content-Type') == 'application/json' begin JSON.parse(body) rescue JSON::JSONError :fail end end
rack_response(method, response)
click to toggle source
# File lib/flon/api.rb, line 156 def rack_response(method, response) [ response.status || 200, DEFAULT_RESPONSE_HEADERS.merge(stringify_values(response.headers || {})), method == :head || !response.body ? [] : [response.body] ] end
receives_body?(http_method)
click to toggle source
# File lib/flon/api.rb, line 135 def receives_body?(http_method) http_method != :get && http_method != :delete end
responsify(result)
click to toggle source
# File lib/flon/api.rb, line 143 def responsify(result) if result.is_a?(Response) result.tap { |it| it.body = it.body.to_json } else Response.new(200, result.to_json) end end
stringify_values(hash)
click to toggle source
# File lib/flon/api.rb, line 164 def stringify_values(hash) hash.transform_values(&:to_s) end
valid_api?(api)
click to toggle source
# File lib/flon/api.rb, line 172 def valid_api?(api) api.class.respond_to?(:router) && api.class.router.is_a?(Flon::Router) end