Class: Praxis::Router

Inherits:
Object
  • Object
show all
Defined in:
lib/praxis/router.rb

Defined Under Namespace

Classes: RequestRouter, VersionMatcher

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(application, request_class: Praxis::Request) ⇒ Router

Returns a new instance of Router.



43
44
45
46
47
48
49
# File 'lib/praxis/router.rb', line 43

def initialize(application, request_class: Praxis::Request)
  @routes = Hash.new do |hash, verb|
    hash[verb] = RequestRouter.new
  end
  @request_class = request_class
  @application = application
end

Instance Attribute Details

#applicationObject (readonly)

Returns the value of attribute application.



7
8
9
# File 'lib/praxis/router.rb', line 7

def application
  @application
end

#request_classObject (readonly)

Returns the value of attribute request_class.



7
8
9
# File 'lib/praxis/router.rb', line 7

def request_class
  @request_class
end

Instance Method Details

#add_route(target, route) ⇒ Object



51
52
53
54
55
56
57
58
59
60
# File 'lib/praxis/router.rb', line 51

def add_route(target, route)
  path_versioning = (Application.instance.versioning_scheme == :path)

  # DEPRECATED: remove with EndpointDefinition.version using: :path
  path_versioning ||= (target.action.endpoint_definition.version_options[:using] == :path)

  target = VersionMatcher.new(target, version: route.version) unless path_versioning

  @routes[route.verb].on(route.path, call: target)
end

#call(env_or_request) ⇒ Object



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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/praxis/router.rb', line 62

def call(env_or_request)
  request = case env_or_request
            when Hash
              request_class.new(env_or_request)
            when request_class
              env_or_request
            else
              raise ArgumentError, "received #{env_or_request.class}"
            end

  verb = request.verb
  r = (@routes.key?(verb) ? @routes[verb] : nil) # Exact verb match
  result = r.call(request) if r
  # If we didn't have an exact verb route, or if we did but the rest or route conditions didn't match
  if r.nil? || result == :not_found
    # Fallback to a wildcard router, if there is one registered
    result = if @routes.key?('ANY')
               @routes['ANY'].call(request)
             else
               :not_found
             end
  end

  if result == :not_found
    # no need to try :path as we cannot really know if you've attempted to pass a version through it here
    # plus we wouldn't have tracked it as unmatched
    version = request.version
    attempted_versions = request.unmatched_versions
    body = 'NotFound'
    unless attempted_versions.empty? || (attempted_versions.size == 1 && attempted_versions.first == 'n/a')
      body += if version == 'n/a'
                '. Your request did not specify an API version.'
              else
                ". Your request specified API version = \"#{version}\"."
              end
      pretty_versions = attempted_versions.collect(&:inspect).join(', ')
      body += " Available versions = #{pretty_versions}."
    end
    headers = { 'Content-Type' => 'text/plain' }
    headers['X-Cascade'] = 'pass' if Praxis::Application.instance.config.praxis.x_cascade
    result = [404, headers, [body]]
  end
  result
end