Sinatra: how to store params hash in a session? - session

enable :sessions
post '/sending_out' do
session[:data] = params.inspect
params.inspect
end
params.inspect contains exactly the hash I want to pass in a session variable. If I copy it from the output on a page and paste in here session[:data] = {hash-from-page}, my further code works fine.
What's going on? Isn't params a simple hash?

Sessions are disabled by default. You need to enable them and then use the session hash from routes and views.
This means your code is correct you just forget to enable sessions so just add:
configure do
enable :sessions
end

Related

Is there a simple way to have persistent form data in SInatra? Or does it require I write form variables to a file and read them manually?

I have a form in Sinatra with 4 text fields. When the page is closed and then reopened I would like to fill the text fields with the values that were last submitted.
I am doing this currently by writing each variable to a file in the same folder, and then reading them back when the program starts. I would like to know if there is an easier way to do this.
Is there an already implemented system in Ruby/Sinatra that allows me to write form data to a file and then read it back somehow?
The best way to handle such situations in sinatra is to use sessions instead of having to write it to a file and retrieve it.
Enable sessions in your configure block.
configure do
enable :sessions
set :session_secret, "secret"
end
in your before block
before do
session[:user_input] ||= []
end
Then pass the user input values in the sessions object. From there it can be retrieved as long as the user sessions is active.

Sinatra app that redirects POST/GET requests with parameters

I'm migrating servers but unfortunately the old server IP is hardcoded inside my iPhone app. Obviously I'm going to submit an update that sets the API endpoint to my new server, but in the meantime I need to setup an app on the old server that redirects all the requests to the new server. I've heard Sinatra would be perfect for this.
require 'sinatra'
get "/foo/bar" do
redirect "http://new-server.com/foo/bar", 303
end
post "/foo/bar" do
redirect "http://new-server.com/foo/bar", 303
end
The problem is that these do not forward the GET or POST parameters along with the request. I read on the Sinatra doc that you can do that by putting them in the URL directly (works for GET requests), or by setting session variables.
Is manually parsing and formatting the GET params to put them back into the redirect URL the only way to go for GET redirects? How are you supposed to forward POST parameters?
For GET requests, use request.fullpath or request.query_string. For POST request, use status code 307, so the subsequent request will be a POST with the same parameters.
helpers do
def new_url
"http://new-server.com" + request.fullpath
end
end
get "/foo/bar" do
redirect new_url
end
post "/foo/bar" do
redirect new_url, 307
end
I would overload the Hash class in lib/overload_hash.rb, like so:
class Hash
def to_url_params
elements = []
keys.size.times do |i|
elements << "#{keys[i]}=#{values[i]}"
end
elements.join('&')
end
end
EDIT (Better solution using net / http)
Place a require "lib/overload_hash", require "net/http" and require "uri" under require 'sinatra'. The following example can be translated into GET easily.
post '/foo/bar' do
uri = URI.parse("http://example.com/search")
response = Net::HTTP.post_form(uri, params.to_ur_params)
response
end

How do I set the session param for multiple namespaces?

If I am handling authentication manually, and am setting session like so:
session[:user_id] = authenticated.user.id
user_id does not show up in my session hash when viewed from another namespace. In this instance I have a namespace :api, and session doesn't show up at api/show/current. How do I set the session hash to be viewed in both namespaces?
The session is completely independent from namespaces, maybe there is something else wrong with your app?
where do you set the user_id?
maybe providing more code helps

Getting unique session ID in Sinatra

I have a simple web app built using Sinatra, with sessions enabled.
If I am understanding correctly, the session data is stored in an encoded cookie. As the session data changes, the value of the cookie will change also.
I need a unique session identifier that remains constant through the entire session. Is there such an identifier. Or must I create my own unique value and store it in the session myself?
Thanks!
EDIT: In a comment below I thought of a useful comparison. If I had a Java servlet, I would use the JSESSIONID as a unique identifier. I need a Sinatra equivalent to the JSESSIONID.
Because this is one of the first Google results for the subject and it contains no actual examples, here is a simple way to create your own SESSION_ID. We're relying on probability and cryptographically secure randomness to keep our IDs unique.
This is the only thing I put in my cookies. I keep all the other data on the back end to prevent anyone from tampering with it.
require 'sinatra'
require 'securerandom'
# The configuration here is just an example. Use your own secret, etc.
use Rack::Session::Cookie, :key => 'SESSION_ID',
:expire_after => 60*60*24, # == one day
:secret => 'This one time, at band camp...'
before do # Before every request, make sure they get assigned an ID.
session[:id] ||= SecureRandom.uuid
end
get '/' do # Show off your new ID.
"Your ID is #{session[:id]}"
end
In a sinatra app if you print out session.keys, you'll see there is a "session_id" that contains the unique id for the current session. You can access this 64 byte string as session["session_id"].
As the session data changes, the value of the cookie will change also.
This is true only if you're using cookies to store your session data, which is the default session storage used by sinatra. More details at http://rubydoc.info/github/rack/rack/master/Rack/Session.
I need a unique session identifier that remains constant through the entire session. Is there such an identifier. Or must I create my own unique value and store it in the session myself?
You can access sinatra session id using the id instance method on the session instance of Rack::Session::Abstract::SessionHash. More details at http://rubydoc.info/github/rack/rack/master/Rack/Session/Abstract/SessionHash#id-instance_method.
Example:
require 'sinatra'
configure do
enable :sessions
end
get '/' do
session.id
end
From what I can tell JSESSIONID is used to pass the session around in a query string, and Sinatra doesn't have something like that, at least not easily accessible. Sinatra uses Rack for session management, and by default uses a cookie to store all session data. There are other session options in Rack, like memcached, where a unique session id is stored in a cookie, but even there Rack abstracts that away so you don't ever need to see the session id (though it is still accessible, see the documentation).
If you want to go that route then look into messing with the Rack middleware in Sinatra, but if all you need is a unique id, then it would probably be easier to generate one yourself and store it in the session.

Using Cookies with Rack::Test

I'm trying to write RSpec tests for my Sinatra application using Rack::Test. I can't understand how I can use cookies. For example if my application set cookies (not via :session) how can I check whether that cookie is properly set?
Also, how can I send requests with that cookie?
Rack::Test keeps a cookie jar that persists over requests. You can access it with rack_mock_session.cookies. Let's say you have a handler like this:
get '/cookie/set' do
response.set_cookie "foo", :value => "bar"
end
Now you could test it with something like this:
it 'defines a cookie' do
get '/'
rack_mock_session.cookie_jar["foo"].should == "bar"
end
You can also access cookies with last_request.cookies, but as the name says, it contains the cookies for the last request, not the response. You can set cookies with set_cookie and clear them with clear_cookies.
it 'shows how to set a cookie' do
clear_cookies
set_cookie "foo=quux"
get '/'
last_request.cookies.should == {"foo" => "quux"}
end
Update: If you want the cookie jar to persist across the test cases (it blocks), you need to initialize the Rack session before executing any test cases. To do so, add this before hook to your describe block.
before :all do
clear_cookies
end
Alternative, you could for example use before :each to set up the necessary cookies before each request.

Resources