Using Cookies With Domino
As part of Phase 2 of Version 6 of this site I have a few minor enhancements lined up. One of them is to start using Cookies to remember your name/email details. Should make life less hassle for the regular posters among you.
Another change I want to make is getting rid of all JavaScript in the database's design. This means that I have to use the Domino 6 @SetHTTPHeader() function to create the Cookies. Doing so involves something like this:
@SetHTTPHeader("Set-Cookie"; "codestore_name=Jake;");
Has anybody used this method to good effect? Are there things I should know about? I'm having lots of problems with it. The combination of the SetHTTPHeader and GetHTTPHeader functions are a really useful addition, but they're so poorly documented it's ridiculous.
How about ideas on the easiest way to parse the Cookie name/value pairs? The server receives all name/value pairs as one string in the HTTP_Cookie field. The format is:
codestore_name=Jake; codestore_email=me@m.com; codestore_website=http://www.codestore.net;
From what I can tell browsers don't always send Cookies in the order you set them, so we can't guarantee name being at position 1 or email at 2 etc. So, how do we extract the name from the string easily? Maybe like this:
pairs:=@Explode(HTTP_Cookie; "; "); names:=@Left(pairs; "="); values:=@Right(pairs; "=");
values[ @Member(names; "codestore_name") ];
Anyway, I'm jumping the gun. I've a bug to resolve first. It's almost as if documents created with in-line forms get their computed fields processed twice. Once for the submitted data and once with no data. I'm pretty sure it's a bug, but I want to make sure I'm not just being stupid before I go shooting me big mouth off. More tomorrow...
Jake,
You might want to have a word with Jerry. He did some good work with cookies and @SetHTTPHeader on an application we both worked on.
Mark
Personnally, i use LS agents to set cookies, which works pretty well :
Print "Set-Cookie: val=var; expires="+RFC822DateFormat(expiration)+"; path=/web-application"
Jake,
Your method od using @Member works if you have ONE server in the domain that sets these cookies. But you can also have other servers, that sets cookies that should be visible to the entire DOMAIN. For instance, your site www.codestore.net might set the codestore_name for the www.codestore.net domain name, and another server, my.codestore.net, perhaps setting the cookie codestore_name on the entire codestore.net domain. This will end up in TWO values when reading from the first server.
I have not tested the above with @Set/GetHTTPHeader, only with the JavaScript methods for setting/getting cookies.
Jake
I use to get cookie values like this:
codestore_name := @Middle(HTTP_COOKIE; "codestore_name="; ";");
It really works in every application I've done.
To set cookies I don't use @SetHTTPHeader, instead I write the actual html header:
<meta http-equiv="Set-Cookie" content="..." />
To specify the expiration date I've always used any of these formulaes:
{Link}
{Link}
And remember that in the page you set the cookie, the HTTP_COOKIE field doesn't have the cookie value specified yet.
Regards
Thanks guys!
Mark. I'll have a word with him. Cheers.
YoGi. Looks like I might have to revert to LS if I can't get to the bottom of this. Doh!
Johann. Thanks. I'd not thought of this.
Marcos. Brilliant. This should make it all a little simpler.
I can't use the <meta> tag to set the cookie though, as this relied on sending HTML content back to teh browser. In this case we simply POST to the server which use the response *headers* to return a redirect instruction and bits like set-cookie in this case. No actual HTML is returned, so it has to be done in the headers. Looks like a WQS might be my best bet.
If you need another resource, there is an article in THE VIEW, September/October 2004, "How to Develop a Secure App..." by Page Nix, about a website application involving cookies.
We utilized the code quite nicely in one of our apps, and the detail and explanation of cookie setting and handling were very good. Worth a read or a download of the sample database even if you go another way.
This seems like a good place to watch the network stream with ethereal, and see what's really happening.
I was using my in-built IE sniffer Brian. This is how I knew that Domino was setting the cookie header multiple times and in the wrong order. Very weird behaviour. I'll mention it tomorrow, but won't dwell on it, as the situation is soooo obscure it's hardly worth it.
Hi Jake -
Allow me to ask the stupid question. What is the motivation behind completely eliminating javascript?
-- Mike
Mike. Pig-headed-ness mainly. I go through phases. At the moment it's a "keep it simple so it's pure and accessible" phase. I just like the idea that everything relies on the server (i.e. my code) and not on the user having JavaScript enabled. In short - there's real no reason. I know most of you guys aren't short-sighted, using out-dated browsers or likely to disable JS. It's all good practice though.
If you use code on the server in order to create Cookies you test it once. If you use JavaScript you have to test and re-develop it as many times as browser the code fails on.
Another issue you may run into with @SetHTTPHeader: If the length of the value is longer than 80-something characters Domino INSERTS A LINEBREAK CHARACTER. It's quite common to have a cookie this long when using persistent vs session cookies.
For example this call:
@SetHttpHeader( "Set-Cookie"; "test=cn%3DMarcin%20Szczepanski%2Fo%3Dtest%2Fou%3DtestInc;expires=Mon, 7-Mar-2005 00:00:00 GMT;path=/;");
This call will end up with a line break after the "2005" which will mean the cookie will not get set correctly. On the other hand, this call:
@SetHttpHeader( "Set-Cookie"; "test=foo;expires=Mon, 7-Mar-2005 00:00:00 GMT;path=/;");
Is fine as it's not long enough to be affected. I managed to replicate this issue up to 6.5.3.
Thanks for the info Marcin. Why can't they do anything right? ;o)