Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No route matches GET /sign_up, but I can visit the page?

I'm getting a strange error logged on my production server for my Rails 4 app:

ActionController::RoutingError: No route matches [GET] "/sign_up"

This is obviously concerning because it would mean new users are unable to sign up. But if I visit that URL, either by typing it in manually, or by clicking on the button on our homepage, I can see the signup page.

There's no redirect, the URL remains the same in the URL bar.

Here's the route in question:

devise_scope :identity do
  get 'sign_in', :to => 'devise/sessions#new'
  get 'sign_up', :to => 'devise/registrations#new'
  get 'sign_out', :to => 'devise/sessions#destroy'
end

Because of a theme hack, the button on our homepage is a form that submits with GET. I thought this might be an issue, but the log shows that it's correctly receiving a GET request.

What's going on here? Where should I start looking to diagnose this?

UPDATE

By the hack on our homepage, what I mean is, due to bootstrap not supporting <a class="btn... in the navbar, we are using a form with method GET to use the kind of button it does support - so from the server perspective, the user is still sending a GET /sign_up when they click that button. This button is just to get them to the /sign_up page (registration_controller#new), it's not the button they press to submit the sign up form with all their details.

(The signup form itself is as normal, ie it sends a POST)

And to be clear, I've walked through the full registration process by hand, and it works. I never get a 404. And the log message does not appear when I do the walk through.

Here's the relevant parts of rake routes

                       Prefix Verb     URI Pattern                                                       Controller#Action
         new_identity_session GET      /identities/sign_in(.:format)                                     devise/sessions#new
             identity_session POST     /identities/sign_in(.:format)                                     devise/sessions#create
     destroy_identity_session DELETE   /identities/sign_out(.:format)                                    devise/sessions#destroy
 cancel_identity_registration GET      /identities/cancel(.:format)                                      identities/registrations#cancel
        identity_registration POST     /identities(.:format)                                             identities/registrations#create
    new_identity_registration GET      /identities/sign_up(.:format)                                     identities/registrations#new
   edit_identity_registration GET      /identities/edit(.:format)                                        identities/registrations#edit
                              PATCH    /identities(.:format)                                             identities/registrations#update
                              PUT      /identities(.:format)                                             identities/registrations#update
                              DELETE   /identities(.:format)                                             identities/registrations#destroy
                      sign_in GET      /sign_in(.:format)                                                devise/sessions#new
                      sign_up GET      /sign_up(.:format)                                                devise/registrations#new
                     sign_out GET      /sign_out(.:format)                                               devise/sessions#destroy

UPDATE 2

We're still getting this issue logged on our production server. The error is coming through rollbar. Interestingly it's not coming up in our production logs. Production logs are using one line logging. We can't reproduce it in development, here's the log for visiting the page:

Started GET "/sign_up" for 127.0.0.1 at 2017-01-02 12:25:10 +0800
Processing by Devise::RegistrationsController#new as HTML
  Rendered identities/shared/_sign_up.html.erb (203.5ms)
  Rendered identities/registrations/new.html.erb within layouts/focused (277.2ms)
  Rendered layouts/_social_headers.html.erb (39.1ms)
  Rendered layouts/_google_analytics.html.erb (6.2ms)
  Rendered layouts/_scripts.html.erb (3618.9ms)
  Rendered layouts/_hotjar.html.erb (4.7ms)
  Rendered layouts/_html_head.html.erb (3708.2ms)
  Nation Load (4.5ms)  SELECT  "nations".* FROM "nations" WHERE "nations"."id" IS NULL  ORDER BY "nations"."id" ASC LIMIT 1
  Rendered layouts/_topnavbar.html.erb (101.0ms)
  Rendered layouts/_breadcrumb.html.erb (7.4ms)
  Rendered layouts/_flash.html.erb (31.4ms)
  Rendered layouts/_footer2.html.erb (8.6ms)
Completed 200 OK in 4223ms (Views: 4203.2ms | ActiveRecord: 4.5ms)
like image 864
ChrisJ Avatar asked Nov 27 '16 21:11

ChrisJ


1 Answers

Turns out this was confusion caused by Rollbar.

Rollbar aggregates exceptions by their class, not their error message by default. So when sending out error reports, the report shows the error message that came from the first ever instance of that exception.

So in our case, our first ever deploy with Rollbar had an error that caused /sign_up to give us a 404 error, which was fixed, but then after that, any 404 generated the same exception class, so when an exploit bot requested, say, /wp-login.php we would get an email from Rollbar that said:

ActionController::RoutingError: No route matches [GET] "/sign_up"

Even though the actual path that caused the most recent error was not /sign_up

We've fixed this by changing our settings on Rollbar under grouping to turn on "Include Exception Message" - so that new 404's aren't grouped together with the /sign_up

I've also added this to the config/initializers/rollbar.rb to filter out some of those 404's from getting sent to Rollbar.

  # Ignore bots trying to hack non existent end-points
  config.exception_level_filters.merge!('ActionController::RoutingError' => lambda { |e|
    e.message =~ %r(No route matches \[[A-Z]+\] "/(.+)")
    case $1.split("/").first.to_s.downcase
    when *%w(myadmin phpmyadmin w00tw00t pma cgi-bin xmlrpc.php wp wordpress cfide)
      'ignore'
    else
      'warning'
    end
  })
like image 140
ChrisJ Avatar answered Oct 20 '22 23:10

ChrisJ