W3C home > Mailing lists > Public > www-lib@w3.org > July to September 2003

reuse HTRequest

From: Jerry G. Chiuan <jerry@oridus.com>
Date: Tue, 2 Sep 2003 18:03:19 -0700
Message-ID: <13eb01c371b7$2a4d9ff0$25a8a8a8@piglet>
To: <www-lib@w3.org>
Cc: "Akritidis Xristoforos" <cakrit@hol.net>
Hi All,
I would like to reuse HTRequest to keep sending data, e.g.

HTRequest * request = HTRequest_new();
HTChunk * chunk = NULL;
for ( ; ; ) {
    //construct data
    chunk = HTPostFormAnchorToChunk(data, anchor, request);
    //deal with data

Is it possible to do that? what else do I have to pay attention to?

Thank you
- Jerry

----- Original Message ----- 
From: Akritidis Xristoforos 
To: Jerry G. Chiuan 
Sent: Sunday, August 31, 2003 11:52 PM
Subject: RE: A better wwwlib example (as a RE to how to return from callback

It seems like HTNet_isIdle() just never returns when I put it in the terminate_handler function. Don't ask me why...

The thing is, I never tried to send multiple requests at once. I had enough problems using the library 'synchronously'. 

The www_request() function returns only when the request is completed, which is what I needed for my programs. 

As for the HT_ERROR, it's a constant equal to -1. The function should actually return the 'status'  variable, but I don't use the return value anyway.


-----Original Message-----
From: Jerry G. Chiuan [mailto:jerry@oridus.com] 
Sent: Friday, August 29, 2003 10:01 PM
To: Akritidis Xristoforos
Subject: Re: A better wwwlib example (as a RE to how to return from callback

Hi Christopher,

Frist, thanks for your "distribution" : )

here I have some questions about your code:

- In your terminate_handler, you invoke HTEventList_stopLoop (), do you need to make sure there is no any other active requests before doing it?

( by using HTNet_isIdle( ), return TRUE if there is no active request any more )

- Once HTEventList_stopLoop () get called, that means it terminates the blocking in event loop and the main procedure www_request( ) can keep going?

- why does terminate_handler return HT_ERROR, what does HT_ERROR mean?


- Jerry


I see that people keep coming across the same problems I encountered on
the fateful day I dug my teeth into wwwlib. It was a real nightmare and
confirmed my belief that a library without documentation is basically
unusable, unless you become an expert in it.

I've become no expert, but I managed to write an api that does http POST
requests with any number of arguments, handles authentication and stores
the result body and headers in two separate strings. It's far from
perfect (see the hard-coded 'outputformat = "xml"' for example, but it
will get you where you're going fast.

All you need to do is call www_init(), www_request with the options you
want, as many times as you like, and www_terminate() when you're done.
Just make sure you change my custom debug function to something else
(printf, HTprint, whatever...)

You may use this, modify it as you please...
If it becomes good enough, maybe we can put it in the distribution?


#include "WWWLib.h"
#include "WWWHTTP.h"
#include "WWWInit.h"
#include "HTUTree.h"
#include "HTNet.h"
#include "HTAABrow.h"

// variable length string that gets the entire response
HTChunk * result_chunk = NULL;

// Avoid printing progress messages
f_PUBLIC BOOL HTProgress (HTRequest * request, HTAlertOpcode op,
int msgnum, const char * dfault, void * input,
HTAlertPar * reply)
    char * msg = HTDialog_progressMessage(request, op, msgnum, dfault,
    if (msg) {
debug(D_DEBUG,"%s\n", msg);
    if (reply) return YES;
    return YES;

// Declaration and constructor for authentication information.
typedef struct _MYBasic {   /* Basic challenge and
credentials */
  char * uid;
  char * pw;
  BOOL retry;     /* Should we ask the user again? */
  BOOL proxy;     /* Proxy authentication */
} MYBasic;

PRIVATE MYBasic * MYBasic_new(char * username, char* password)
  MYBasic * me = NULL;
  if ((me = (MYBasic *) HT_CALLOC(1, sizeof(MYBasic))) == NULL)
  me->uid = strdup(username);
  me->pw = strdup(password);
  me->retry = NO;
  me->proxy = NO;
  return me;

PRIVATE int printer (const char * fmt, va_list pArgs)
  s_debug(D_DEBUG, fmt, pArgs);
  return 0;

PRIVATE int tracer (const char * fmt, va_list pArgs)
  s_debug(D_ANALYSIS, fmt, pArgs);
  return 0;

PRIVATE int terminate_handler (HTRequest * request, HTResponse *
       void * param, int status)
  char statuscode[64];
  sprintf (statuscode,"%d",status);
  HTEventList_stopLoop ();
  if (request && response && param && status) return HT_ERROR;
  return HT_ERROR;

void www_init(void) {
  /* Need our own trace and print functions */

  /* Get trace messages */
  if (log_facilities & D_ANALYSIS) {

  /* Add our own filter to update the history list */
  HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);

  /* Set the timeout for long we are going to wait for a response */

  /* Initialize libwww core */
  HTProfile_newNoCacheClient("TestApp", "1.0");


void www_terminate(void) {
  /* Terminate the Library */

int www_request (char* outputformat, char **HTMLheader, char **
HTMLresponse, char *url, char *username, char *password, ...) {
  // Everything requires a request stream
  HTRequest * request = HTRequest_new();
  // Structure holding authentication info
  MYBasic * basic;
  // Anchor holding the URL. Need it for POST requests
  HTAnchor * anchor = NULL;

  char * cwd = HTGetCurrentDirectoryURL();
  char * absolute_url;
  char * name_value=NULL;

  // Get arbitrary number of arguments for the cgi we will call
  // Put the arguments in an association list, to be used in PUT and GET
  HTAssocList * formfields = NULL;

  va_list argsvar;
  va_start (argsvar, password);
  name_value=va_arg(argsvar,char *);
  if (name_value) {
    formfields = HTAssocList_new ();
    do {
      debug(D_DEBUG,"argument '%s'", name_value);
      name_value=va_arg(argsvar,char *);
    } while (name_value);

  if (!url) return 1;

  debug(D_DEBUG,"www_request %s", url);

  // Escape illegal characters. Basically spaces and greek letters
  absolute_url = HTParse(url, cwd, PARSE_ALL);

  /* We want raw output including headers */
  if (strcmp(outputformat,"xml") == 0) {
    HTRequest_setOutputFormat(request, HTAtom_for("text/xml"));
  } else {
    HTRequest_setOutputFormat(request, WWW_SOURCE);
  /* Close connection immediately */
  HTRequest_addConnection(request, "close", "");

  /* Automatic Authentication */
  if (username && password) {
    basic = MYBasic_new(username,password);
    HTBasic_generate (request, basic, 0);

  /* Get an anchor object for the URL */
  anchor = HTAnchor_findAddress(absolute_url);

  // Load the url
  if (formfields) {
    // Load with a POST
    result_chunk = HTPostFormAnchorToChunk(formfields, anchor, request);

    /* Clean up the form fields */

  } else {
    // Load with a GET
    result_chunk = HTLoadAnchorToChunk (anchor, request);

  (*HTMLheader) = NULL;
  (*HTMLresponse) = NULL;

  if (result_chunk) {
    /* Go into the event loop... */
    (*HTMLresponse) = HTChunk_toCString(result_chunk);
    debug(D_ANALYSIS, "Response : %s", *HTMLresponse);
    // Get headers and status code
      HTResponse *response = HTRequest_response(request);
      if (response) {
HTAssocList * headers = HTResponse_header(response);
if (headers) {
  HTAssoc * pres;
  (*HTMLheader) = (char *) malloc (sizeof(char) * 1024);
  (*HTMLheader)[0] = '\0';
  while ((pres = (HTAssoc *) HTAssocList_nextObject(headers))) {
    char * name = HTAssoc_name(pres);
    char * value = HTAssoc_value(pres);
    if (strcmp(name,"status") == 0) {
      RETURNVALUE = atoi(value);
    } else {
      debug(D_DEBUG,"HEADER %s = %s", name, value);
      sprintf(*HTMLheader,"%s%s = %s\n",*HTMLheader,name,value);


  /* Clean up the request */
Received on Tuesday, 2 September 2003 21:02:37 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:33:56 UTC