I can't find any simple examples for using Rack::Session::Cookie and would like to be able to store information in a cookie, and access it on later requests and have it expire.
These are the only examples I've been able to find:
How do I set/get session vars in a Rack app?
http://rack.rubyforge.org/doc/classes/Rack/Session/Cookie.html
Here's what I'm getting:
use Rack::Session::Cookie, :key => 'rack.session',
:domain => 'foo.com',
:path => '/',
:expire_after => 2592000,
:secret => 'change_me'
And then setting/retrieving:
env['rack.session'][:msg]="Hello Rack"
I can't find any other guides or examples for the setup of this. Can someone help?
You have already setup cookie in your question. I am not sure if you means something else by "setup".
Instead of env['rack.session'] you can use session[KEY] for simplification.
session[:key] = "vaue" # will set the value
session[:key] # will return the value
Simple Sinatra example
require 'sinatra'
set :sessions, true
get '/' do
session[:key_set] = "set"
"Hello"
end
get "/sess" do
session[:key_set]
end
Update
I believe it wasn't working for you because you had set invalid domain. So I had to strip that off :domain => 'foo.com',. BTW Sinatra wraps Rack cookie and exposes session helper. So above code worked fine for me. I believe following code should work as expected.
require 'sinatra'
use Rack::Session::Cookie, :key => 'rack.session',
:expire_after => 2592000,
:secret => 'change_me'
get '/' do
msg = params["msg"] || "not set"
env["rack.session"][:msg] = msg
"Hello"
end
get "/sess" do
request.session["msg"]
end
set session value msg access root or / defaults to 'not set' if you pass ?msg=someSTring it should set msg with new value.
access /sess to check whats in session.
You can take some cues from How do I set/get session vars in a Rack app?
Check the example below. It might give you good idea
http://chneukirchen.org/repos/rack/lib/rack/session/cookie.rb
Related
So i've been using sinatra and well no matter what i try i cannot seem to get sessions to work as intended.
Im enabling session/cookies with the following:
use Rack::Session::Cookie, :key => 'localhost_tester',
:path => '/',
:expire_after => 14400, # In seconds
:secret => 'secret_stuff'
And im trying to create a login page, the post data seems to be getting sent but no session is being created. This is what im using:
get '/account-login' do
#title = 'Adnetwork'
erb :accounts
end
post '/account-login' do
email = params[:email]
password = params[:password]
user = User.new()
if user.login(email, password)
#session isnt being made...
session['email'] = email
#redirect once session is complete
redirect to'/dashboard'
else
erb :accounts
end
end
The session wont actually be called "email" thats just an example i was using while testing. But it never actually creates the session. I have cookie editor plugin on chrome to see whats happening and the only thing thats being created is a session called "localhost" tester.
Am i being an idiot and doing it all wrong or is it something else that im missing?
I am using Ruby with Sinatra do develop a web application.
I have Ruby version 2.3.0, Sinatra 5.0.30
Following the suggestions from Rails cookies, set start date and expire date, I tried this:
#language = 'en-US'
response.set_cookie(:USER_LANGUAGE, :value => #language, :expires => 1.hour.from_now, :domain => '.example.com')
At first I thought it worked because the cookie set except the expiration time is still just only for the session. The error in my Apache error log says this:
NoMethodError - undefined method 'hour' for 1:Fixnum:
Please note: none of these worked to resolve the problem (none of them could be properly found by the compiler)
require 'active_support'
require 'active_support/all'
require 'activesupport'
So, I tried this instead:
#language = 'en-US'
response.set_cookie(:USER_LANGUAGE, :value => #language, :expires => 30, :domain => '.example.com')
Just to see what would happen and nothing changed, it still only expires with the session.
How should I go about setting an expiration time for my cookies in Ruby with Sinatra?
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
I am using Ruby and Sinatra to develop an application.
I use
enable :sessions
in order to use the session variable provided by rack. How can I make all of the session cookies be HTTPOnly? Is it like this by default? I can't find any documentation on this.
Instead of enable :sessions:
use Rack::Session::Cookie, {:httponly => true }
I'd suggest using the encrypted_cookie gem instead, it's far more secure. As an example, here's what I'll probably have for a project:
# app/main.rb
module Example
class App < Sinatra::Base # this class in its own file
# stuff here
end
end
# app/config.rb
require "main"
module Example
def self.app #
Rack::Builder.app do
cookie_settings = {
:key => 'usr',
:path => "/",
:expire_after => 86400, # In seconds, 1 day.
:secret => ENV["COOKIE_KEY"], # load this into the environment of the server
:httponly => true
}
cookie_settings.merge!( :secure => true ) if ENV["RACK_ENV"] == "production"
# AES encryption of cookies
use Rack::Session::EncryptedCookie, cookie_settings
# other stuff here
run App
end
end
end
# config.ru
require "app/config"
run Example.app # this in the rackup file
(To clarify why I've laid it out this way - this kind of stucture allows me to split the app up and use it easier in tests by just requiring the app/config.rb. YMMV)
I'm making a short URL app, using Ruby, Sinatra, and Redis. Currently it's under 15 lines:
require 'rubygems'
require 'sinatra'
require 'redis'
require 'uri'
configure do
REDISTOGO_URL = "redis://localhost:6379/"
uri = URI.parse(REDISTOGO_URL)
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
end
get '/' do
haml :index
end
post '/shorten' do
a = rand(9999)
REDIS.set(a.to_s, params[:long])
"<pre>http://199.19.118.186/get/#{a}</pre>"
#haml :shorten
end
get '/get/:url' do
redirect REDIS.get(params[:url])
end
Where index.haml is a form that POSTs long to /shorten. I've no problem with that.
Right now, however, when I try to use Redis (with the server running, yes), I get this error:
What am I doing wrong?
EDIT: Copy/paste from Emacs... facepalm
EDIT: When trying to access redis alone from ruby (code below), I get this:
/var/lib/gems/1.8/gems/redis-2.2.2/lib/redis/client.rb:47:in `call': ERR unknown command (RuntimeError)
from /var/lib/gems/1.8/gems/redis-2.2.2/lib/redis.rb:841:in `set'
from /usr/lib/ruby/1.8/monitor.rb:242:in `synchronize'
from /var/lib/gems/1.8/gems/redis-2.2.2/lib/redis.rb:840:in `set'
from test_redis.rb:9
With this code:
require 'rubygems'
require 'redis'
require 'uri'
REDISTOGO_URL = "redis://localhost:6379/"
uri = URI.parse(REDISTOGO_URL)
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
REDIS.set("test", "blah")
puts REDIS.get("test")
Ruby being case sensitive, I would try to replace REDIS.SET by REDIS.set and REDIS.GET by REDIS.get. You can find the documentation of the Redis client here:
https://github.com/ezmobius/redis-rb
I have tested your example with ruby 1.8.7. (default on my Linux box).
After installing sinatra, haml, redis and hiredis gems, I have modified the code as follows:
require 'rubygems'
require 'sinatra'
require 'redis'
require 'uri'
configure do
REDISTOGO_URL = "redis://localhost:6379/"
uri = URI.parse(REDISTOGO_URL)
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
end
get '/' do
"Hello"
haml :index
end
post '/shorten' do
a = rand(9999)
REDIS.set(a.to_s, "http://"+params[:long])
"<pre>http://localhost:4567/get/#{a}</pre>"
end
get '/get/:url' do
redirect REDIS.get(params[:url])
end
I have added the following template in views/index.haml.
!!!
%html
%head
%title My Sinatra Website
%body
%h1 Welcome
%p
Welcome to my website made with Sinatra and HAML
%form{ :action => "/shorten", :method=>"POST" }
%fieldset
%input{ :type =>"text", :name=>"long" }
%input{ :type =>"submit" }
Once Redis is started on port 6379 and sinatra on port 4567, it works like a charm.
I suggest you check your ruby installation and try to access Redis from ruby with a simple non sinatra script.
UPDATE:
The error message is peculiar because normally, when an unknown command is sent to the server, the faulty command is provided:
ERR unknown command 'dummy'
while you just have:
ERR unknown command
Actually, this specific fix was introduced in Redis server more than 2 years ago (in December 2009) - an eternity for Redis.
https://github.com/antirez/redis/commit/2c14807b2dd5c15f1471bec32a7c6dbb077720ee
In other words, you are trying to use a very old (i.e. pre 1-3) version of Redis server with the last version of the Redis client ruby gem, which probably does not support anymore the initial protocol. You may want to compile and install a recent version of Redis server (it is easy), it should work better.
Is it possible to to rewrite the base URL?
E.g. instead of www.host.com/ to use www.host.com/blah/ as
a base url and so:
get '/' do
...
end
would work for www.host.com/blah/
I could append to all my routes '/blah/..' but any gems etc.
would fail to work as well.
This can be done in Rails easily and I would like to have it in Sinatra as well.
I use a rack middleware for this rack-rewrite and I am quite happy with it :)
use Rack::Rewrite do
rewrite %r{^/\w{2}/utils}, '/utils'
rewrite %r{^/\w{2}/ctrl}, '/ctrl'
rewrite %r{^/\w{2}/}, '/'
end
EDIT:
Not sure if I understand your problem, but here are a config.ru file
# encoding: utf-8
require './config/trst_conf'
require 'rack-flash'
require 'rack/rewrite'
use Rack::Session::Cookie, :secret => 'zsdgryst34kkufklfSwsqwess'
use Rack::Flash
use Rack::Rewrite do
rewrite %r{^/\w{2}/auth}, '/auth'
rewrite %r{^/\w{2}/utils}, '/utils'
rewrite %r{^/\w{2}/srv}, '/srv'
rewrite %r{^/\w{2}/}, '/'
end
map '/auth' do
run TrstAuth.new
end
map '/utils' do
run TrstUtils.new
end
map '/srv' do
map '/tsk' do
run TrstSysTsk.new
end
map '/' do
run TrstSys.new
end
end
map '/' do
run TrstPub.new
end
and an example Sinatra::Base subclass
# encoding: utf-8
class TrstAuth < Sinatra::Base
# Render stylesheets
get '/stylesheets/:name.css' do
content_type 'text/css', :charset => 'utf-8'
sass :"stylesheets/#{params[:name]}", Compass.sass_engine_options
end
# Render login screen
get '/login' do
haml :"/trst_auth/login", :layout => request.xhr? ? false : :'layouts/trst_pub'
end
# Authentication
post '/login' do
if user = TrstUser.authenticate(params[:login_name], params[:password])
session[:user] = user.id
session[:tasks] = user.daily_tasks
flash[:msg] = {:msg => {:txt => I18n.t('trst_auth.login_msg'), :class => "info"}}.to_json
redirect "#{lang_path}/srv"
else
flash[:msg] = {:msg => {:txt => I18n.t('trst_auth.login_err'), :class => "error"}}.to_json
redirect "#{lang_path}/"
end
end
# Logout
get '/logout' do
session[:user] = nil
session[:daily_tasks] = nil
flash[:msg] = {:msg => {:txt => I18n.t('trst_auth.logout_msg'), :class => "info"}}.to_json
redirect "#{lang_path}/"
end
end
maybe this helps :) full source on github.
In a before block you can edit env['PATH_INFO]`; Sinatra will then use the edited value for routing.
For your example, something like this might work...
before do
env['PATH_INFO'].sub!(/^\/blah/, '')
end
I agree with the other answers that using a middleware component is a more robust solution but if you want something concise and simple, that works inside the Sinatra app instead of via config.ru, then munging the Rack environment is not bad.
You could have a look at https://github.com/josh/rack-mount, maybe that one can help you out?