Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

simplify getting and setting cookies - add support for extended cooki…

…e attributes

No longer have to deal with raw cookie and set-cookie strings.  Replaced
Web:get_cookie() which returned the raw cookie string with
Web:get_cookies() which returns a table of key/value pairs representing
the cookies sent in the HTTP request header.    Web:set_cookie([string])
was replaced with Web:set_cookie([table]), where [table] is at a
minimum, of the following form:  {key="[some key]", value="[some
value]"}.  cookie table may optionally contain standard cookie
attributes:  path, domain, expires, http_only and secure.
  • Loading branch information...
commit b41b5b06e36a3d20052b1263772ddccdfe516c15 1 parent c62064e
@mtowers mtowers authored
View
8 tir/mongrel2/connection.lua
@@ -49,7 +49,13 @@ local function http_response(body, code, status, headers)
local raw = {}
for k, v in pairs(headers) do
- insert(raw, format('%s: %s', k, v))
+ if( "table" == type(v) ) then
+ for l, w in pairs(v) do
+ insert(raw, format('%s: %s', k, w))
+ end
+ else
+ insert(raw, format('%s: %s', k, v))
+ end
end
return format(HTTP_FORMAT, code, status, concat(raw, '\r\n'), body)
View
19 tir/session.lua
@@ -36,18 +36,25 @@ end
function make_expires()
local temp = os.date("*t", os.time())
temp.year = temp.year + BIG_EXPIRE_TIME
- return os.date("%a, %d-%b-%Y %X GMT", os.time(temp))
+ return os.time(temp)
end
function make_session_cookie(ident)
- return 'session="' .. (ident or make_session_id()) ..
- '"; version=1; path=/; expires=' .. make_expires()
+ local cookie = {}
+ cookie.key = 'session'
+ cookie.value = ident or make_session_id()
+ cookie.version = 1
+ cookie.path = '/'
+ cookie.expires = make_expires()
+ return cookie
end
function parse_session_id(cookie)
if not cookie then return nil end
- return cookie:match('session="(APP-[a-z0-9\-]+)";?')
+ local cookie = parse_http_cookie(cookie)
+
+ return cookie.session
end
@@ -66,13 +73,11 @@ end
function http_cookie_ident(req)
local ident = parse_session_id(req.headers['cookie'])
-
if not ident then
ident = make_session_id()
local cookie = make_session_cookie(ident)
- req.headers['set-cookie'] = cookie
- req.headers['cookie'] = cookie
+ set_http_cookie(req, cookie)
req.session_id = ident
end
View
60 tir/util.lua
@@ -146,15 +146,65 @@ end
-- Parses a cookie string into a table
-- Note: If the cookie string contains multiple cookies with the same key,
--- only one of them will be returned in the resulting table
-function parse_cookie(cookie)
- local cookie_str = string.gsub(cookie, "%s*;%s*", ";") -- remove extra spaces
-
+-- (which can happen if similar cookies exist for different paths, domains, etc.)
+-- the requested key will return a table containing each value
+function parse_http_cookie(cookie)
local cookies = {}
+
+ if( not cookie ) then return {} end
+
+ local cookie_str = string.gsub(cookie, "%s*;%s*", ";") -- remove extra spaces
for k, v in string.gmatch(cookie_str, "([^;]+)=([^;]+)") do
- cookies[k] = v
+ -- check if the key already exists
+ -- if it does, then set the value for the key to a table containing both values
+ if( cookies[k] ) then
+ if( 'table' == type(cookies[k]) ) then
+ table.insert(cookies[k], v)
+ else
+ local values = {}
+ table.insert(values, cookies[k]) -- move the old value into a table
+ table.insert(values, v)
+ cookies[k] = values
+ end
+ -- otherwise, just set the key equal to the value
+ else
+ cookies[k] = v
+ end
end
return cookies
end
+
+function set_http_cookie(req, cookie)
+ --key and value are required, everything else is optional
+ assert(cookie and cookie.key and cookie.value, "cookie.key and cookie.value are required")
+ --strip out cookie key/value delimiters
+ local key = string.gsub(cookie.key, "([=;]+)", "")
+ local value = string.gsub(cookie.value or '', "([=;]+)", "")
+
+ local cookie_str = key .. '=' .. value
+
+ -- if no path is specified, use the root
+ cookie_str = cookie_str .. '; ' .. 'path=' .. (cookie.path or '/')
+
+ if( cookie.domain ) then
+ cookie_str = cookie_str .. ';' .. 'domain=' .. cookie.domain
+ end
+
+ if( cookie.expires ) then
+ assert("number" == type(cookie.expires), "expires value must be a number - UNIX epoch seconds")
+ cookie_str = cookie_str .. ';' .. 'expires=' .. os.date("%a, %d-%b-%Y %X GMT", cookie.expires)
+ end
+
+ if( cookie.http_only ) then cookie_str = cookie_str .. '; httponly' end
+
+ if( cookie.secure ) then cookie_str = cookie_str .. '; secure' end
+
+ -- make sure we actually have a headers table before we go trying to set stuff
+ req.headers = req.headers or {}
+ -- make sure we have a set-cookie table to work with
+ req.headers['set-cookie'] = req.headers['set-cookie'] or {}
+ --insert the new cookie as a new set-cookie response header
+ table.insert(req.headers['set-cookie'], cookie_str)
+end
View
12 tir/web.lua
@@ -47,11 +47,17 @@ function web(conn, main, req, stateless)
end
function Web:set_cookie(cookie)
- self.req.headers['set-cookie'] = cookie
+ set_http_cookie(self.req, cookie)
+ end
+
+ function Web:zap_cookie(cookie)
+ cookie.expires = 0
+ cookie.value = 'deleted'
+ set_http_cookie(self.req, cookie)
end
- function Web:get_cookie()
- return self.req.headers['cookie']
+ function Web:get_cookies()
+ return parse_http_cookie(self.req.headers['cookie'])
end
function Web:session()
Please sign in to comment.
Something went wrong with that request. Please try again.