On Thu, 22 Nov 2012, Fabian Keil wrote:

Regarding the documentation I think it would make sense to refer to the CURLOPT_HTTPHEADER for the syntax description instead of duplication most of it, or at least making it clear that the syntax is basically the same, so the user doesn't spend time looking for differences that don't exist.

Ack, fixed now.

I also believe that "used for proxy requests" could be mistaken to mean requests that are made through a proxy, so maybe the documentation should explicitly refer to CONNECT requests like the commit description does.

I changed that to become a settting for all HTTP proxy requests, including non-CONNECT cases. I decided to do this because it struck me it isn't very easy for an application to otherwise separate headers for proxies and hosts since libcurl does most of the proxy checking magic itself so many applications won't know if the request goes out over a proxy or directly to the server. So the documentation actually describes what the code does.

Obviously I also need to write up a set of test cases to verify that it works.

Attached is an updated version of the patch.

--

 / daniel.haxx.se
From e09426f0504701737b77fec74a1210f3273c9d24 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <dan...@haxx.se>
Date: Sun, 9 Sep 2012 13:21:06 +0200
Subject: [PATCH] CURLOPT_PROXYHEADER: send/replace proxy headers only

This allows applications to set headers for CONNECT requests that will
not be used in the actual following host request, and vice
versa. Previously this could be problematic if for example an
application wanted to send a Content-Length: header in a host request,
but also have it do CONNECT first.

As a special quirk to stay backwards compatible with libcurl versions
released before this option existed, all headers set with
CURLOPT_HTTPHEADER will also be used for proxies unless you set one or
more headers with CURLOPT_PROXYHEADER. So if you want no header sent to
a proxy, you must set a blank ("") one.

If you after having used CURLOPT_PROXYHEADER want to restore the old
functionality where CURLOPT_HTTPHEADER controls all headers, set
CURLOPT_PROXYHEADER to NULL.
---
 docs/libcurl/curl_easy_setopt.3  |   27 +++++++++++++++
 docs/libcurl/symbols-in-versions |    1 +
 include/curl/curl.h              |    7 +++-
 lib/http.c                       |   67 +++++++++++++++++++++++---------------
 lib/http.h                       |    7 ++--
 lib/http_proxy.c                 |    8 ++---
 lib/rtsp.c                       |   26 +++++++--------
 lib/url.c                        |   14 ++++++++
 lib/urldata.h                    |    1 +
 9 files changed, 110 insertions(+), 48 deletions(-)

diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index a388c22..1e74993 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -1367,6 +1367,33 @@ Pass a NULL to this to reset back to no custom headers.
 
 The most commonly replaced headers have "shortcuts" in the options
 \fICURLOPT_COOKIE\fP, \fICURLOPT_USERAGENT\fP and \fICURLOPT_REFERER\fP.
+
+Starting in 7.29.0, libcurl offers an alternative option that sets or replaces
+headers only for requests that are sent to a proxy:
+\fICURLOPT_PROXYHEADER\fP. If \fICURLOPT_PROXYHEADER\fP is not used at all by
+an application, the \fICURLOPT_HTTPHEADER headers\fP will be used for proxy
+requests as well!
+.IP CURLOPT_PROXYHEADER
+Pass a pointer to a linked list of HTTP headers to pass in your HTTP request
+sent to a proxy. The rules for this lis is identical to the
+\fICURLOPT_HTTPHEADER\fP option's.
+
+The headers set with this option is only ever used in requests sent to a
+proxy.
+
+As a special quirk to stay backwards compatible with the libcurl versions
+released before this option existed, all headers set with
+\fICURLOPT_HTTPHEADER\fP will also be used for proxies unless you set one or
+more headers (or even just NULL) with \fICURLOPT_PROXYHEADER\fP.
+
+The first line in a request (containing the method, usually a GET or POST) is
+not a header and cannot be replaced using this option. Only the lines
+following the request-line are headers. Adding this method line in this list
+of headers will only cause your request to send an invalid header.
+
+Pass a NULL to this to reset back to no custom headers.
+
+This option was added in libcurl 7.29.0.
 .IP CURLOPT_HTTP200ALIASES
 Pass a pointer to a linked list of aliases to be treated as valid HTTP 200
 responses.  Some servers respond with a custom header response line.  For
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index 1de1ace..0a4e5f4 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -424,6 +424,7 @@ CURLOPT_PROGRESSFUNCTION        7.1
 CURLOPT_PROTOCOLS               7.19.4
 CURLOPT_PROXY                   7.1
 CURLOPT_PROXYAUTH               7.10.7
+CURLOPT_PROXYHEADER             7.29.0
 CURLOPT_PROXYPASSWORD           7.19.1
 CURLOPT_PROXYPORT               7.1
 CURLOPT_PROXYTYPE               7.10
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 5b39a24..96afcfe 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -897,7 +897,8 @@ typedef enum {
   /* Set cookie in request: */
   CINIT(COOKIE, OBJECTPOINT, 22),
 
-  /* This points to a linked list of headers, struct curl_slist kind */
+  /* This points to a linked list of headers, struct curl_slist kind. This
+     list is also used for RTSP (in spite of its name) */
   CINIT(HTTPHEADER, OBJECTPOINT, 23),
 
   /* This points to a linked list of post entries, struct curl_httppost */
@@ -1536,6 +1537,10 @@ typedef enum {
   /* set the SMTP auth originator */
   CINIT(MAIL_AUTH, OBJECTPOINT, 217),
 
+  /* This points to a linked list of headers used for proxy requests only,
+     struct curl_slist kind */
+  CINIT(PROXYHEADER, OBJECTPOINT, 218),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
diff --git a/lib/http.c b/lib/http.c
index 4eee832..5bbba85 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -154,17 +154,25 @@ const struct Curl_handler Curl_handler_https = {
 
 
 /*
- * checkheaders() checks the linked list of custom HTTP headers for a
+ * checkheaders() checks the linked list of custom request headers for a
  * particular header (prefix).
  *
+ * It takes a connectdata struct as input instead of the SessionHandle simply
+ * to know if this is a proxy request or not, as it then might check a
+ * different header list.
+ *
  * Returns a pointer to the first matching header or NULL if none matched.
  */
-char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader)
+char *Curl_checkheaders(struct connectdata *conn,
+                        const char *thisheader)
 {
   struct curl_slist *head;
+  struct SessionHandle *data = conn->data;
   size_t thislen = strlen(thisheader);
 
-  for(head = data->set.headers; head; head=head->next) {
+  for(head = (conn->bits.proxy && data->set.proxyheaders)?
+        data->set.proxyheaders:data->set.headers;
+      head; head=head->next) {
     if(Curl_raw_nequal(head->data, thisheader, thislen))
       return head->data;
   }
@@ -573,9 +581,9 @@ output_auth_headers(struct connectdata *conn,
   if(authstatus->picked == CURLAUTH_BASIC) {
     /* Basic */
     if((proxy && conn->bits.proxy_user_passwd &&
-       !Curl_checkheaders(data, "Proxy-authorization:")) ||
+        !Curl_checkheaders(conn, "Proxy-authorization:")) ||
        (!proxy && conn->bits.user_passwd &&
-       !Curl_checkheaders(data, "Authorization:"))) {
+        !Curl_checkheaders(conn, "Authorization:"))) {
       auth="Basic";
       result = http_output_basic(conn, proxy);
       if(result)
@@ -1503,7 +1511,7 @@ static CURLcode expect100(struct SessionHandle *data,
     /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
        100-continue to the headers which actually speeds up post operations
        (as there is one packet coming back from the web server) */
-    ptr = Curl_checkheaders(data, "Expect:");
+    ptr = Curl_checkheaders(conn, "Expect:");
     if(ptr) {
       data->state.expect100header =
         Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -1519,10 +1527,13 @@ static CURLcode expect100(struct SessionHandle *data,
 }
 
 CURLcode Curl_add_custom_headers(struct connectdata *conn,
-                                   Curl_send_buffer *req_buffer)
+                                 bool is_proxy,
+                                 Curl_send_buffer *req_buffer)
 {
   char *ptr;
-  struct curl_slist *headers=conn->data->set.headers;
+  struct curl_slist *headers=
+    (is_proxy && conn->data->set.proxyheaders)?
+    conn->data->set.proxyheaders:conn->data->set.headers;
 
   while(headers) {
     ptr = strchr(headers->data, ':');
@@ -1738,7 +1749,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
      it might have been used in the proxy connect, but if we have got a header
      with the user-agent string specified, we erase the previously made string
      here. */
-  if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
+  if(Curl_checkheaders(conn, "User-Agent:") &&
+     conn->allocptr.uagent) {
     free(conn->allocptr.uagent);
     conn->allocptr.uagent=NULL;
   }
@@ -1759,15 +1771,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     conn->bits.authneg = FALSE;
 
   Curl_safefree(conn->allocptr.ref);
-  if(data->change.referer && !Curl_checkheaders(data, "Referer:"))
+  if(data->change.referer && !Curl_checkheaders(conn, "Referer:"))
     conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
   else
     conn->allocptr.ref = NULL;
 
-  if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie:"))
+  if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:"))
     addcookies = data->set.str[STRING_COOKIE];
 
-  if(!Curl_checkheaders(data, "Accept-Encoding:") &&
+  if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
      data->set.str[STRING_ENCODING]) {
     Curl_safefree(conn->allocptr.accept_encoding);
     conn->allocptr.accept_encoding =
@@ -1779,13 +1791,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 #ifdef HAVE_LIBZ
   /* we only consider transfer-encoding magic if libz support is built-in */
 
-  if(!Curl_checkheaders(data, "TE:") && data->set.http_transfer_encoding) {
+  if(!Curl_checkheaders(conn, "TE:") &&
+     data->set.http_transfer_encoding) {
     /* When we are to insert a TE: header in the request, we must also insert
        TE in a Connection: header, so we need to merge the custom provided
        Connection: header and prevent the original to get sent. Note that if
        the user has inserted his/hers own TE: header we don't do this magic
        but then assume that the user will handle it all! */
-    char *cptr = Curl_checkheaders(data, "Connection:");
+    char *cptr = Curl_checkheaders(conn, "Connection:");
 #define TE_HEADER "TE: gzip\r\n"
 
     Curl_safefree(conn->allocptr.te);
@@ -1799,7 +1812,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   }
 #endif
 
-  ptr = Curl_checkheaders(data, "Transfer-Encoding:");
+  ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
   if(ptr) {
     /* Some kind of TE is requested, check if 'chunked' is chosen */
     data->req.upload_chunky =
@@ -1832,7 +1845,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 
   Curl_safefree(conn->allocptr.host);
 
-  ptr = Curl_checkheaders(data, "Host:");
+  ptr = Curl_checkheaders(conn, "Host:");
   if(ptr && (!data->state.this_is_a_follow ||
              Curl_raw_equal(data->state.first_host, conn->host.name))) {
 #if !defined(CURL_DISABLE_COOKIES)
@@ -1977,13 +1990,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     /* we must build the whole post sequence first, so that we have a size of
        the whole transfer before we start to send it */
     result = Curl_getformdata(data, &http->sendit, data->set.httppost,
-                              Curl_checkheaders(data, "Content-Type:"),
+                              Curl_checkheaders(conn, "Content-Type:"),
                               &http->postsize);
     if(result)
       return result;
   }
 
-  http->p_accept = Curl_checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n";
+  http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
 
   if(( (HTTPREQ_POST == httpreq) ||
        (HTTPREQ_POST_FORM == httpreq) ||
@@ -2064,7 +2077,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
      * ones if any such are specified.
      */
     if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
-       !Curl_checkheaders(data, "Range:")) {
+       !Curl_checkheaders(conn, "Range:")) {
       /* if a line like this was already allocated, free the previous one */
       if(conn->allocptr.rangeline)
         free(conn->allocptr.rangeline);
@@ -2072,7 +2085,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
                                          data->state.range);
     }
     else if((httpreq != HTTPREQ_GET) &&
-            !Curl_checkheaders(data, "Content-Range:")) {
+            !Curl_checkheaders(conn, "Content-Range:")) {
 
       /* if a line like this was already allocated, free the previous one */
       if(conn->allocptr.rangeline)
@@ -2174,7 +2187,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
                      conn->allocptr.ref:"" /* Referer: <data> */,
                      (conn->bits.httpproxy &&
                       !conn->bits.tunnel_proxy &&
-                      !Curl_checkheaders(data, "Proxy-Connection:"))?
+                      !Curl_checkheaders(conn, "Proxy-Connection:"))?
                      "Proxy-Connection: Keep-Alive\r\n":"",
                      te
       );
@@ -2250,7 +2263,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       return result;
   }
 
-  result = Curl_add_custom_headers(conn, req_buffer);
+  result = Curl_add_custom_headers(conn, FALSE, req_buffer);
   if(result)
     return result;
 
@@ -2300,7 +2313,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     http->sending = HTTPSEND_BODY;
 
     if(!data->req.upload_chunky &&
-       !Curl_checkheaders(data, "Content-Length:")) {
+       !Curl_checkheaders(conn, "Content-Length:")) {
       /* only add Content-Length if not uploading chunked */
       result = Curl_add_bufferf(req_buffer,
                                 "Content-Length: %" FORMAT_OFF_T "\r\n",
@@ -2372,7 +2385,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       postsize = data->set.infilesize;
 
     if((postsize != -1) && !data->req.upload_chunky &&
-       !Curl_checkheaders(data, "Content-Length:")) {
+       !Curl_checkheaders(conn, "Content-Length:")) {
       /* only add Content-Length if not uploading chunked */
       result = Curl_add_bufferf(req_buffer,
                                 "Content-Length: %" FORMAT_OFF_T "\r\n",
@@ -2422,7 +2435,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
          we don't upload data chunked, as RFC2616 forbids us to set both
          kinds of headers (Transfer-Encoding: chunked and Content-Length) */
 
-      if(conn->bits.authneg || !Curl_checkheaders(data, "Content-Length:")) {
+      if(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:")) {
         /* we allow replacing this header if not during auth negotiation,
            although it isn't very wise to actually set your own */
         result = Curl_add_bufferf(req_buffer,
@@ -2433,7 +2446,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       }
     }
 
-    if(!Curl_checkheaders(data, "Content-Type:")) {
+    if(!Curl_checkheaders(conn, "Content-Type:")) {
       result = Curl_add_bufferf(req_buffer,
                                 "Content-Type: application/"
                                 "x-www-form-urlencoded\r\n");
@@ -2445,7 +2458,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
        the somewhat bigger ones we allow the app to disable it. Just make
        sure that the expect100header is always set to the preferred value
        here. */
-    ptr = Curl_checkheaders(data, "Expect:");
+    ptr = Curl_checkheaders(conn, "Expect:");
     if(ptr) {
       data->state.expect100header =
         Curl_compareheader(ptr, "Expect:", "100-continue");
diff --git a/lib/http.h b/lib/http.h
index cfe8b84..b94ef19 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -8,7 +8,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <dan...@haxx.se>, et al.
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <dan...@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -34,7 +34,7 @@ bool Curl_compareheader(const char *headerline,  /* line to check */
                         const char *header,   /* header keyword _with_ colon */
                         const char *content); /* content string to find */
 
-char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader);
+char *Curl_checkheaders(struct connectdata *conn, const char *thisheader);
 
 /* ------------------------------------------------------------------------- */
 /*
@@ -61,7 +61,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
 CURLcode Curl_add_timecondition(struct SessionHandle *data,
                                 Curl_send_buffer *buf);
 CURLcode Curl_add_custom_headers(struct connectdata *conn,
-                                   Curl_send_buffer *req_buffer);
+                                 bool is_connect,
+                                 Curl_send_buffer *req_buffer);
 
 /* protocol-specific functions set up to be called by the main engine */
 CURLcode Curl_http(struct connectdata *conn, bool *done);
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index 245e1c1..688f259 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -176,7 +176,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
           return CURLE_OUT_OF_MEMORY;
         }
 
-        if(!Curl_checkheaders(data, "Host:")) {
+        if(!Curl_checkheaders(conn, "Host:")) {
           host = aprintf("Host: %s\r\n", hostheader);
           if(!host) {
             free(hostheader);
@@ -184,10 +184,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
             return CURLE_OUT_OF_MEMORY;
           }
         }
-        if(!Curl_checkheaders(data, "Proxy-Connection:"))
+        if(!Curl_checkheaders(conn, "Proxy-Connection:"))
           proxyconn = "Proxy-Connection: Keep-Alive\r\n";
 
-        if(!Curl_checkheaders(data, "User-Agent:") &&
+        if(!Curl_checkheaders(conn, "User-Agent:") &&
            data->set.str[STRING_USERAGENT])
           useragent = conn->allocptr.uagent;
 
@@ -211,7 +211,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
         free(hostheader);
 
         if(CURLE_OK == result)
-          result = Curl_add_custom_headers(conn, req_buffer);
+          result = Curl_add_custom_headers(conn, TRUE, req_buffer);
 
         if(CURLE_OK == result)
           /* CRLF terminate the request */
diff --git a/lib/rtsp.c b/lib/rtsp.c
index ca9788e..07ed226 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -340,7 +340,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
   }
 
   /* Transport Header for SETUP requests */
-  p_transport = Curl_checkheaders(data, "Transport:");
+  p_transport = Curl_checkheaders(conn, "Transport:");
   if(rtspreq == RTSPREQ_SETUP && !p_transport) {
     /* New Transport: setting? */
     if(data->set.str[STRING_RTSP_TRANSPORT]) {
@@ -364,11 +364,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
   /* Accept Headers for DESCRIBE requests */
   if(rtspreq == RTSPREQ_DESCRIBE) {
     /* Accept Header */
-    p_accept = Curl_checkheaders(data, "Accept:")?
+    p_accept = Curl_checkheaders(conn, "Accept:")?
       NULL:"Accept: application/sdp\r\n";
 
     /* Accept-Encoding header */
-    if(!Curl_checkheaders(data, "Accept-Encoding:") &&
+    if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
        data->set.str[STRING_ENCODING]) {
       Curl_safefree(conn->allocptr.accept_encoding);
       conn->allocptr.accept_encoding =
@@ -385,18 +385,18 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
      it might have been used in the proxy connect, but if we have got a header
      with the user-agent string specified, we erase the previously made string
      here. */
-  if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
+  if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
     Curl_safefree(conn->allocptr.uagent);
     conn->allocptr.uagent = NULL;
   }
-  else if(!Curl_checkheaders(data, "User-Agent:") &&
+  else if(!Curl_checkheaders(conn, "User-Agent:") &&
           data->set.str[STRING_USERAGENT]) {
     p_uagent = conn->allocptr.uagent;
   }
 
   /* Referrer */
   Curl_safefree(conn->allocptr.ref);
-  if(data->change.referer && !Curl_checkheaders(data, "Referer:"))
+  if(data->change.referer && !Curl_checkheaders(conn, "Referer:"))
     conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
   else
     conn->allocptr.ref = NULL;
@@ -413,7 +413,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
      (rtspreq  & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
 
     /* Check to see if there is a range set in the custom headers */
-    if(!Curl_checkheaders(data, "Range:") && data->state.range) {
+    if(!Curl_checkheaders(conn, "Range:") && data->state.range) {
       Curl_safefree(conn->allocptr.rangeline);
       conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
       p_range = conn->allocptr.rangeline;
@@ -423,11 +423,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
   /*
    * Sanity check the custom headers
    */
-  if(Curl_checkheaders(data, "CSeq:")) {
+  if(Curl_checkheaders(conn, "CSeq:")) {
     failf(data, "CSeq cannot be set as a custom header.");
     return CURLE_RTSP_CSEQ_ERROR;
   }
-  if(Curl_checkheaders(data, "Session:")) {
+  if(Curl_checkheaders(conn, "Session:")) {
     failf(data, "Session ID cannot be set as a custom header.");
     return CURLE_BAD_FUNCTION_ARGUMENT;
   }
@@ -483,7 +483,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
       return result;
   }
 
-  result = Curl_add_custom_headers(conn, req_buffer);
+  result = Curl_add_custom_headers(conn, FALSE, req_buffer);
   if(result)
     return result;
 
@@ -506,7 +506,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
     if(putsize > 0 || postsize > 0) {
       /* As stated in the http comments, it is probably not wise to
        * actually set a custom Content-Length in the headers */
-      if(!Curl_checkheaders(data, "Content-Length:")) {
+      if(!Curl_checkheaders(conn, "Content-Length:")) {
         result = Curl_add_bufferf(req_buffer,
             "Content-Length: %" FORMAT_OFF_T"\r\n",
             (data->set.upload ? putsize : postsize));
@@ -516,7 +516,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
 
       if(rtspreq == RTSPREQ_SET_PARAMETER ||
          rtspreq == RTSPREQ_GET_PARAMETER) {
-        if(!Curl_checkheaders(data, "Content-Type:")) {
+        if(!Curl_checkheaders(conn, "Content-Type:")) {
           result = Curl_add_bufferf(req_buffer,
               "Content-Type: text/parameters\r\n");
           if(result)
@@ -525,7 +525,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
       }
 
       if(rtspreq == RTSPREQ_ANNOUNCE) {
-        if(!Curl_checkheaders(data, "Content-Type:")) {
+        if(!Curl_checkheaders(conn, "Content-Type:")) {
           result = Curl_add_bufferf(req_buffer,
               "Content-Type: application/sdp\r\n");
           if(result)
diff --git a/lib/url.c b/lib/url.c
index 601d8d3..58e922d 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1261,6 +1261,20 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
     data->set.headers = va_arg(param, struct curl_slist *);
     break;
 
+  case CURLOPT_PROXYHEADER:
+    /*
+     * Set a list with proxy headers to use (or replace internals with)
+     *
+     * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
+     * long time we remain doing it this way until CURLOPT_PROXYHEADER is
+     * used. As soon as this option has been used, if set to anything but
+     * NULL, custom headers for proxies are only picked from this list.
+     *
+     * Set this option to NULL to restore the previous behavior.
+     */
+    data->set.proxyheaders = va_arg(param, struct curl_slist *);
+    break;
+
   case CURLOPT_HTTP200ALIASES:
     /*
      * Set a list of aliases for HTTP 200 in response header
diff --git a/lib/urldata.h b/lib/urldata.h
index 4116c34..54b18a3 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1466,6 +1466,7 @@ struct UserDefined {
                                 download */
   curl_off_t set_resume_from;  /* continue [ftp] transfer from here */
   struct curl_slist *headers; /* linked list of extra headers */
+  struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */
   struct curl_httppost *httppost;  /* linked list of POST data */
   bool cookiesession;   /* new cookie session? */
   bool crlf;            /* convert crlf on ftp upload(?) */
-- 
1.7.10.4

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to