Sinatra - response.set_cookie doesn't work
The documentation on http://sinatra-book.gittr.com/#cookies says to use the set_cookie helper, but in newer versions of Sinatra (at least from 1.2.0+ and possibly earlier), you should use response.set_cookie to set cookies.
response.set_cookie("my_cookie", :value => "value_of_cookie",
:domain => myDomain,
:path => myPath,
:expires => Date.new(2020,1,1))
cookie = request.cookies["my_cookie"]
SUMMARY
don't set localhost
as a domain for your cookies because you need to set it to "" or FALSE
How to set and read raw cookie in Ruby/Sinatra
Use Sinatra Cookies http://www.sinatrarb.com/contrib/cookies.html
require "sinatra/cookies"
cookies[:something] = 'foobar'
You can also read raw cookies in the request object:
request.cookies
As described in Accessing the Request Object
There is also the set_cookie
method of the response object
response.set_cookie("my_cookie", :value => "value_of_cookie",
:domain => myDomain,
:path => myPath,
:expires => Date.new(2020,1,1))
- https://stackoverflow.com/a/5078196/156746
- http://craig-russell.co.uk/2013/01/31/persistent-cookies-sinatra.html#.U9KVFIBdWUA
Why cookie doesn't work using Sinatra and Omniauth?
Is was a trivial problem, just add the path to the cookie: response.set_cookie 'test', {:value=> "facebook_callback", :path => "/"}
The reason why I did not notice was that there is a redirect to "/", so Chrome was only showing me the cookies for the path "/". Removing the redirect, I notice I have two cookies named "test". One with "/" path and the other with "/auth" path.
Sinatra unable to set cookies from helper file
When you require 'sinatra'
certain magic things happen that brings a bunch of stuff into scope and essentially turns your app.rb into an instance of Sinatra::Application
. The cookies
method is only defined on instances like this – it isn’t present on other classes automatically.
What you probably want to do is turn your helper into a real Sinatra style helper by making it a module and then loading it using the helpers
keyword, which will just make these instance methods:
module SessionsHelper
def sign_in(user)
cookies[:remember_token] = { value: user.remember_token, expires: 20.years.from_now.utc }
self.current_user = user
end
...
end
And in your main file:
require './helpers/sessions_helper'
helpers SessionsHelper
...
post '/sign_in' do
user = User.find_by(email: params[:email])
if user && user.authenticate(params[:password])
sign_in user
redirect '/'
else
...
end
You might like to read more about this in the README.
ActionDispatch::Cookies not setting Set-Cookie header in response but response.set_cookie does
I got the reason for this behavior. Actually other team deployed an application gateway
on production. This result in the Rails server getting HTTP request which was HTTPS initially.
Now as I have marked my cookies to be secure: true
, it looks like ActionDispatch::Cookies does not even send cookies in response to a request if the protocol is HTTP. It will only send if protocol is HTTPS. If I disable the secure by secure: false
then it work or if I disable the application gateway then it work with ActionDispatch::Cookie.
It seems strange as secure
is a client side attribute, but from behaviour of ActionDispatch::Cookies it looks like it don't even send cookies from server if protocol is HTTP and secure is set to true.
Although I didn't find any documentation of this behavior, but this is how it's working.
Sinatra cookies vanish on certain routes?
The problem is that the cookie is set with path /cookie
. When you set a cookie your can specify a path, which is effectively a sub-part of the Website that you want the cookie to apply to. I guess Sinatra/Rack use the path of the current request by default which in /cookie/set
would be /cookie
.
You can make it work the way you expect by explicitly specifying the path:
response.set_cookie("TestCookie", {
:expires => Time.now + 2400,
:value => "TestValue",
:path => '/'
})
Or you could set the cookie at a route called say /cookie-set
rather than /cookie/set
Set cookie expiration time in Ruby
Sinatra doesn't have the ActiveSupport
library which provides a helper for number-to-time, so 1.hour.from_now
doesn't works here.
You should use this:
class SinatraApp < Sinatra::Base
use Rack::Session::Cookie, :key => 'rack.session',
:domain => 'foo.com',
:path => '/',
:expire_after => 2592000, # In seconds
:secret => 'some_secret'
And set a time in seconds. Because the Sinatra session comes from Rack::Session
.
HOW TO ENABLE SESSIONS WITH SINATRA
How do I manually set cookie in rails app?
Finally I managed to solve it. So, I added rack_request.rb
in initializers
. And here's the code for it:
require 'rack'
require 'rack/request'
require 'rack/utils'
Rack::Request.class_eval do
def cookies
hash = @env["rack.request.cookie_hash"] ||= {}
string = @env["HTTP_COOKIE"] || "_session_id=#{@env['HTTP_X_SESSION_ID']}"
unless string =~ /\s*_session_id=/i
if @env['HTTP_X_SESSION_ID'].present?
string << "; _session_id=#{@env['HTTP_X_SESSION_ID']}"
end
end
# require 'colorize'
#
# Rails.logger.info 'from cookies'.green
# Rails.logger.info (string.blue)
return hash if string == @env["rack.request.cookie_string"]
hash.clear
# According to RFC 2109:
# If multiple cookies satisfy the criteria above, they are ordered in
# the Cookie header such that those with more specific Path attributes
# precede those with less specific. Ordering with respect to other
# attributes (e.g., Domain) is unspecified.
cookies = Rack::Utils.parse_query(string, ';,') { |s| Rack::Utils.unescape(s) rescue s }
cookies.each { |k, v| hash[k] = Array === v ? v.first : v }
@env["rack.request.cookie_string"] = string
hash
end
end
And I'm sending 'X-SESSION-ID'
in my ajaxHeaders for session id.
Related Topics
Should I Check in '.Ruby-Gemset' And/Or '.Ruby-Version'
Differencebetween "Be_True" and "Be True" in Rspec
Star Rating in Ajax with Ruby on Rails
Check If a File Exists Using a Wildcard
How to Recursively Require All Files in a Directory in Ruby
Ruby on Rails - Differentiating Plural VS Singular Resource in a Rest API
How to Format a String with Floats in Ruby Using #{Variable}
Finding Lines in a Text File Matching a Regular Expression
Rails, Activerecord: Self[:Attribute] VS Self.Attribute
Webkit_Server Hangs Periodically When Run from Capybara in Ruby
How to Specify "Http Request Header" in Openuri
Rails/Rspec: How to Test #Initialize Method
No Such File to Load Bundler Error for Rails 3
Why Is Date.Today - 6.Months + 6.Months != Date.Today
Do You Know an Alternative Ctags Generator for Ruby