cURL / Mailing Lists / curl-library / Single Mail

curl-library

POST+30x=GET?

From: Dirk Manske <dm_at_nettraffic.de>
Date: Mon, 15 Apr 2002 00:58:55 +0200

Hallo,

being non RFC conform to be browser conform?

While doing a login transaction with my libcurl application I noticed
that libcurl does a post after getting a 301 from a previous post request.

Looking into http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.2:

| Note: When automatically redirecting a POST request after
| receiving a 301 status code, some existing HTTP/1.0 user agents
| will erroneously change it into a GET request.

Hmm, libcurl is right...but most browsers do a get after a 301 to follow Location,
see anonymized extract from by squid log:

Mozilla 0.9.9

 TCP_MISS/301 648 POST http://.../login_check - DIRECT/... text/html
 TCP_MISS/301 353 GET http://.../cookie_check/1,9144,,00.html? - DIRECT/64.39.40.14

Konqueror 3.0

 TCP_MISS/301 648 POST http://.../login_check - DIRECT/... text/html
 TCP_MISS/301 353 GET http://.../cookie_check/1,9144,,00.html? - DIRECT/64.39.40.14 text/html

NS 4.79

 TCP_MISS/301 648 POST http://.../login_check - DIRECT/... text/html
 TCP_MISS/301 353 GET http://.../cookie_check/1,9144,,00.html? - DIRECT/... text/html

Opera 6.0beta1

 TCP_MISS/301 648 POST http://.../login_check - DIRECT/... text/html
 TCP_MISS/404 455 POST http://.../cookie_check/1,9144,,00.html? - DIRECT/...

Links 0.96

 TCP_MISS/301 743 POST http://.../login_check - DIRECT/... text/html
 TCP_MISS/404 450 POST http://.../cookie_check/1,9144,,00.html? - DIRECT/... text/html

w3m 0.2.4

 TCP_MISS/301 643 POST http://.../login_check - DIRECT/... text/html
 TCP_MISS/301 348 GET http://.../cookie_check/1,9144,,00.html? - DIRECT/... text/html

Summarize: Mozilla,Konqueror,NS4, and w3m do a get
            Opera6 and Links do a post.

            2:1 get/post

When doing post login will fail (webserver answers 404).

So I have done this provisionally patch againt 7.9.5:

--- snip (hand made diff)
         /* TBD: set the URL with curl_setopt() */
         data->change.url = newurl;
         newurl = NULL; /* don't free! */

         infof(data, "Follows Location: to new URL: '%s'\n", data->change.url);
+ if(data->set.httpreq==HTTPREQ_POST || data->set.httpreq==HTTPREQ_POST_FORM){
+ infof(data, "Follows Location: switch from post to get\n");
+ data->set.httpreq=HTTPREQ_GET;
+ }
         /*
          * We get here when the HTTP code is 300-399. We need to perform
          * differently based on exactly what return code there was.
--- snip

With these changes login wrongs with libcurl.

But is this the right way?

May be it is better to switch to get only when the location url contains a '?':

--- snip (hande made diff)
         /* TBD: set the URL with curl_setopt() */
         data->change.url = newurl;
         newurl = NULL; /* don't free! */

+ infof(data, "Follows Location: to new URL: '%s'\n", data->change.url);
+ if((data->set.httpreq==HTTPREQ_POST || data->set.httpreq==HTTPREQ_POST_FORM)
+ && strchr(data->change.url,'?') ){
+ infof(data, "Follows Location: switch from post to get\n");
+ data->set.httpreq=HTTPREQ_GET;
+ }
+
        /*
         * We get here when the HTTP code is 300-399. We need to perform
         * differently based on exactly what return code there was.
--- snip

[Warning: these patches are not well tested.]

Comments?

Live long a prosper,
Dirk Manske
Received on 2002-04-15