Re: errors in post request

[email protected] (Hanspeter Halle)
Newsgroups gmane.comp.lib.libwww
Message-ID <[email protected]>
Hi Venu,
the original post code in libwww is broken for servers supporting pipelinig 
(which are the most ones nowadays). If a 2nd post to the same server is 
requested before the data of the 1st one is sent libwww sends the 2nd 
HTTP-request before the data of the first. This will screw up every server. 
Possible solutions:

1. Decrease the delay between the post and the data inserted by libwww 
(default is 2s) by using the function HTTP_setBodyWriteDelay. This in fact 
does only decrease the propability of this problem.

2. Switch off pipelining. So for every request a new TCP-connection will be 
used.

3. Try if my patch (see below) can still be applied to the current version of 
libwww. It delays the transmission of the 2nd HTTP-Request until the data for 
the 1st one has completely delivered.

Hanspeter



 
Am Mittwoch, 7. Mai 2003 09:53 schrieb pawar:
> hi everybody,
> i am new to libwww library.
> i am developing application which works like a proxy
> server. it receives request from browser, and it will
> forward that request to remote server using libwww
> library and sockets.
> i am getting errors while getting data  from remote
> server in post request.
> when the first time request goes to server through my
> application, server is responding properly and getting
> data, but when the second request goes to remote
> server while reading the data from the remote server i
> am getting the following error.
> from HTDialog_errorMessage() function of HTDialog.c
>
> Fatal Error: 403 Forbidden (Forbidden)
>
> anybody helps me in this greatly appreciated.
>
> thanks & regards,
>
> venu
>
> =====
> Venu Pawar
> Avon Technologies (India) Private Limited
>
> __________________________________
> Do you Yahoo!?
> The New Yahoo! Search - Faster. Easier. Bingo.
> http://search.yahoo.com
post-bugfix.patch (text/x-diff, 5.8 KB)
Index: Library/src/HTHost.c
===================================================================
RCS file: /sources/public/libwww/Library/src/HTHost.c,v
retrieving revision 2.72
diff -c -r2.72 HTHost.c
*** HTHost.c	2000/07/28 13:56:08	2.72
--- HTHost.c	2002/12/05 13:05:59
***************
*** 1163,1168 ****
--- 1163,1209 ----
      return NO;
  }
  
+ 
+ /*
+ **	[email protected]: Return the successor resp. predecessor of the given request in 
+ **	the pipeline if any
+ */
+ extern HTNet * HTHost_predecessor (HTHost * host, HTNet * net)
+ {
+   HTList * lp;
+   HTNet * net2;
+ 
+   if (!host || !net)
+     return NULL;
+ 
+   for (lp=host->pipeline;(net2=HTList_nextObject (lp)); )
+     if ( net2 == net ) break;
+ 
+   if ( !net2 )
+     return NULL;
+ 
+   return HTList_nextObject (lp);
+ }
+ 
+ extern HTNet * HTHost_successor (HTHost * host, HTNet * net)
+ {
+   HTList * lp;
+   HTNet * net2;
+   HTNet * res = NULL;
+ 
+   if (!host || !net)
+     return NULL;
+ 
+   for (lp=host->pipeline;(net2=HTList_nextObject (lp)); ) {
+     if ( net2 == net ) 
+       return res;
+     else
+       res = net2;
+   }
+ 
+   return NULL;
+ }
+ 
  /*
  **	Handle pending host objects.
  **	There are two ways we can end up with pending reqyests:
Index: Library/src/HTHost.html
===================================================================
RCS file: /sources/public/libwww/Library/src/HTHost.html,v
retrieving revision 2.29
diff -c -r2.29 HTHost.html
*** HTHost.html	1999/07/07 15:43:28	2.29
--- HTHost.html	2002/12/05 13:06:00
***************
*** 201,206 ****
--- 201,209 ----
  extern BOOL HTHost_deleteNet (HTHost * host, HTNet * net, int status);
  
  extern HTList * HTHost_net   (HTHost * host);
+ 
+ extern HTNet * HTHost_predecessor (HTHost * host, HTNet * net);
+ extern HTNet * HTHost_successor (HTHost * host, HTNet * net);
  </PRE>
  <H2>
    Channels
Index: Library/src/HTNet.c
===================================================================
RCS file: /sources/public/libwww/Library/src/HTNet.c,v
retrieving revision 2.106
diff -c -r2.106 HTNet.c
*** HTNet.c	2000/07/04 15:26:25	2.106
--- HTNet.c	2002/12/05 13:06:02
***************
*** 1299,1301 ****
--- 1299,1324 ----
  {
      return (net && net->countRawBytes);
  }
+ 
+ 
+ /* ------------------------------------------------------------------------- */
+ /*			    Delay pipeline successors 			     */
+ /* ------------------------------------------------------------------------- */
+ 
+ 
+ extern void HTNet_enableSuccessor (HTNet * net)
+ {
+   if ( net )
+     net->successorEnabled = YES;
+ }
+ 
+ 
+ /*
+ **	Check if this request has finished sending.
+ **	If net==NULL we suppose the asking request has no 
+ **	predecessor, so sending is allowed
+ */
+ extern BOOL HTNet_isSuccessorEnabled (HTNet * net)
+ {
+   return net ? net->successorEnabled : YES;
+ }
Index: Library/src/HTNet.html
===================================================================
RCS file: /sources/public/libwww/Library/src/HTNet.html,v
retrieving revision 2.57
diff -c -r2.57 HTNet.html
*** HTNet.html	2000/07/04 15:18:51	2.57
--- HTNet.html	2002/12/05 13:06:03
***************
*** 665,670 ****
--- 665,679 ----
  <PRE>extern BOOL HTNet_setRawBytesCount (HTNet * net, BOOL mode);
  extern BOOL HTNet_rawBytesCount (HTNet * net);
  </PRE>
+ <H3>
+   Delay pipeline successors
+ </H3>
+ <P>
+ [email protected]: With pipelining the next request after a post could easily be sent before 
+ the post data where completely out. So we provide a flag here telling that this request is completely sent.
+ <PRE>extern void HTNet_enableSuccessor (HTNet * net);
+ extern BOOL HTNet_isSuccessorEnabled (HTNet * net);
+ </PRE>
  <PRE>
  #endif /* HTNET_H */
  </PRE>
Index: Library/src/HTNetMan.html
===================================================================
RCS file: /sources/public/libwww/Library/src/HTNetMan.html,v
retrieving revision 2.25
diff -c -r2.25 HTNetMan.html
*** HTNetMan.html	1998/09/24 19:48:52	2.25
--- HTNetMan.html	2002/12/05 13:06:03
***************
*** 65,70 ****
--- 65,73 ----
  
      /* Eric's sleezoid cheat - should go to extra pipeline object */
      HTEventType		registeredFor;
+ 
+     /* Hanspeter's post bug workaround */
+     BOOL		successorEnabled;
  };
  
  extern SOCKET HTNet_socket(HTNet * me);
Index: Library/src/HTTP.c
===================================================================
RCS file: /sources/public/libwww/Library/src/HTTP.c,v
retrieving revision 1.192
diff -c -r1.192 HTTP.c
*** HTTP.c	2002/05/28 18:36:25	1.192
--- HTTP.c	2002/12/05 13:06:06
***************
*** 1063,1070 ****
--- 1063,1079 ----
      **  time so that we can write some more data to the net.
      */
      if (status != HT_OK) {
+         HTHost * host = HTNet_host(http->net);
+ 	HTNet * successor;
+ 
  	HTTimer_delete(http->timer);
  	http->timer = NULL;
+ 	HTNet_enableSuccessor ( http->net );
+ 	successor = HTHost_successor ( host, http->net );
+ 	if ( ! successor )
+ 	  HTHost_launchPending ( host );
+ 	else
+ 	  HTNet_execute( successor, HTEvent_WRITE);
      } else if (!http->repetitive_writing) {
  	http->timer = HTTimer_new(NULL, FlushPutEvent, http, HTRepeatWrite, YES, YES);
  	http->repetitive_writing = YES;
***************
*** 1255,1260 ****
--- 1264,1274 ----
  	      if (type == HTEvent_WRITE) {
  		  HTStream * input = HTRequest_inputStream(request);
  		  HTPostCallback * pcbf = HTRequest_postCallback(request);
+ 
+ 		  /* hphalle: Check if predecessor has finished writing */
+ 		  if (!HTNet_isSuccessorEnabled(HTHost_predecessor(host, net)))
+ 		    return HT_OK;
+ 
  		  status = HTRequest_flush(request) ?
  		      HTHost_forceFlush(host) : (*input->isa->flush)(input);
  
***************
*** 1289,1294 ****
--- 1303,1309 ----
  			**  Check to see if we can start a new request
  			**  pending in the host object.
  			*/
+ 			HTNet_enableSuccessor ( net );
  			HTHost_launchPending(host);
  			type = HTEvent_READ;
  		      }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.