devise confirmation_url in HTTPS - ruby-on-rails

My website is entirely SSL, so I would like to have also the urls generated by devise (3.2.2) for Email verification to be https://....
currently the urls are generated by:
confirmation_url(#resource, :confirmation_token => #token)
which produces nice urls like:
http://example.com/users/confirmation?confirmation_token=zqfHS35ckLQZscSbsgMm
I would like the url to be
https://example.com/users/confirmation?confirmation_token=zqfHS35ckLQZscSbsgMm
Also, currently the email verification doesn't work, because nginx operates a redirect to the https equivalent to every page, and for some reasons things get messed up and the https version is a corrupted url, like:
https://example.com/users/confirmation?confirmation_token=zqfHS35ckLQZscSbsgMm?confirmation_token=zqfHS35ckLQZscSbsgMm
for some reasons nginx redirects to this corrupted url, so Unicorn can't but reject the request.
any clues?

You can either specify the protocol in the email template, as you did in your own answer, or you can specify it as a default in the mailer. The simplest way to do this, if you are happy for all emails to use https links, is to add it to your app config. For example, in your production.rb:
config.action_mailer.default_url_options = {:protocol => 'https', :host => 'example.com'}
I know it doesnt matter any more if you're going straight to https, but your url after the nginx redirect from http to https looks like it's appending the query string to the entire url, so it would be worth fixing that so it works in all cases even if you don't need it for the emails any more. If you're using a return 301 … statement in the nginx config, perhaps there's a trailing $query_string or $args you don't need - for example, if you're using $request_uri that already has the GET parameters in it.
Also, I don't think you will find confirmation_url defined directly anywhere. If you try rake routes you'll probably see one of them is:
user_confirmation GET /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"show"}
which means that there will automatically be a user_confirmation_url helper available as with routes in general. I think devise then allows you to use confirmation_url due to its clever tracking of the scope you're using ('user' in this case), though I must admit I haven't looked at the code enough in devise's routing to know exactly how it does it for the routes.

I changed the method call to:
confirmation_url(#resource, :confirmation_token => #token, protocol: "https")
and that started generating correctly the urls with https as required.
I couldn't find the definition of confirmation_url anywhere in the devise code though.

Related

*_url helpers don't work with varying subdomain levels

I've got a site with an api subdomain. On the same domain where the site is located, I've also got a dev subdomain with, you guessed it, a development version of the site.
My issue is that this dev version of the site also has an api subdomain (ie: api.dev.example.com. The routes work without issue using a regex to match the last segment of the subdomain against api (/api(?:\..*)?/), but the *_url helpers do not generate what I would like. Instead of spitting out http://api.dev.example.com/somepath, they spit out http://dev.example.com/somepath.
I'm looking for a solution that doesn't require special handling of the dev site vs the prod site. Subdomain sniffing based on requests so some such nonsense does not appeal to me.
Relevant routes.rb content:
constraints subdomain: /api(?:\..*)?/, format: 'json', protocol: 'http://' do
get '/' => 'example#index'
post '/create', to: 'example#create', as: :api_create_example
end
You can pass the subdomain to the url helper:
fear_and_loathing_in_las_vegas_url(subdomain: 'api.dev')
This will generate http://api.dev.example.com/fear_and_loathing_in_las_vegas

How do I ignore a route in rails?

I have a route i.e. mysite.com:3000/new_route that I'd like to ignore, is this possible to do through rails and not server side?
I've read that this can be done through apache, however, my app is running on Heroku and that type of control isn't accessible to me. Therefore, I'm looking for another way to do this through Rails.
Thanks
update
I am using faye to have live notifications in my app, on localhost faye runs on port 9292 - localhost:9292/faye, all good in development mode, but in production it should point to mydomain.com/faye, there are no port numbers in production environment, and loading faye.js returns error not found
If you're talking about a resources route you don't want to be created:
resources :something, except: :new
However, I'm not exactly sure if this is what you meant by ignore.
You can define a route at the top of your routes.rb file that will redirect to some other page.
get '/new_route', redirect: '/'
By the time you ask Rails to process the route, it is already too late. If you ask rails to process a route, it will, either by returning a 404 of 500 error, or a page.
If you want the route to be processed by another application, it will need to be intercepted by your webserver (nginx or apache, or whichever one you're using). In their configuration, you just redirect that route to the other application, and every other route to the Rails app.
EDIT
Another option you have, is to forward your requests to a different server.
You add a route like
get 'faye/*query' => 'faye#get'
post 'faye/*params' => 'faye#post'
And then a controller
require 'faraday'
class FayeController < ApplicationController
APP = 'http://mydomain.com:9292'
def get
request_page :get
end
def post
request_page :post
end
private
def request_page(method)
conn = Faraday.new(:url => APP)
query = params.delete(:query)
response = conn.send method, query, params
render text: response.body.gsub(APP, 'mydomain.com/faye')
end
end
which will use Faraday to load the information from your other application.

Rails/Rack: retrieving request params from within canonical_host middleware

I'm using the Rack Canonical Host middleware (https://github.com/tylerhunt/rack-canonical-host) with Rails to force the www for all root requests (example.com becomes www.example.com). However, if a visitor is attempting to access a valid subdomain of our app, we obviously don't want to force www. Here's the example usage of the middleware:
Rails.application.config.middleware.use Rack::CanonicalHost do
# the following return value will be used to set the canonical host
'www.example.com'
end
As you can see it's somewhat static, which is a problem. However, if I had access to the request parameters (eg subdomain, domain, etc) I could check against them, and redirect accordingly (and only if need be).
Anyone have any pointers?
Specify a parameter for this block
Rails.application.config.middleware.use Rack::CanonicalHost do |params|
puts "PATH_INFO #{params['PATH_INFO']}"
end

Functional test "get" requests and the https protocol

I'm trying to write a functional test for an action that must run over https. I'm not testing the HTTPS redirect - I already know that works from another test.
What I'm trying to do is:
get :new, :protocol => "https://"
assert_redirected_to :root
But this does not issue the request over https. Is there a "get" option that will allow me to change the protocol?
Also, if I try to specify the url (e.g.: get "https:/test.host/do/something") I get a routing error, since there's no route at my rails level for https - it's taken care of at my web server level.
I found a much simpler answer here:
http://railspikes.com/2008/9/12/testing-ssl
Which is to put the following line either (a) at the beginning of each functional test where SSL is needed, or (b) in the 'setup' method if every action in a controller uses SSL.
#request.env['HTTPS'] = 'on'
This prepends all requests with https
In functionnal test, there are no routing from HTTP or anything else, it's use directly the controller. So you can't test that become from HTTP or HTTPS.
But you can mock the request.protocole dans define it like 'https'
request.stub(:protocol).and_return("https://")
get :new

Custom URLs in Rails of the form custom.site.com

I would like to have my users specify custom URL paths such that those paths are placed in front of my site's name, i.e. if I have a site called www.orion.com, I'd like a user to be able to create his own little home page at johnny.orion.com.
I have successfully managed to implement orion.com/johnny, which works implemented by adding map.connect ':path' at the end of my routes then making sure the path variable is present when needed.
How can I get johnny.orion.com to function?
First, you'll need to set up wildcard DNS - so that the subdomains actually resolve to somewhere.
Then, configure your virtual host to accept connections from these subdomains:
# If you're using Apache, something like:
ServerAlias *.orion.com
Then, you can use the subdomain-fu gem to handle your routes within Rails. Have a look at the associated Railscast for some good tips.
The syntax for the gem is something like this:
link_to 'Posts', post_path(#post, :subdomain => 'johnny')
johnny.orion.com/posts/4

Resources