From ef6be35bae1fe501fecd9a2a21eb5d03ddff4243 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 4 Feb 2014 23:37:29 +0100 Subject: [PATCH] CURLOPT_HEADEROPT: added Modified the logic so that CURLOPT_HEADEROPT now controls if PROXYHEADER is actually used or not. --- docs/libcurl/curl_easy_setopt.3 | 60 +++++++++++++++++++------------- docs/libcurl/symbols-in-versions | 1 + include/curl/curl.h | 7 ++++ lib/http.c | 4 +-- lib/url.c | 8 +++++ lib/urldata.h | 1 + tests/data/test1525 | 2 +- tests/libtest/lib1525.c | 3 +- tests/libtest/lib1526.c | 1 + 9 files changed, 59 insertions(+), 28 deletions(-) diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index bda293576..40c5a01c7 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -1515,17 +1515,20 @@ set the User-Agent: header in the http request sent to the remote server. This can be used to fool servers or scripts. You can also set any custom header with \fICURLOPT_HTTPHEADER\fP. .IP CURLOPT_HTTPHEADER -Pass a pointer to a linked list of HTTP headers to pass to the server in your -HTTP request. The linked list should be a fully valid list of \fBstruct -curl_slist\fP structs properly filled in. Use \fIcurl_slist_append(3)\fP to -create the list and \fIcurl_slist_free_all(3)\fP to clean up an entire -list. If you add a header that is otherwise generated and used by libcurl -internally, your added one will be used instead. If you add a header with no -content as in 'Accept:' (no data on the right side of the colon), the -internally used header will get disabled. Thus, using this option you can add -new headers, replace internal headers and remove internal headers. To add a -header with no content (nothing to the right side of the colon), use the -form 'MyHeader;' (note the ending semicolon). +Pass a pointer to a linked list of HTTP headers to pass to the server and/or +proxy in your HTTP request. The same list is used for both host and proxy +requests! + +The linked list should be a fully valid list of \fBstruct curl_slist\fP +structs properly filled in. Use \fIcurl_slist_append(3)\fP to create the list +and \fIcurl_slist_free_all(3)\fP to clean up an entire list. If you add a +header that is otherwise generated and used by libcurl internally, your added +one will be used instead. If you add a header with no content as in 'Accept:' +(no data on the right side of the colon), the internally used header will get +disabled. With this option you can add new headers, replace internal headers +and remove internal headers. To add a header with no content (nothing to the +right side of the colon), use the form 'MyHeader;' (note the ending +semicolon). The headers included in the linked list must not be CRLF-terminated, because curl adds CRLF after each header item. Failure to comply with this will result @@ -1542,26 +1545,35 @@ 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.36.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! +There's an alternative option that sets or replaces headers only for requests +that are sent with CONNECT to a proxy: \fICURLOPT_PROXYHEADER\fP. Use +\fICURLOPT_HEADEROPT\fP to control the behavior. +.IP CURLOPT_HEADEROPT +Pass a long that is a bitmask of options of how to deal with headers. The +available options are: + +CURLHEADER_UNIFIED - keep working as before. This means CURLOPT_HTTPHEADER +headers will be used in requests both to servers and in CONNECT requests. With +this option enabled, \fICURLOPT_PROXYHEADER\fP will not have any effect. + +CURLHEADER_SEPARATE - makes \fICURLOPT_HTTPHEADER\fP headers only get sent to +a host and not to a proxy if CONNECT is being used. It has to be set to make +\fICURLOPT_PROXYHEADER\fP get used. + +This behavior is set per request and an application can alter it between +different invokes if desired. + +(Added in 7.36.0) .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 list 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 headers set with this option is only ever used in requests sent to a proxy +- when there's also a request sent to a host. 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 +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. diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index 925e47923..ecd38b52b 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -370,6 +370,7 @@ CURLOPT_GSSAPI_DELEGATION 7.22.0 CURLOPT_HEADER 7.1 CURLOPT_HEADERDATA 7.10 CURLOPT_HEADERFUNCTION 7.7.2 +CURLOPT_HEADEROPT 7.36.0 CURLOPT_HTTP200ALIASES 7.10.3 CURLOPT_HTTPAUTH 7.10.6 CURLOPT_HTTPGET 7.8.1 diff --git a/include/curl/curl.h b/include/curl/curl.h index efdd2e842..8384191f1 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -754,6 +754,10 @@ typedef enum { CURLFTPMETHOD_LAST /* not an option, never use */ } curl_ftpmethod; +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + /* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ #define CURLPROTO_HTTP (1<<0) #define CURLPROTO_HTTPS (1<<1) @@ -1586,6 +1590,9 @@ typedef enum { struct curl_slist kind */ CINIT(PROXYHEADER, OBJECTPOINT, 228), + /* Pass in a bitmask of "header options" */ + CINIT(HEADEROPT, LONG, 229), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/http.c b/lib/http.c index c0cb4c069..b316fb4c2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -200,7 +200,7 @@ char *Curl_checkProxyheaders(const struct connectdata *conn, size_t thislen = strlen(thisheader); struct SessionHandle *data = conn->data; - for(head = (conn->bits.proxy && data->set.proxyheaders)? + for(head = (conn->bits.proxy && data->set.sep_headers)? data->set.proxyheaders:data->set.headers; head; head=head->next) { if(Curl_raw_nequal(head->data, thisheader, thislen)) @@ -1550,7 +1550,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, { char *ptr; struct curl_slist *headers= - (is_proxy && conn->data->set.proxyheaders)? + (is_proxy && conn->data->set.sep_headers)? conn->data->set.proxyheaders:conn->data->set.headers; while(headers) { diff --git a/lib/url.c b/lib/url.c index 25bb04115..73ae3ec8a 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1081,6 +1081,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, data->set.proxyheaders = va_arg(param, struct curl_slist *); break; + case CURLOPT_HEADEROPT: + /* + * Set header option. + */ + arg = va_arg(param, long); + data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE; + 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 fd13eb981..19c79cfe8 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1467,6 +1467,7 @@ struct UserDefined { 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 sep_headers; /* handle host and proxy headers separately */ bool cookiesession; /* new cookie session? */ bool crlf; /* convert crlf on ftp upload(?) */ struct curl_slist *quote; /* after connection is established */ diff --git a/tests/data/test1525 b/tests/data/test1525 index 13e0d1489..0560d5c1a 100644 --- a/tests/data/test1525 +++ b/tests/data/test1525 @@ -46,7 +46,7 @@ http-proxy lib1525 -CURLOPT_PROXYHEADER: same headers for host and proxy +CURLOPT_PROXYHEADER is ignored CURLHEADER_UNIFIED http://the.old.moo.1525:%HTTPPORT/1525 %HOSTIP:%PROXYPORT diff --git a/tests/libtest/lib1525.c b/tests/libtest/lib1525.c index 45e914e69..957b4295e 100644 --- a/tests/libtest/lib1525.c +++ b/tests/libtest/lib1525.c @@ -71,7 +71,8 @@ int test(char *URL) test_setopt(curl, CURLOPT_URL, URL); test_setopt(curl, CURLOPT_PROXY, libtest_arg2); test_setopt(curl, CURLOPT_HTTPHEADER, hhl); - test_setopt(curl, CURLOPT_PROXYHEADER, NULL); + test_setopt(curl, CURLOPT_PROXYHEADER, hhl); + test_setopt(curl, CURLOPT_HEADEROPT, CURLHEADER_UNIFIED); test_setopt(curl, CURLOPT_POST, 0L); test_setopt(curl, CURLOPT_UPLOAD, 1L); test_setopt(curl, CURLOPT_VERBOSE, 1L); diff --git a/tests/libtest/lib1526.c b/tests/libtest/lib1526.c index e71512854..fb757f592 100644 --- a/tests/libtest/lib1526.c +++ b/tests/libtest/lib1526.c @@ -72,6 +72,7 @@ int test(char *URL) test_setopt(curl, CURLOPT_PROXY, libtest_arg2); test_setopt(curl, CURLOPT_HTTPHEADER, hhl); test_setopt(curl, CURLOPT_PROXYHEADER, phl); + test_setopt(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE); test_setopt(curl, CURLOPT_POST, 0L); test_setopt(curl, CURLOPT_UPLOAD, 1L); test_setopt(curl, CURLOPT_VERBOSE, 1L);