Read cookie

How can I get the value of a browser cookie with Ruby?

Pål Bergström wrote:

How can I get the value of a browser cookie with Ruby?

In what framework? CGI? Rack? Rails? Sinatra? Other?

If you are writing a CGI there is a ‘cookies’ accessor. For details see
the comments in the source at /usr/lib/ruby/1.8/cgi.rb (or wherever it
is installed on your system)

Brian C. wrote:

Pål Bergström wrote:

How can I get the value of a browser cookie with Ruby?

In what framework? CGI? Rack? Rails? Sinatra? Other?

If you are writing a CGI there is a ‘cookies’ accessor. For details see
the comments in the source at /usr/lib/ruby/1.8/cgi.rb (or wherever it
is installed on your system)

It’s rails. I used CGI but doesn’t seem to work anymore. I just want to
get a value of a cookie with a ruby script in /lib. What about net/http?

Brian C. wrote:

In what framework? CGI? Rack? Rails? Sinatra? Other?

Btw, I’m not sure I follow. Does it have to be within a framework?
Isn’t the framework built with ruby in the first place? Never mind
Rails. I don’t need the cookie there. That’s easy. I need it in a script
in /lib.

2010/9/3 Pål Bergström [email protected]:

It’s rails.

And have you looked for ‘cookie’ in the Rails API docs? :slight_smile:

Hassan S. wrote:

2010/9/3 P�l Bergstr�m [email protected]:

It’s rails.

And have you looked for ‘cookie’ in the Rails API docs? :slight_smile:

I’m asking about getting a cookie value in Ruby, not Rails.

Pål Bergström wrote:

Hassan S. wrote:

And have you looked for ‘cookie’ in the Rails API docs? :slight_smile:

I’m asking about getting a cookie value in Ruby, not Rails.

Can I get the value using Rack?

2010/9/3 Pål Bergström [email protected]:

Brian C. wrote:

In what framework? CGI? Rack? Rails? Sinatra? Other?

Btw, I’m not sure I follow. Does it have to be within a framework?
Isn’t the framework built with ruby in the first place? Never mind
Rails. I don’t need the cookie there. That’s easy. I need it in a script
in /lib.

So, you need to make a request to a site and get the cookie that the
server sends back?
If that’s the case then try this:

require ‘mechanize’

agent = WWW::Mechanize.new
page = agent.get(“http://www.google.com”)
p agent.cookies

Jesus.

Jesús Gabriel y Galán wrote:

So, you need to make a request to a site and get the cookie that the
server sends back?
If that’s the case then try this:

require ‘mechanize’

agent = WWW::Mechanize.new
page = agent.get(“http://www.google.com”)
p agent.cookies

It reguards my own site.

Looks great and simple. Is Mechanize someting I need to install or is it
part of Ruby?

Looks great and simple. Is Mechanize someting I need to install or is it
part of Ruby?

I need to install Nokogiri first :slight_smile:

Hassan S. wrote:

In short, what is the context?

Using a personal encryption script in models, with a key stored in a
cookie. For making certain data encrypted when saving to the database
using ‘before_save’. Can’t get that through Rails.

2010/9/3 Pål Bergström [email protected]:

I’m asking about getting a cookie value in Ruby, not Rails.

So where would you be “getting” this cookie from? Stored in a file? As
part of an HTTP request? If the latter, what’s handling the request in
the first place?

In short, what is the context?

Pål Bergström wrote:

It’s rails. I used CGI but doesn’t seem to work anymore. I just want to
get a value of a cookie with a ruby script in /lib. What about net/http?

It’s not clear what you want now.

Are you writing a web client in Ruby - something which initiates a
connection to a web server, and sends a HTTP request? (Like a browser)

Or a web server - something which listens for incoming HTTP requests,
and answers them?

net/http is something you’d use for the former, and rails is something
you’d use for the latter.

The cookie interaction is described at:

Roughly:

  • The server includes a “Set-Cookie:” header in a response
  • The client includes a “Cookie:” header in each subsequent request to
    the same server

When you say you want to “get the value of a browser cookie” it sounds
like you’re writing something server-side, to extract the cookies sent
by the browser. But if you’re writing a client using net/http or
mechanize, then it’s you who sends the cookies with each request in
the first place.

Jesús Gabriel y Galán wrote:

require ‘mechanize’

agent = WWW::Mechanize.new
page = agent.get(“http://www.google.com”)
p agent.cookies

Got it working when installed as a gem. Thank you so much :slight_smile: Don’t
understand why I didn’t get an answer before. I’ve asked about this
severeal times. Hopefully I’m on the right track now.

I do get a cookie. A session cookie. But how do I get a particular
cookie?

When you say you want to “get the value of a browser cookie” it sounds
like you’re writing something server-side, to extract the cookies sent
by the browser. But if you’re writing a client using net/http or
mechanize, then it’s you who sends the cookies with each request in
the first place.

I’m sorry if I’m unclear. But I don’t understand what the problem is
with my question. So let me ask again.

Before I could get the value in a cookie, any cookie, from a browser
visiting a rails app using cgi. I used it in Rails in order to get a
unique string into the model. I can’t use cookies[:cookie_name] for
that. As I understand it I can’t do that with Rails 2.3.x ( or 3?).
That’s what I want to do.

Pål Bergström wrote:

I’m sorry if I’m unclear. But I don’t understand what the problem is
with my question. So let me ask again.

Before I could get the value in a cookie, any cookie, from a browser
visiting a rails app using cgi. I used it in Rails in order to get a
unique string into the model.

(Presumably a unique string which your app provided in a previous
request, via Set-Cookie)

I can’t use cookies[:cookie_name] for
that. As I understand it I can’t do that with Rails 2.3.x ( or 3?).

Are you sure? Have you tried it? The method seems to be there:
http://api.rubyonrails.org/classes/ActionController/Cookies.html

Or you could try request.cookies[“cookie_name”] instead.

However, in a rails app you rarely manipulate cookies directly. Rather
you’d do:

session[:foo] = “bar”

By default, Rails serialises the entire session object, signs it
cryptographically, and then sends it to the client as a cookie. This
allows you to store sensitive information (e.g. admin rights) whilst
being sure the user will not be able to tamper with it.

Brian C. wrote:

The value displayed (which is the value in the cookie) is the timestamp
of the previous request.

But that’s in the controller. Or do I miss something?

So it took a very long time to get here, given that you didn’t say in
the first place you were writing a Rails app (probably the question
would have been better directed to a Rails forum then); then in another
posting you said “Never mind
Rails. I don’t need the cookie there”; in another you mentioned
net/http.

I thought it would be better here as I thought it was more relevant for
Ruby than Rails. I’ve asked in Rails before but didn’t get a solution.
And I’m not a pure programmer (obviously), more a designer trying to
build web apps. I’m still learning. Otherwise I wouldn’t ask and I would
know exactly the difference between cgi, net/http, and so on.

One more time:

  1. I have a Rails app.

  2. I have/had certain data aes encrypted in certain columns in mysql
    with a unique key for each user. That key is saved in a cookie. If they
    use an iPhone or another browser they need to ad the key to each
    browser. It’s just another layer of security on top of Rails. So if
    someone get hold of that key it’s useless unless you login or break the
    security of mysql.

  3. l use “before_save” and “fast-aes” in the model. So everything happes
    in the model and in a script for encrypting located in /lib, just
    because I can’t get the cookie into the model with rails
    cookies[:my_cookie]. Or can I? Maybe I’m overlooking something. Can get
    the value of a cookie from the controller into the model in a simple
    uniform way?

  4. I used cgi to get the cookie value before. Now I can’t do that after
    rails 2.3.x. I wonder if I can do it in another way?

Just tested with rails 2.3.8, and it seems to be fine:

rails foobar
cd foobar
cat <app/controllers/foobar_controller.rb
class FooController < ApplicationController
def bar
render :text => cookies[“test”].inspect
cookies[“test”] = Time.now.to_s
end
end
EOF
script/server

Point browser at http://127.0.0.1:3000/foo/bar - and then refresh.

The value displayed (which is the value in the cookie) is the timestamp
of the previous request.

So it took a very long time to get here, given that you didn’t say in
the first place you were writing a Rails app (probably the question
would have been better directed to a Rails forum then); then in another
posting you said “Never mind
Rails. I don’t need the cookie there”; in another you mentioned
net/http.

Pål Bergström wrote:

The value displayed (which is the value in the cookie) is the timestamp
of the previous request.

But that’s in the controller. Or do I miss something?

Yes, it’s in the controller.

One more time:

  1. I have a Rails app.

  2. I have/had certain data aes encrypted in certain columns in mysql
    with a unique key for each user. That key is saved in a cookie. If they
    use an iPhone or another browser they need to ad the key to each
    browser. It’s just another layer of security on top of Rails. So if
    someone get hold of that key it’s useless unless you login or break the
    security of mysql.

  3. l use “before_save” and “fast-aes” in the model. So everything happes
    in the model and in a script for encrypting located in /lib, just
    because I can’t get the cookie into the model with rails
    cookies[:my_cookie]. Or can I? Maybe I’m overlooking something. Can get
    the value of a cookie from the controller into the model in a simple
    uniform way?

Ah right, so now you’re definitely asking a Rails question. I think your
question is: how can I access request/controller parameters from an
instance of the model?

The brief answer is: you can’t. An instance of a model exists
independently of any controller. A model can be instantiated outside of
a controller; and in principle, one model object could be shared between
multiple controller instances.

A simple solution is to pass the parameter explicitly. That is, in your
model you can have a method which accepts the encryption key as a
parameter, like ‘decrypt’ say, and invoke it from the controller:

code in controller


thing = Thing.find(id)
thing.decrypt(cookies[“key”])

Or you could set an instance variable in the model (models can have
regular Ruby attrs, which are not stored in the database), which in turn
you can use in your before_save method.

If you want to make it completely transparent, there is a messy solution
you could consider, which is to use Thread-local variables. In your
controller’s “before” filter, do

Thread[:key] = cookies[“key”]

Then this will be accessible in your model as Thread[:key]. You need to
be very careful to reset this variable before every controller action,
otherwise the key may leak from one user’s request to another user.

This is actually how Rails deals with timezones - in the controller, if
you set Time.zone = xxx in the controller, it affects the model through
a thread-local variable. See

http://api.rubyonrails.org/classes/Time.html#method-c-zone%3D

and click on “show source”.

I’d recommend you avoid doing this if you possibly can. I think in your
case, I’d use an instance variable.

class MyModel < ActiveRecord::Base
attr_accessor :key

def before_save
raise “Key not set!” unless key
… encrypt using key
end
end

class MyController < ApplicationController
def create
@thing = MyModel.new(params[:thing])
@thing.key = cookies[:key]
@thing.save!
end
end

Of course, you do need to update your code at each point where you load
or save models, but there is no risk of one user’s key hanging over to
another request.

This of course a 100% Rails question. If you didn’t get a good answer on
a Rails forum, maybe you needed to be bit clearer in the phrasing of
your question. There is good advice at
http://www.catb.org/~esr/faqs/smart-questions.html#intro

In future I’d recommend you be more specific about what you’re trying to
do; post samples of code; and mark the points where you’re having
problems. One ambiguous sentence just doesn’t cut it, and most people
are likely to skip over it.

HTH,

Brian.

Brian C. wrote:

In future I’d recommend you be more specific about what you’re trying to
do; post samples of code; and mark the points where you’re having
problems. One ambiguous sentence just doesn’t cut it, and most people
are likely to skip over it.

Thanks for your time and effort to answer. I appreciate it. I have given
detailed explanation for what I wanted to do several times (before
this). So I thought I would just ask: Can Ruby access a cookie in a
users browser? I could do it with cgi but not anymore.

I know I can pass it to the model with a params. But that means sending
it on many occasions instead of setting it once. Maybe you have given me
a solution to that with Thread-local variables. I will examine your
answer more closely.

I don’t have the before_save and after_find in the controller. It’s in
the model.