priosshrsth
priosshrsth

Reputation: 1158

How do I manually set cookie in rails app?

I have a situation where I need to send session id in custom header because safari does not allow sending cookie from iframe.

But now, I'm having trouble setting the cookie from rack middleware.

status, headers, body = @app.call(env)
session_id = headers['X-SESSION-ID'] || headers['HTTP_X_SESSION_ID'] || headers['x-session-id'] || ''

if !headers['Cookie'].present? && session_id.present?
  headers['Cookie'] = {
    '_session_id': {
      value: session_id,
      path: '/',
      httpOnly: true
    }
  }
end

Or is there way to manually set session id without having to fetch it from cookie?

Update 1:

Modifying rack request files does work. But, I'm not sure how to proceed with this one. If nothing works then, I might manually update this file in all servers.

def cookies
  hash   = @env["rack.request.cookie_hash"] ||= {}
  string = @env["HTTP_COOKIE"] || "_session_id=#{@env["HTTP_X_SESSION_ID"]}"

  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 = 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

Looks like modifying the cookie method as above do not work.

Upvotes: 3

Views: 1717

Answers (1)

priosshrsth
priosshrsth

Reputation: 1158

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.

Upvotes: 2

Related Questions