I'm using devise_token_auth and everything works well until I add API constraints to the routes: constraints: ApiConstraint.new(version: 4, default: true)
Rails.application.routes.draw do
namespace :api do
scope module: :v4, constraints: ApiConstraint.new(version: 4, default: true) do
# Token auth routes available at /api/auth
mount_devise_token_auth_for "User", at: "auth"
end
end
end
Adding these constraints restrain access to the routes unless the request contains the correct headers:
class ApiConstraint
attr_reader :version
VENDOR_MIME = "application/vnd.myproject-v%d"
def initialize(version: "4", default: false)
@version, @default = version, default
end
def matches?(request)
byebug # <-- I wish there was something like request.current_path available
return @default unless request.headers.key?("accept")
request
.headers
.fetch("accept")
.include?(VENDOR_MIME % version)
end
end
I realised this is problematic for the reset password link which we get by email:
https://myproject.herokuapp.com/api/auth/password/edit?reset_password_token=...
... as it can't carry any headers!
I could redirect the user to a webpage which then does an AJAX call with the appropriate headers, but I was wondering if there was a way to enhance my routes.rb
or ApiConstraint
class to make an exception on the /auth/password/edit
route?
You can use request.url
, request.fullpath
, request.params
to access the data you need.
More importantly, in order to figure out what methods are available to you at runtime, once the REPL opens up on the line where you put your byebug
debugger entry, you can use these following methods (assuming your using pry
):
ls # display everything in the current scope
cd request # or any other variable or instance variable.
cd .. # you can navigate your code as if it was a filesystem
request.methods.grep /path/
request.methods.grep /url/
request.methods.grep /param/
# or
cd request
methods.grep /query/
OP update
# api_constraint.rb
def initialize(version: "4", default: false, exceptions: [])
@version, @default, @exceptions = version, default, exceptions
end
def matches?(request)
return true if @exceptions.include? request.path
...
end
#routes.rb
scope module: :v4, constraints: ApiConstraint.new(version: 4, default: true, exceptions: [
"/api/auth/password/edit"
]) do
...
end