From 74851340bd7b4edbdc749e74562fc1ebcef9930f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 20 Feb 2014 17:10:00 +0100 Subject: PROXYHEADER: send these headers in "normal" proxy requests too Updated the docs to clarify and the code accordingly, with test 1528 to verify: When CURLHEADER_SEPARATE is set and libcurl is asked to send a request to a proxy but it isn't CONNECT, then _both_ header lists (CURLOPT_HTTPHEADER and CURLOPT_PROXYHEADER) will be used since the single request is then made for both the proxy and the server. --- lib/http.c | 148 +++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 94 insertions(+), 54 deletions(-) (limited to 'lib') diff --git a/lib/http.c b/lib/http.c index b316fb4c2..1a2799f28 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1544,80 +1544,120 @@ static CURLcode expect100(struct SessionHandle *data, return result; } +enum proxy_use { + HEADER_SERVER, /* direct to server */ + HEADER_PROXY, /* regular request to proxy */ + HEADER_CONNECT /* sending CONNECT to a proxy */ +}; + CURLcode Curl_add_custom_headers(struct connectdata *conn, - bool is_proxy, + bool is_connect, Curl_send_buffer *req_buffer) { char *ptr; - struct curl_slist *headers= - (is_proxy && conn->data->set.sep_headers)? - conn->data->set.proxyheaders:conn->data->set.headers; - - while(headers) { - ptr = strchr(headers->data, ':'); - if(ptr) { - /* we require a colon for this to be a true header */ + struct curl_slist *h[2]; + struct curl_slist *headers; + int numlists=1; /* by default */ + struct SessionHandle *data = conn->data; + int i; - ptr++; /* pass the colon */ - while(*ptr && ISSPACE(*ptr)) - ptr++; + enum proxy_use proxy; - if(*ptr) { - /* only send this if the contents was non-blank */ + if(is_connect) + proxy = HEADER_CONNECT; + else + proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy? + HEADER_PROXY:HEADER_SERVER; - if(conn->allocptr.host && - /* a Host: header was sent already, don't pass on any custom Host: - header as that will produce *two* in the same request! */ - checkprefix("Host:", headers->data)) - ; - else if(conn->data->set.httpreq == HTTPREQ_POST_FORM && - /* this header (extended by formdata.c) is sent later */ - checkprefix("Content-Type:", headers->data)) - ; - else if(conn->bits.authneg && - /* while doing auth neg, don't allow the custom length since - we will force length zero then */ - checkprefix("Content-Length", headers->data)) - ; - else if(conn->allocptr.te && - /* when asking for Transfer-Encoding, don't pass on a custom - Connection: */ - checkprefix("Connection", headers->data)) - ; - else { - CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n", - headers->data); - if(result) - return result; - } - } + switch(proxy) { + case HEADER_SERVER: + h[0] = data->set.headers; + break; + case HEADER_PROXY: + h[0] = data->set.headers; + if(data->set.sep_headers) { + h[1] = data->set.proxyheaders; + numlists++; } - else { - ptr = strchr(headers->data, ';'); + break; + case HEADER_CONNECT: + if(data->set.sep_headers) + h[0] = data->set.proxyheaders; + else + h[0] = data->set.headers; + break; + } + + /* loop through one or two lists */ + for(i=0; i < numlists; i++) { + headers = h[i]; + + while(headers) { + ptr = strchr(headers->data, ':'); if(ptr) { + /* we require a colon for this to be a true header */ - ptr++; /* pass the semicolon */ + ptr++; /* pass the colon */ while(*ptr && ISSPACE(*ptr)) ptr++; if(*ptr) { - /* this may be used for something else in the future */ - } - else { - if(*(--ptr) == ';') { - CURLcode result; - - /* send no-value custom header if terminated by semicolon */ - *ptr = ':'; - result = Curl_add_bufferf(req_buffer, "%s\r\n", - headers->data); + /* only send this if the contents was non-blank */ + + if(conn->allocptr.host && + /* a Host: header was sent already, don't pass on any custom Host: + header as that will produce *two* in the same request! */ + checkprefix("Host:", headers->data)) + ; + else if(data->set.httpreq == HTTPREQ_POST_FORM && + /* this header (extended by formdata.c) is sent later */ + checkprefix("Content-Type:", headers->data)) + ; + else if(conn->bits.authneg && + /* while doing auth neg, don't allow the custom length since + we will force length zero then */ + checkprefix("Content-Length", headers->data)) + ; + else if(conn->allocptr.te && + /* when asking for Transfer-Encoding, don't pass on a custom + Connection: */ + checkprefix("Connection", headers->data)) + ; + else { + CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n", + headers->data); if(result) return result; } } } + else { + ptr = strchr(headers->data, ';'); + if(ptr) { + + ptr++; /* pass the semicolon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + + if(*ptr) { + /* this may be used for something else in the future */ + } + else { + if(*(--ptr) == ';') { + CURLcode result; + + /* send no-value custom header if terminated by semicolon */ + *ptr = ':'; + result = Curl_add_bufferf(req_buffer, "%s\r\n", + headers->data); + if(result) + return result; + } + } + } + } + headers = headers->next; } - headers = headers->next; } return CURLE_OK; } -- cgit v1.2.3