- From: <Jim_Ravan@avid.com>
- Date: Tue, 16 Mar 1999 11:19:27 -0500
- To: www-lib@w3.org
Gert, >With libwww, how can I send my own headers along with a request? Or can only >standard headers be sent? I would like to send a cookie with my request, as >if it was coming from a browser. I know cookies are not supported by libwww >(yet). I *just* finished code to send and receive cookies. Look at the bottom of the HTTPGenMake routine in HTTPGen.c. There is a comment that states "Put out extra information, if any". There you'll find two loops, one to walk the HTRequest_generator list in the request, and one to walk the global HTHeader_generator list. These lists are expected to contain individual elements that contain the addresses of HTPostCallback functions. So a function needs to be constructed to write the cookies to the stream. A function that I wrote to put out cookies looks like this: // LIBWWW stream struct struct _HTStream { const HTStreamClass* isa; HTStream* target; }; static int SendCookies(HTRequest* request, HTStream* stream) /* * ARGUMENTS * request (IN) - current LIBWWW request object. * stream (IN) - current LIBWWW stream object. * * RETURN VALUE * HT_OK continue processing other request generators. * * DESCRIPTION * This LIBWWW Request Generator adds all generated cookie headers * to the current request. */ { char* cookie; // cookie header. HTList* local; // copy of cookieList to use for walking. local = cookieList; // Send all the cookies. while (cookie = (char*)HTList_nextObject(local)) (*stream->target->isa->put_block)(stream->target, cookie, strlen(cookie)); HTList_delete(cookieList); // Release the list. cookieList = NULL; return HT_OK; // Indicate that request generator processing should continue. } But, all in all, it's pretty uninteresting, huh? The generator just walks a list and writes the list elements to a stream. But where's the list "cookieList", and why is it necessary? Well, *that's* a little more interesting. Obviously, the cookieList contains the fully formatted cookie strings to be sent. Some other code puts the cookie strings on the list. What code? ... Before filters. I have a set of before filters that generate the actual cookie text. I attach whichever cookie header before filters I need to the request to generate the proper cookies. In my application, I have to send various cookies at various times depending on what is being done at the moment. The code to attach the cookie before filters to the request is: request = HTRequest_new(); // Send session ID cookie. HTRequest_addBefore(request, SetSessionContext, NULL, sess->ssID, HT_FILTER_LAST, FALSE); (sess->ssID contains a character string, for example, "3748596741") Note that the before filters have a context parameter, in this example, sess->ssID. That's the necessary magic. I use the before filter context pointer to pass information about the cookie value to the cookie filter. Note that the generator callback does *not* have a context pointer. That is why there has to be a cookieList. cookieList is a static list where the before cookie filters attach their cookie strings. I had to do it that way because I could not pass a context pointer directly to the generator and have the generator format the cookie strings directly. This means this solution won't thread very well, but that was not currently an issue for my application. And who adds the SendCookies generator to the request? I chose to do that in the cookie filters. You could just as easily do that in the request setup code. And you could decide to add all this stuff to the global lists. I chose to add all this at the request level. Here's a cookie filter: #define kCRLF "\x0D\x0A" static int SetSessionContext(HTRequest* request, void* param, int mode) /* * ARGUMENTS * request (IN) - current LIBWWW request object. * param (IN) - context that contains a session ID. * mode (IN) - unused. * * RETURN VALUE * HT_OK continue processing LIBWWW BEFORE filters. * * DESCRIPTION * This LIBWWW Before Filter adds a cookie header to the current request * that identifies the current session. */ { HTList* list; // Request Generators list. char* sessionID = (char*)param; // SessionID. char* linebuf; // Build cookie header here. int override; // Read, but not used. if (sessionID) // If there is a sessionID... { // Format a sessionID cookie header and put it on the cookieList. linebuf = (char*)malloc(257); sprintf(linebuf, "Cookie: SessionID=%s;%s", sessionID, kCRLF); if (!cookieList) cookieList = HTList_new(); HTList_addObject(cookieList, linebuf); // If necessary, create the request generator list. list = HTRequest_generator(request, &override); if (!list) { list = HTList_new(); HTList_addObject(list, SendCookies); HTRequest_setGenerator(request, list, FALSE); } } return HT_OK; // Indicate that Before Filter processing should continue. } In summary, here's how it all works. Write an HTPostCallback that writes cookies from a static list to the stream. Write one or more before filters that format cookie strings and place them on that static list. Each cookie filter also adds the HTPostCallback to the request if it's not already there. When setting up a request, add the before filters that generate the cookies you need. Of course, if you only have one cookie to generate, you don't need the before filters. Just stick the value in a static and do it all in the HTPostCallback. But I expect most applications need to generate more than one type of cookie. All this would be much simpler, and threadable, if the generator had a context parameter. Ah well. Hope this helps. regards, -jim
Received on Tuesday, 16 March 1999 11:24:12 UTC