Manipulating cookies without server side scripting and without client-side scripting

I wanted to title this article "Baking and eating cookie with no hands" but it could have been a little confusing ;-)

Sometimes there are situations where you've got a set of static pages on the web.
You don't want (or can't) use any form of server side scripting and where using javascript to do the job is out of question (because the page is hit by millions of users and you have to support people who have deactivated javascript)

I've found Apache mod_rewrite of great help for that.

Let's say that you are publishing public domain books on the web.

you've got a url like that


You want to supply the user a feature that will allow them to return quickly to the last text they have visited (a bookmark, literally, that is)

So you create a url like


and you it to redirect the user to


How do you do it?
below is a mod_rewrite code that you can stick in your Apache config or a .htaccess:

RewriteCond %{HTTP_COOKIE}  ^.*book=(.*?)@part=(.*?)@chapter=(.*?)$
RewriteRule ^.*book/last_position.*$ /book/%1/%2/%3/ [L]

and to set the cookie when a user visits a url like


you use the following mod_rewrite code:

RewriteRule ^.*book/(.*?)/(.*?)/(.*?)/.*$ - [L,CO=book:[email protected][email protected]=$3:my.domain]

the "@" in both snippet of code has no special meaning, I use them as a separator. I suppose you could anything that's not a Regular Expression operator. You cannot use ";" as this is a Netscape cookie field separator.

It's also worth noting that the cookie flag is available only in versions of Apache greater than 2.0.40.

All good? The problem here is that every-time a user hits a url to read a book, a mod_rewrite code is executed and a cookie set which could be a performance drag.

it's a better to modify the current url to save the current position:


Then the following mod_rewrite code (instead on the one above that set cookie every-time) will do the trick:

RewriteRule ^.*book/(.*?)/(.*?)/(.*?)/save_position.*$ - [L,CO=book:[email protected][email protected]=$3:my.domain]

That way a cookie is set and mod_rewrite is triggered only when the user explicitly call it (through a link on the page).

But if it's a link on the page, you want the user to stay on the page, so you will use the following code instead of the last one:

RewriteRule ^.*book/(.*?)/(.*?)/(.*?)/save_position.*$ /book/$1/$2/$3/ [L,CO=book:[email protected][email protected]=$3:my.domain]

In all of the code above, the url is being rewritten, which mean the user doesn't see anything changed in the url. If you want the redirection being explicitly visible to the users, you can add the R flag. It becomes:

RewriteCond %{HTTP_COOKIE}  ^.*book=(.*?)@part=(.*?)@chapter=(.*?)$
RewriteRule ^.*book/last_position.*$ /book/%1/%2/%3/ [R,L]

RewriteRule ^.*book/(.*?)/(.*?)/(.*?)/save_position.*$ /book/$1/$2/$3/ [R,L,CO=book:[email protected][email protected]=$3:my.domain]

There's one thing we need to do now: deal with users who have deactivated the cookies. When they click on the saveposition link they will be brought back to the calling page whether or not they have cookie activated. The issue is the /lastposition url. If by any chance non-cookie users find that url they need to be redirected somewhere. Somewhere could be an entry point to navigate all the book like /book/. We do the same if the users accepts cookies but haven't got one yet.

this could be done with the following code:

RewriteCond %{HTTP_COOKIE}  ^.*book=(.*?)@part=(.*?)@chapter=(.*?)$
RewriteRule ^.*book/last_position.*$ /book/%1/%2/%3/ [R,L]
RewriteRule ^.*book/last_position.*$ /book/ [R,L]

A final refinement is the time of validity for the cookie. If you don't supply this parameter when setting up the cookie, the cookie lifetime won't last beyond the current browsing session. The COokie flag accept duration in minutes. So to set the lifetime of a cookie to 1 year, you do that:

RewriteRule ^.*book/(.*?)/(.*?)/(.*?)/save_position.*$ /book/$1/$2/$3/ [R,L,CO=book:[email protected][email protected]=$3:my.domain:525600]

Finally when assembled together, the code looks like that:

RewriteCond %{HTTP_COOKIE}  ^.*book=(.*?)@part=(.*?)@chapter=(.*?)$
RewriteRule ^.*book/last_position.*$ /book/%1/%2/%3/ [R,L]
RewriteRule ^.*book/last_position.*$ /book/ [R,L]

RewriteRule ^.*book/(.*?)/(.*?)/(.*?)/save_position.*$ /book/$1/$2/$3/ [R,L,CO=book:[email protected][email protected]=$3:my.domain:525600]

Related links:

Enjoy your cookies.

Technorati Tags:
internet, apache, mod_rewrite, cookie