CURLOPT_POSTREDIR: also allow 303 to do POST on the redirected URL
authorAndrei Cipu <acipu@ixiacom.com>
Fri, 30 Mar 2012 07:40:04 +0000 (10:40 +0300)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 5 Apr 2012 21:29:21 +0000 (23:29 +0200)
As it turns out, some people do want that after all.

docs/libcurl/curl_easy_setopt.3
docs/libcurl/symbols-in-versions
include/curl/curl.h
lib/transfer.c
lib/url.c
lib/urldata.h

index d0e054b..a90ee65 100644 (file)
@@ -1180,12 +1180,13 @@ Setting the limit to 0 will make libcurl refuse any redirect. Set it to -1 for
 an infinite number of redirects (which is the default)
 .IP CURLOPT_POSTREDIR
 Pass a bitmask to control how libcurl acts on redirects after POSTs that get a
-301 or 302 response back.  A parameter with bit 0 set (value
+301, 302 or 303 response back.  A parameter with bit 0 set (value
 \fBCURL_REDIR_POST_301\fP) tells the library to respect RFC 2616/10.3.2 and
 not convert POST requests into GET requests when following a 301
 redirection. Setting bit 1 (value CURL_REDIR_POST_302) makes libcurl maintain
-the request method after a 302 redirect. CURL_REDIR_POST_ALL is a convenience
-define that sets both bits.
+the request method after a 302 redirect. Setting bit 2 (value
+\fBCURL_REDIR_POST_303) makes libcurl maintain the request method after a 302
+redirect. CURL_REDIR_POST_ALL is a convenience define that sets both bits.
 
 The non-RFC behaviour is ubiquitous in web browsers, so the library does the
 conversion by default to maintain consistency. However, a server may require a
index 62d8a24..41705fd 100644 (file)
@@ -649,6 +649,7 @@ CURL_READFUNC_PAUSE             7.18.0
 CURL_REDIR_GET_ALL              7.19.1
 CURL_REDIR_POST_301             7.19.1
 CURL_REDIR_POST_302             7.19.1
+CURL_REDIR_POST_303             7.25.1
 CURL_REDIR_POST_ALL             7.19.1
 CURL_RTSPREQ_ANNOUNCE           7.20.0
 CURL_RTSPREQ_DESCRIBE           7.20.0
index f2501cd..f3166d9 100644 (file)
@@ -1624,13 +1624,16 @@ enum CURL_TLSAUTH {
 };
 
 /* symbols to use with CURLOPT_POSTREDIR.
-   CURL_REDIR_POST_301 and CURL_REDIR_POST_302 can be bitwise ORed so that
-   CURL_REDIR_POST_301 | CURL_REDIR_POST_302 == CURL_REDIR_POST_ALL */
+   CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303
+   can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302
+   | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */
 
 #define CURL_REDIR_GET_ALL  0
 #define CURL_REDIR_POST_301 1
 #define CURL_REDIR_POST_302 2
-#define CURL_REDIR_POST_ALL (CURL_REDIR_POST_301|CURL_REDIR_POST_302)
+#define CURL_REDIR_POST_303 4
+#define CURL_REDIR_POST_ALL \
+    (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
 
 typedef enum {
   CURL_TIMECOND_NONE,
index d872719..20b3d04 100644 (file)
@@ -1864,7 +1864,7 @@ CURLcode Curl_follow(struct SessionHandle *data,
      */
     if((data->set.httpreq == HTTPREQ_POST
         || data->set.httpreq == HTTPREQ_POST_FORM)
-       && !data->set.post301) {
+       && !(data->set.keep_post & CURL_REDIR_POST_301)) {
       infof(data,
             "Violate RFC 2616/10.3.2 and switch from POST to GET\n");
       data->set.httpreq = HTTPREQ_GET;
@@ -1892,7 +1892,7 @@ CURLcode Curl_follow(struct SessionHandle *data,
     */
     if((data->set.httpreq == HTTPREQ_POST
         || data->set.httpreq == HTTPREQ_POST_FORM)
-       && !data->set.post302) {
+       && !(data->set.keep_post & CURL_REDIR_POST_302)) {
       infof(data,
             "Violate RFC 2616/10.3.3 and switch from POST to GET\n");
       data->set.httpreq = HTTPREQ_GET;
@@ -1900,9 +1900,10 @@ CURLcode Curl_follow(struct SessionHandle *data,
     break;
 
   case 303: /* See Other */
-    /* Disable both types of POSTs, since doing a second POST when
-     * following isn't what anyone would want! */
-    if(data->set.httpreq != HTTPREQ_GET) {
+    /* Disable both types of POSTs, unless the user explicitely
+       asks for POST after POST */
+    if(data->set.httpreq != HTTPREQ_GET
+      && !(data->set.keep_post & CURL_REDIR_POST_303)) {
       data->set.httpreq = HTTPREQ_GET; /* enforce GET request */
       infof(data, "Disables POST, goes with %s\n",
             data->set.opt_no_body?"HEAD":"GET");
index 01e217c..9ae977e 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -1111,12 +1111,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
      * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
      * CURL_REDIR_POST_301 - POST is kept as POST after 301
      * CURL_REDIR_POST_302 - POST is kept as POST after 302
-     * CURL_REDIR_POST_ALL - POST is kept as POST after 301 and 302
+     * CURL_REDIR_POST_303 - POST is kept as POST after 303
+     * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
      * other - POST is kept as POST after 301 and 302
      */
     long postRedir = va_arg(param, long);
-    data->set.post301 = (postRedir & CURL_REDIR_POST_301)?TRUE:FALSE;
-    data->set.post302 = (postRedir & CURL_REDIR_POST_302)?TRUE:FALSE;
+    data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
   }
   break;
 
index b27fc6b..3474431 100644 (file)
@@ -1368,9 +1368,9 @@ struct UserDefined {
   long followlocation; /* as in HTTP Location: */
   long maxredirs;    /* maximum no. of http(s) redirects to follow, set to -1
                         for infinity */
-  bool post301;      /* Obey RFC 2616/10.3.2 and keep POSTs as POSTs after a
-                        301 */
-  bool post302;      /* keep POSTs as POSTs after a 302 */
+
+  int keep_post;     /* keep POSTs as POSTs after a 30x request; each
+                        bit represents a request, from 301 to 303 */
   bool free_referer; /* set TRUE if 'referer' points to a string we
                         allocated */
   void *postfields;  /* if POST, set the fields' values here */