class OpenapiFirst::Router

Constants

ORIGINAL_PATH

Public Class Methods

new( app, spec:, raise_error: false, not_found: :halt, parent_app: nil ) click to toggle source
# File lib/openapi_first/router.rb, line 9
def initialize(
  app,
  spec:,
  raise_error: false,
  not_found: :halt,
  parent_app: nil
)
  @app = app
  @parent_app = parent_app
  @raise = raise_error
  @not_found = not_found
  @filepath = spec.filepath
  @router = build_router(spec.operations)
end

Public Instance Methods

call(env) click to toggle source
# File lib/openapi_first/router.rb, line 24
def call(env)
  env[OPERATION] = nil
  response = call_router(env)
  if env[OPERATION].nil?
    return @parent_app.call(env) if @parent_app # This should only happen if used via OpenapiFirst.middleware

    raise_error(env) if @raise

    return @app.call(env) if @not_found == :continue
  end
  response
end

Private Instance Methods

build_router(operations) click to toggle source
# File lib/openapi_first/router.rb, line 59
def build_router(operations) # rubocop:disable Metrics/AbcSize
  router = Hanami::Router.new
  operations.each do |operation|
    normalized_path = operation.path.gsub('{', ':').gsub('}', '')
    if operation.operation_id.nil?
      warn "operationId is missing in '#{operation.method} #{operation.path}'. I am ignoring this operation."
    end
    router.public_send(
      operation.method,
      normalized_path,
      to: lambda do |env|
        env[OPERATION] = operation
        env[PARAMETERS] = env['router.params']
        env[Rack::PATH_INFO] = env.delete(ORIGINAL_PATH)
        @app.call(env)
      end
    )
  end
  router
end
call_router(env) click to toggle source
# File lib/openapi_first/router.rb, line 50
def call_router(env)
  # Changing and restoring PATH_INFO is needed, because Hanami::Router does not respect existing script_path
  env[ORIGINAL_PATH] = env[Rack::PATH_INFO]
  env[Rack::PATH_INFO] = Rack::Request.new(env).path
  @router.call(env)
ensure
  env[Rack::PATH_INFO] = env.delete(ORIGINAL_PATH) if env[ORIGINAL_PATH]
end
raise_error(env) click to toggle source
# File lib/openapi_first/router.rb, line 41
def raise_error(env)
  req = Rack::Request.new(env)
  msg =
    "Could not find definition for #{req.request_method} '#{
      req.path
    }' in API description #{@filepath}"
  raise NotFoundError, msg
end