Skip to content

Instantly share code, notes, and snippets.

@eirc
Created March 16, 2012 10:46
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save eirc/2049542 to your computer and use it in GitHub Desktop.
Save eirc/2049542 to your computer and use it in GitHub Desktop.
# Rack middleware that drops non properly encoded cookies that would hurt the ActionDispatch::Cookies middleware.
#
# This is actually a hotfix for issues
# * https://github.com/rack/rack/issues/225
# * https://github.com/rails/rails/issues/2622
module CleanCookies
# Tests whether a string may be decoded as a form component
def decodable?(string)
URI.decode_www_form_component(string)
true
rescue ArgumentError => e
/^invalid %-encoding \(.*\)$/.match(e.message) ? false : raise
end
module_function :decodable?
# Tests whether a cookie is clean, that is its key and value may be decoded as a form components
def clean?(cookie)
key, value = cookie.split('=', 2)
decodable?(key) && decodable?(value)
end
module_function :clean?
class Rack
def initialize(app)
@app = app
end
def call(env)
if env['HTTP_COOKIE']
clean_cookies, dirty_cookies = [], []
# Split cookies into clean and dirty
env['HTTP_COOKIE'].split(/[;,] */n).each do |cookie|
if CleanCookies::clean?(cookie)
clean_cookies << cookie
else
dirty_cookies << cookie
end
end
# Keep only clean cookies
env['HTTP_COOKIE'] = clean_cookies.join('; ')
# Inform about dropped dirty cookies
unless dirty_cookies.empty?
env['rack.errors'].puts "Ignoring dirty cookies: #{dirty_cookies.inspect}"
end
end
# Carry on
@app.call(env)
end
end
end
# Automatically insert self in a Rails 3 middleware stack
if defined?(Rails.configuration) && Rails.configuration.respond_to?(:middleware)
Rails.configuration.middleware.insert_before ActionDispatch::Cookies, CleanCookies::Rack
end
@morenocarullo
Copy link

Hi, did you manage to eventually include this into rack-contrib? I'm writing a pull request for this, mentioning your code.

@viniciusnz
Copy link

Thanks a lot for this! This should be the rack default behaviour, not giving a 500 error... You're the best!

@dejan
Copy link

dejan commented Oct 20, 2012

Thank you, it works great!

@kakubei
Copy link

kakubei commented Oct 16, 2013

I have a similar error but with handling a binary POST instead of cookies. How would I handle that for this line?

Rails.configuration.middleware.insert_before ActionDispatch::Cookies, CleanCookies::Rack

I created a CatchPost method, but my doubt is the ActionDispatch:: bit, how do I tell it to insert before handling a POST?

Sorry if this sounds dumb but I know nothing about Rack.

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment