Kuro5hin.org: technology and culture, from the trenches
create account | help/FAQ | contact | links | search | IRC | site news
[ Everything | Diaries | Technology | Science | Culture | Politics | Media | News | Internet | Op-Ed | Fiction | Meta | MLP ]
We need your support: buy an ad | premium membership

HTTP Cookie were create by furry monsters at Netscape as part of Netscape extensions to CGI. The way cookie work is that webserver give "Set-Cookie:" header with information on cookie, and browser keep track of cookie. Then, when browser access page on same site, it send back list of all cookie for that site. It make me sad that W3 Consortium does not have good final Cookie spec. Me think it never really baked into HTTP standard and Netscape standard is only good definition me can find.

Setting Cookie

Set-Cookie HTTP header is very simple. It similar to any other HTTP header like Content-Type. Its format is:

Set-Cookie: key=value; [expires=DATE;] [path=PATH;]
where key is name of cookie, value is data stored in cookie, and optional "expires" field is when browser give cookie to Cookie Monster to eat. ARR ARUM NUMM NUMMM! Also optional "path" field say which part of site should see cookie. So cookie in path=/cookie/eat will not be seen by CGI in path of /cookie/dont-eat on webserver. Is good idea to set path always because some browser do not use good default.

It important that expires date given in RFC-822 format. This is format that look like "Sat, 14 Sep 2002 21:57:39 +0000" and is format given by UNIX command date -R. Also note in Netscape standard timezone must be UTC. Browser may not care.

Getting Cookie

In most webserver, cookie are given in environment variable HTTP_COOKIE. They are in format of

key=value; key=value; key=value; ...
and so on. There are many way to parse cookie value. It depending on language you use.

Simple Cookie Code

Here is simple code for handling cookie with simple CGI. CGI is written in C. Because C is for cookie! That good enough for me. Other language have CGI library available. This code for seeing how CGI library work, not for big use on web. Me write code just for article.

/* c-cookie.c
** Cookie start with C
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>

typedef struct {
        char *key;
        char *val;
} Cookie;

char *CopyKey(char *);
char *CopyVal(char *);

Cookie *ParseCookie(char *env, int *n)
{
        Cookie *c = NULL;
        int nc = 0;
        char *cookiestr = NULL;

        if (!env)
        {
                *n = 0;
                return NULL;
        }

        /* add ; to end of string for easier parsing */
        cookiestr = malloc(strlen(env) + 2);
        sprintf(cookiestr, "%s;", cookiestr);

        env = cookiestr;
        while (*env)
        {
                char *next = strstr(env, ";");
                if (next)
                {
                        /* Get this token */
                        c = realloc(c, sizeof(Cookie)*(nc + 1));
                        c[nc].key = CopyKey(env);
                        c[nc].val = CopyVal(env);
                        nc++;

                        /* find next token */
                        env = next + 1;
                        while (*env && isspace(*env))
                                env++;
                }
               
        }

        /* Clean up crumbs! */
        free(cookiestr);

        *n = nc;
        return c;
}

char *CopyKey(char *pair)
{
        char *p = strchr(pair, '=');
        char *ret = NULL;
        if (p)
        {
                int len = p - pair;
                ret = malloc(len + 1);
                memcpy(ret, pair, len);
                ret[len] = '\0';
        }

        return ret;
}

char *CopyVal(char *pair)
{
        char *ret = NULL;
        int len;
        pair = strchr(pair, '=');
        if (pair)
        {
                pair++;
                len = strchr(pair, ';') - pair;
                ret = malloc(len + 1);
                strncpy(ret, pair, len);
                ret[len] = '\0';
        }

        return ret;
}

static char *favorite_cookies[] = {
        "chocolate",
        "vanilla",
        "sprinkles",
        "HTTP",
        NULL
};

int main(void)
{
        char expirestr[200];
        Cookie *cookies;
        int num_cookies;
        int i;

        /* We format page in HTML */
        printf("Content-type: text/html\n");

        /* If we have parameter, set cookie */
        if (getenv("QUERY_STRING"))
        {
                /* we make expire in one hour */
                time_t expires = time(NULL) + 3600;

                /* format string can be "%z" in GNU libc */
                strftime(expirestr, 200, "%a,  %d  %b  %Y  %H:%M:%S  %z",
                        gmtime(&expires));

                /* Set cookie! */
                printf("Set-Cookie: FAVORITE=%s; Expires=%s\n",
                      getenv("QUERY_STRING"),
                      ctime(&expires));
        }
       
        printf("\n");
       
        printf("<html><head><title>CGI is for Cookie</title></head><body>\n");

        if (getenv("HTTP_COOKIE"))
        {
                printf("<P>Hello children and furry creature!  You have these "
                      "cookie.  GIVE ME COOKIE!\n");
                printf("<table border=2>");
                printf("<tr><th>Name</th><th>Value</th></tr> \n");
               
                cookies = ParseCookie(getenv("HTTP_COOKIE"), &num_cookies);
               
                for (i = 0; i < num_cookies; i++)
                        printf("<tr><td>%s</td><td>%s</td></tr>\n",
                              cookies[i].key,
                              cookies[i].val);
               
                printf("</table></p>\n");
        }
               
        printf("<P>What is you favorite kind of cookie?<ul>\n");
               
        for (i = 0; favorite_cookies[i]; i++)
                printf ("<li><a href=\"?%s\">%s</a></li>\n",
                        favorite_cookies[i],
                        favorite_cookies[i]);

        printf("</ul></p></body></html>");

        return 0;
}

Conclusion

I hope this very helpful for furry monster who want write CGI using cookie. Cookie make Cookie Monster very hungry! GIVE ME COOKIE!

Sponsors

Voxel dot net
o Managed Hosting
o VoxCAST Content Delivery
o Raw Infrastructure

Login

Poll
Is article helpful?
o Yes 9%
o No 15%
o GIVE ME COOKIE 75%

Votes: 152
Results | Other Polls

Related Links
o Netscape extensions to CGI
o W3 Consortium
o Also by Cookie Monster


Display: Sort:
Understanding HTTP Cookie | 90 comments (51 topical, 39 editorial, 0 hidden)
Gratuitous use of typedefs (1.57 / 7) (#4)
by Bob Dog on Sun Sep 15, 2002 at 12:36:56 AM EST

plz fix k thx.

Um (5.00 / 1) (#10)
by carbon on Sun Sep 15, 2002 at 01:43:32 AM EST

There's exactly one explicit typedef, and it's used in a manner which doesn't make any difference anyways.

Oh, and your comment should've been editorial.


Wasn't Dr. Claus the bad guy on Inspector Gadget? - dirvish
[ Parent ]
Mindlessly using typedefs for every damn struct (3.00 / 2) (#30)
by Bob Dog on Sun Sep 15, 2002 at 09:54:44 AM EST

is gratuitous.

[ Parent ]
I'd disagree (5.00 / 1) (#51)
by Delirium on Sun Sep 15, 2002 at 08:59:27 PM EST

I like C++'s method of automatically doing it for you (i.e. when you do struct Blah {};, you can declare variables as blah x;, even without doing a typedef).

[ Parent ]
Ye Gods! (none / 0) (#62)
by Bob Dog on Mon Sep 16, 2002 at 12:12:48 PM EST

I'm sure glad C doesn't do that.  And that I don't have to use C++.

I dislike typedefs for several reasons. They pollute the variable namespace, they make the syntax weird and as they don't create a new type they're misnamed.

[ Parent ]

well (none / 0) (#64)
by Delirium on Mon Sep 16, 2002 at 12:46:11 PM EST

That's why C++ has multiple namespaces. =]

And a struct (or class) is a new (aggregate) type, so I don't see that as problematic.

[ Parent ]

Well, I'm glad I don't have to read your code then (5.00 / 2) (#72)
by joto on Mon Sep 16, 2002 at 04:16:37 PM EST

Typedefs are useful. They have static scope, so you can put them anywhere you like without polluting the global namespace.

Which would you rather read?

void (*signal(int, void (*)(int)))(int);

or?

typedef void (*)(int) SigFunc;
SigFunc signal(int, SigFunc);

At least for me, the first declaration takes me at least 10 seconds to decipher, and I consider myself pretty good at C.

And putting typedefs around structs are just common sense. Nobody in their right mind wants to type struct Foo foo instead of simply Foo foo everywhere.

If you can't manage the global namespace with coding conventions like unique prefixes, having a separate namespace for structs doesn't really help, since it is still a global namespace. So preferring to not use typedefs for that reason is simply not a good reason.

Of course, in C++, with STL and god knows what other nasties, typedefs are even more useful to avoid completely unreadable declarations. And in C++ you can also use namespaces to avoid unique prefixes everywhere.

[ Parent ]

Posting the example in C (1.80 / 5) (#13)
by medham on Sun Sep 15, 2002 at 02:06:06 AM EST

Is rather recherche (don't type accents).

The real 'medham' has userid 6831.

is medham accentuated? (5.00 / 1) (#24)
by martingale on Sun Sep 15, 2002 at 05:49:46 AM EST

Your comment has rocked the foundations of my certitudes - now I must know: Does medham have an accent? If so, is it acute, grave or, dare I even suggest it, circumflex? Do tell, please, the readers of k5 have a right to know if medham is really a mesdham...

[ Parent ]
-1 (4.00 / 7) (#27)
by kaemaril on Sun Sep 15, 2002 at 08:12:34 AM EST

Too Sesame-Street-centric.

Ha, sorry, couldn't resist. Seriously, though, C? How ... eighties :)


Why, yes, I am being sarcastic. Why do you ask?


So, you want a cookie? (4.00 / 1) (#31)
by pyramid termite on Sun Sep 15, 2002 at 10:11:39 AM EST

Bet you can't eat all of THIS ONE.

I'm just pandering to the lowest common denominator here.

- thelizman
how come (none / 0) (#39)
by VoxLobster on Sun Sep 15, 2002 at 01:37:56 PM EST

there was never stuff like this on Sesame Street? I mean, yeah, the number 7 is great, but I could have gotten a great head start on my comp sci education.

VoxLobster
I was raised by a cup of coffee! -- Homsar

Bad Cookie Monster! (5.00 / 1) (#56)
by wiredog on Mon Sep 16, 2002 at 09:29:19 AM EST

No cookie for you!

Earth first! We can mine the rest later.
[ Parent ]
Also (none / 0) (#65)
by Bob Dog on Mon Sep 16, 2002 at 01:06:02 PM EST

You didn't check the return values of {m,re}alloc Mr. Monster.  That be bad.

[ Parent ]
Actually there is an earlier RFC... (none / 0) (#69)
by MstlyHrmls on Mon Sep 16, 2002 at 03:05:12 PM EST

RFC 2109: HTTP State Management Mechanism

It's basically a codification of the Netscape spec, with a few minor improvements. Took me ages to dig it up as well. Why they couldn't put something obvious like "Cookie" in the title is beyond me...

Now that Mr. Monster has given us an introduction to HTTP Cookies, will Big Bird be giving us a lecture on RFC 1149: A Standard for the Transmission of IP Datagrams on Avian Carriers? Perhaps the latest addendum, RFC 2549: IP over Avian Carriers with Quality of Service would be more relevant

Mike


--
Some humans would do anything to see if it was possible to do it. If you put a large switch in some cave somewhere, with a sign on it saying "End of th
[ Parent ]
Excellent (4.89 / 19) (#44)
by ennui on Sun Sep 15, 2002 at 03:34:44 PM EST

Now we just need Oscar the Grouch to explain the concept of a heap, or maybe garbage collection.

"You can get a lot more done with a kind word and a gun, than with a kind word alone." -- Al Capone
For those who think it's ugly in C: (5.00 / 2) (#45)
by fluffy grue on Sun Sep 15, 2002 at 04:20:48 PM EST

You could always do it in Bourne shell.
--
"Is a sentence fragment" is a sentence fragment.
"Is not a quine" is not a quine.

[ Hug Your Trikuare ]

But C is for Cookie! [nt] (5.00 / 2) (#71)
by Karmakaze on Mon Sep 16, 2002 at 03:58:51 PM EST


--
Karmakaze
[ Parent ]
Perl is for cookie; that's good enough for me. (none / 0) (#78)
by pin0cchio on Mon Sep 16, 2002 at 11:57:49 PM EST

Oh, cookie cookie starts with PHP.
lj65
[ Parent ]
Nah (none / 0) (#87)
by exceed on Fri Sep 27, 2002 at 04:02:45 PM EST

That's even uglier.

void women (float money, time_t time);
[ Parent ]
Kind of my point (nt) (none / 0) (#89)
by fluffy grue on Fri Sep 27, 2002 at 04:40:32 PM EST



[ Parent ]
Nah (none / 0) (#88)
by exceed on Fri Sep 27, 2002 at 04:03:01 PM EST

That's even more ugly.

void women (float money, time_t time);
[ Parent ]
J00 n33d m1lk (3.00 / 1) (#53)
by Joh3n on Mon Sep 16, 2002 at 04:01:25 AM EST

c00k13 b3tt3r w1th m1lk!
---------------------------------
You can learn a lot about someone by popping in their un-rewound pr0n tape and seeing where exactly they came.
-terpy
Note for mozilla users (2.00 / 1) (#55)
by salsaman on Mon Sep 16, 2002 at 06:50:40 AM EST

If you use mozilla, I think HTTP_COOKIE is not defined. Instead you can access the cookie manager from the tools menu. You can also block cookies from certain sites if you don't like their taste. For example, I find the flavour of cookies from doubleclick.com to be particularly foul, so I never take cookies from them.

For linux, the actual cookies themselves are stored in: ~/.mozilla/<profile_name>/<salt>/cookies.txt. Salt is a randomly generated directory name which helps stop cookie monster from finding your cookie jar and eating all the contents. Sorry cookie monster !

wanna see my puppet? (none / 0) (#57)
by billt on Mon Sep 16, 2002 at 09:50:55 AM EST

my %puppet = map { split '=' } (split(/;\s*/,$ENV{'HTTP_COOKIE'}));

What a worthless article! (1.33 / 15) (#58)
by MessiahWWKD on Mon Sep 16, 2002 at 10:01:12 AM EST

This is seriously one of the most trivial pieces of crap that I've seen on kuro5hin yet! This article not only has any relevance to anything, but it's simply information anybody can find easily on Google if they desire. Why does this make it past the queue and not my informative article about the new Dale Road Branch of Valley First Credit Union?
Sent from my iPad

Aawwwwwwwwwww... (3.80 / 5) (#60)
by silsor on Mon Sep 16, 2002 at 11:15:02 AM EST

Somebody call the waaaaaaaambulance.


✠  Patron saint of unmoderated (none / 0) top-level comments.
[ Parent ]
What a pointless comment! (3.00 / 2) (#75)
by Ranger Rick on Mon Sep 16, 2002 at 07:07:25 PM EST

You didn't make any points I haven't seen anywhere else.

Why did this comment make it to the article and not my informative one about the pointlessness of bitching about an article instead of just ignoring it?


:wq!


[ Parent ]
Pot calling kettle black (none / 0) (#80)
by MessiahWWKD on Tue Sep 17, 2002 at 01:57:06 AM EST

My aren't you redundant!
Sent from my iPad
[ Parent ]
Damn you. (none / 0) (#83)
by UncannyVortex on Tue Sep 17, 2002 at 05:42:50 PM EST

Why did Rick post a link to his own comment and not my informative one about the problems associated with expressing one's opinion rather than fact -- as Rick has done here -- a practice also known as crapflooding?

[ Parent ]
I thought it was engrish at first (none / 0) (#59)
by gr00vey on Mon Sep 16, 2002 at 10:38:46 AM EST

Then I slowly realised it was cookie monster.. I guess I am just not too bright! www.engrish.com

Bad programming (none / 0) (#61)
by darthaya on Mon Sep 16, 2002 at 11:49:30 AM EST

Potential memory leak for not freeing the memory after CopyKey and CopyVal.

Muppet code (4.66 / 3) (#70)
by Kintanon on Mon Sep 16, 2002 at 03:34:37 PM EST

The guy is a fuzzy blue puppet with someones hand up his ass! Give him a break!

Kintanon

[ Parent ]

Credits (5.00 / 3) (#63)
by Sir Rastus Bear on Mon Sep 16, 2002 at 12:14:18 PM EST

This article has been brought to you by the number "F".
"It's the dog's fault, but she irrationally yells at me that I shouldn't use the wood chipper when I'm drunk."
And the letter (5.00 / 2) (#66)
by greyrat on Mon Sep 16, 2002 at 01:30:12 PM EST

1001010
~ ~ ~
Did I actually read the article? No. No I didn't.
"Watch out for me nobbystyles, Gromit!"

[ Parent ]
Worth pointing out (4.50 / 2) (#73)
by Shimmer on Mon Sep 16, 2002 at 04:40:32 PM EST

First, let me just say that I wish more technical articles were written in Cookie Monster-ese.  Bravo.

You don't mention the distinction between a "session" cookie (that goes away when the browser closes) and a "persistent" cookie (that is stored on the client's computer even after the browser is closed.

IIRC, ommitting the EXPIRES portion of the Set-Cookie header causes the cookie to be a session cookie.

-- Brian

Wizard needs food badly.

Cookies and Cookies and Cookies (none / 0) (#76)
by jefu on Mon Sep 16, 2002 at 08:49:21 PM EST

So, I've been wondering.  I can see one cookie or two (session and long term) but why, oh why (or is that Y O Y in sesamespeakeese) do sites want to set four or fie or even (one extreme case) seven (7 (!)) cookies ?

(I'm not typical, I suspect, but I allow two cookies from the site I'm visiting and that is all.   Sites that want more start getting cranky email from me.)

Some reasons (none / 0) (#79)
by fluffy grue on Tue Sep 17, 2002 at 01:38:35 AM EST

Typically it's because of the programmer being too lazy to aggregate all configuration information into a single cookie. (For example, in my webcomic I set two cookies, one for the current page (automatic bookmark, so people can read it at their own pace) and one for the display mode, so I don't have to parse out the correct cookie and parse the cookie itself, and I'm not about to store server-side "browse profiles" for everyone who reads it.)

Also, a lot of sites have a lot of disparate systems working under the hood, rather than it being one single unified backend, and it's often easier to just have separate cookies than to try to have a unified configuration space for all users. (For example, my forum uses phpBB, which uses its own separate set of cookies, and I'm not about to try to unify phpBB's configuration with my webcomic's!)


--
"Is a sentence fragment" is a sentence fragment.
"Is not a quine" is not a quine.

[ Hug Your Trikuare ]
[ Parent ]

laziness. (none / 0) (#85)
by werner on Wed Sep 18, 2002 at 10:43:32 AM EST

It's easier to call setcookie("myCookie", $value, time(), "/" ); whenever you need to, rather than write special code to collect, set, reload, parse and make available all the variables you need.

PHPNuke has a nice cookie function. It joins them all together with '|'s and base64 encodes the result for the cookie value. Well that's what it did last time I looked.

[ Parent ]

well it's probably (1.00 / 2) (#77)
by iamabot on Mon Sep 16, 2002 at 09:35:04 PM EST

because jesus hates you :(
./bot
Good monster! (3.00 / 2) (#81)
by wanders on Tue Sep 17, 2002 at 04:30:22 AM EST

Best kuro5hin article ever. Really. Even though it contains code in that nasty C language. Have a cookie!
~
~
:x
Imposter! (none / 0) (#84)
by Weird Willy on Wed Sep 18, 2002 at 12:45:15 AM EST

this article is obviousy written by an imposter, the real Cookie Monster never used adverbs...

I ain't complaining (none / 0) (#90)
by kichigai on Tue Jan 14, 2003 at 09:39:25 AM EST

"C" is for cookie, that's good enough for me.
"I said I was smart, I never said I was mature!"
-Me

[ Parent ]
What I recently discovered (none / 0) (#86)
by fluffy grue on Wed Sep 18, 2002 at 07:30:45 PM EST

This article inspired me to finally update the cookie code in my webcomic browser to use the newer Set-Cookie2 protocol instead of the old Set-Cookie. But no browser actually supports Set-Cookie2 (at least, Galeon and Mozilla don't), and so you have to use Set-Cookie as a fallback anyway. Which is kind of pointless because all that Set-Cookie2 does is add some extensibility (which Set-Cookie could have had anyway; the browser should be able to just ignore things it doesn't know) and replaces the crappy RFC-822-using "Expires" attribute with the non-crappy "MaxAge" attribute. So any new CGI applications still have to support the old cookie protocol anyway, so why bother updating?

Just for purity's sake, my code now sets both kinds of cookie, redundant as it may be...
--
"Is a sentence fragment" is a sentence fragment.
"Is not a quine" is not a quine.

[ Hug Your Trikuare ]

Understanding HTTP Cookie | 90 comments (51 topical, 39 editorial, 0 hidden)
Display: Sort:

kuro5hin.org

[XML]
All trademarks and copyrights on this page are owned by their respective companies. The Rest 2000 - Present Kuro5hin.org Inc.
See our legalese page for copyright policies. Please also read our Privacy Policy.
Kuro5hin.org is powered by Free Software, including Apache, Perl, and Linux, The Scoop Engine that runs this site is freely available, under the terms of the GPL.
Need some help? Email help@kuro5hin.org.
My heart's the long stairs.

Powered by Scoop create account | help/FAQ | mission | links | search | IRC | YOU choose the stories!