3

I am using Kaminari to handle pagination. I recently found out that a lot of bogus request is requesting an invalid page number, such as /post/page/undefined. Since I am using Solr, bad page number got passed into it and cause 500 error.

I want to be able to validate the page number, before it gets passed to the controller. So invalid page number will cause routing error instead.

I have asked the creator of Kaminari, and he gave a temporary solution. However I am wondering if there are cleaner ways to do this. I also don't want to include this logic in every paginable resource, as that will be not DRY at all.

My route example:

resources :transactions do
  get 'page/:page', :action => :index, :on => :collection
end
lulalala
  • 17,572
  • 15
  • 110
  • 169

3 Answers3

0

I think a good solution is to simply remove or correct any invalid or frivolous page parameters and redirect to the corrected URL, like so:

# This goes in your relevant controller(s)
before_filter :correct_page_parameters!

# This goes in your application controller
def correct_page_parameters!
  supplied_parameters = params[:page]
  if supplied_parameters        
    proper_parameters = supplied_parameters.to_i

    if proper_parameters < 2
      params.delete(:page)
      redirect_to params
    elsif supplied_parameters != proper_parameters.to_s
      redirect_to params.merge(:only_path => true, :page => proper_parameters)
    end
  end
end

Hope this helps, good luck!

Brad Werth
  • 17,411
  • 10
  • 63
  • 88
-1

As suggested by amatsuda in the link you provided, use constraints.

Refer to this question (similar to yours)...

I recommend adopting the more RESTful routes, described by

resources :posts # or :transactions

Then requests to /post/page/blah will 404 (as they should), while GET requests to /posts will behave as defined in your application.

Community
  • 1
  • 1
rthbound
  • 1,323
  • 1
  • 17
  • 24
  • Well, is there a prettier way to use constraint than his solution? And how can I default to page 1 in a DRY way across controllers? – lulalala Oct 31 '12 at 02:15
  • I'd recommend taking page out of the url and putting it in the query string... that way it's optional... in your controller you could call for `params[:page] || 1` – rthbound Oct 31 '12 at 02:18
  • I want to use action caching so I used the url approach. Your defaulting to 1 won't work if request is `page=undefined` – lulalala Oct 31 '12 at 02:30
  • sorry, why does sending params in the query string prevent using action caching? – rthbound Oct 31 '12 at 02:41
  • [Rails does not make any distinction between query string parameters and POST parameters, and both are available in the params hash in your controller](http://guides.rubyonrails.org/v2.3.11/action_controller_overview.html#parameters) – rthbound Oct 31 '12 at 03:13
  • Ok it only affects page caching: http://guides.rubyonrails.org/caching_with_rails.html#highlighter_627788 but it is prettier – lulalala Oct 31 '12 at 06:10
-1

You could validate page in routes like that:

resources :transactions do
  get 'page/:page', :action => :index, :on => :collection, :page => /\d/
end