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;
}