class Moonrope::RackMiddleware
Attributes
base[R]
Public Class Methods
new(app, base, options = {})
click to toggle source
Initialize a new Moonrope::Rack server
@param app [Object] the next Rack application in the stack @param base [Moonrope::Base] the base API to serve @param options [Hash] a hash of options
# File lib/moonrope/rack_middleware.rb, line 12 def initialize(app, base, options = {}) @app = app @base = base @options = options end
Public Instance Methods
call(env)
click to toggle source
Make a new request
@param env [Hash] a rack environment hash @return [Array] a rack triplet
# File lib/moonrope/rack_middleware.rb, line 26 def call(env) if env['PATH_INFO'] =~ Moonrope::Request.path_regex # # Set some global headers which are always returned # global_headers = {} global_headers['Content-Type'] = 'text/plain' global_headers['Access-Control-Allow-Origin'] = '*' if env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'] global_headers['Access-Control-Allow-Headers'] = env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'] end global_headers['Access-Control-Allow-Methods'] = '*' # # Options always returns a 200 # if env['REQUEST_METHOD'] == 'OPTIONS' return [200, global_headers, ['OK']] end # # Responses are now in JSON # global_headers['Content-Type'] = 'application/json' # # Reload if needed # if @options[:reload_on_each_request] @base = @base.copy begin @base.load rescue => e return generate_error_triplet(@base, nil, e, global_headers) end end # # Create a new request object # request = base.request(env, $1) # # If force SSL is enabled, don't allow requests to proceed if they're # not SSL # if base.force_ssl? && !request.ssl? return [400, global_headers, [{:status => 'http-not-supported', :message => "Non-secure HTTP connections are not supported. Requests should be made using https:// rather than http://."}.to_json]] end # # Call the on request block if one has been defined for the base. # if base.on_request.is_a?(Proc) base.on_request.call(base, env) end # # Check the request is valid # unless request.valid? return [400, global_headers, [{:status => 'invalid-controller-or-action'}.to_json]] end # # Execute the request # begin result = request.execute json = result.to_json global_headers['Content-Length'] = json.bytesize.to_s headers = global_headers.merge(result.headers) Moonrope.logger.info "[#{Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")}] controller=#{request.controller.name} action=#{request.action.name} status=#{result.status} time=#{result.time} ip=#{request.ip} size=#{json.bytesize}" base.request_callbacks.each do |callback| # Call each request callback and provide the request, the result # and the raw that's being returned to the user. callback.call(request, result, json, headers) end [200, headers, [json]] rescue JSON::ParserError => e [400, global_headers, [{:status => 'invalid-json', :details => e.message}.to_json]] rescue => e generate_error_triplet(base, request, e, global_headers) end else if @app && @app.respond_to?(:call) @app.call(env) else [404, {}, ["Non-API request"]] end end end
generate_error_triplet(base, request, exception, headers = {})
click to toggle source
# File lib/moonrope/rack_middleware.rb, line 123 def generate_error_triplet(base, request, exception, headers = {}) Moonrope.logger.info exception.class Moonrope.logger.info exception.message Moonrope.logger.info exception.backtrace.join("\n") response = {:status => 'internal-server-error'} # Call any request errors which have been registered on the base base.request_error_callbacks.each do |callback| callback.call(request, exception) end # If in development, return more details about the exception which was raised. if base.environment == 'development' response[:error] = exception.class.to_s response[:message] = exception.message response[:backtrace] = exception.backtrace[0,6] end [500, headers, [response.to_json]] end