CURLOPT_PROXYHEADER: set headers for proxy-only

Includes docs and new test cases: 1525, 1526 and 1527

Co-written-by: Vijay Panghal
This commit is contained in:
Daniel Stenberg 2014-01-31 08:10:07 +01:00
parent 42937f87e6
commit ac887eedbc
17 changed files with 667 additions and 48 deletions

View File

@ -1541,6 +1541,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.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!
.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 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.36.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

View File

@ -439,6 +439,7 @@ CURLOPT_PROGRESSFUNCTION 7.1 7.32.0
CURLOPT_PROTOCOLS 7.19.4
CURLOPT_PROXY 7.1
CURLOPT_PROXYAUTH 7.10.7
CURLOPT_PROXYHEADER 7.36.0
CURLOPT_PROXYPASSWORD 7.19.1
CURLOPT_PROXYPORT 7.1
CURLOPT_PROXYTYPE 7.10

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@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
@ -903,7 +903,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 */
@ -1581,6 +1582,10 @@ typedef enum {
* Expect: 100-continue header before sending the data anyway. */
CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
/* This points to a linked list of headers used for proxy requests only,
struct curl_slist kind */
CINIT(PROXYHEADER, OBJECTPOINT, 228),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;

View File

@ -169,12 +169,40 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
*
* 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(const struct connectdata *conn,
const char *thisheader)
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
struct SessionHandle *data = conn->data;
for(head = data->set.headers; head; head=head->next) {
for(head = data->set.headers;head; head=head->next) {
if(Curl_raw_nequal(head->data, thisheader, thislen))
return head->data;
}
return NULL;
}
/*
* checkProxyHeaders() checks the linked list of custom proxy headers
* if proxy headers are not available, then it will lookup into http header
* link list
*
* 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.
*
*/
char *Curl_checkProxyheaders(const struct connectdata *conn,
const char *thisheader)
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
struct SessionHandle *data = conn->data;
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;
}
@ -584,9 +612,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_checkProxyheaders(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)
@ -1501,7 +1529,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");
@ -1517,10 +1545,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, ':');
@ -1736,7 +1767,7 @@ 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;
}
@ -1757,7 +1788,7 @@ 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);
if(!conn->allocptr.ref)
return CURLE_OUT_OF_MEMORY;
@ -1765,10 +1796,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
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 =
@ -1780,13 +1811,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);
@ -1804,7 +1836,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* In HTTP2 forbids Transfer-Encoding: chunked */
ptr = NULL;
else {
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 =
@ -1838,7 +1870,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)
@ -1983,13 +2015,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) ||
@ -2069,7 +2101,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);
@ -2077,7 +2109,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)
@ -2179,7 +2211,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_checkProxyheaders(conn, "Proxy-Connection:"))?
"Proxy-Connection: Keep-Alive\r\n":"",
te
);
@ -2264,7 +2296,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;
@ -2314,7 +2346,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: %" CURL_FORMAT_CURL_OFF_T
@ -2386,7 +2418,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: %" CURL_FORMAT_CURL_OFF_T
@ -2438,7 +2470,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((postsize != -1) && !data->req.upload_chunky &&
!Curl_checkheaders(data, "Content-Length:")) {
!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,
@ -2448,7 +2480,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
}
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");
@ -2460,7 +2492,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");

View File

@ -39,9 +39,13 @@ extern const struct Curl_handler Curl_handler_https;
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(const struct connectdata *conn,
const char *thisheader);
char *Curl_copy_header_value(const char *header);
char *Curl_checkProxyheaders(const struct connectdata *conn,
const char *thisheader);
/* ------------------------------------------------------------------------- */
/*
* The add_buffer series of functions are used to build one large memory chunk
@ -67,7 +71,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);

View File

@ -165,7 +165,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
if(!Curl_checkheaders(data, "Host:")) {
if(!Curl_checkProxyheaders(conn, "Host:")) {
host = aprintf("Host: %s\r\n", hostheader);
if(!host) {
free(hostheader);
@ -173,10 +173,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
}
if(!Curl_checkheaders(data, "Proxy-Connection:"))
if(!Curl_checkProxyheaders(conn, "Proxy-Connection:"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n";
if(!Curl_checkheaders(data, "User-Agent:") &&
if(!Curl_checkProxyheaders(conn, "User-Agent:") &&
data->set.str[STRING_USERAGENT])
useragent = conn->allocptr.uagent;
@ -200,7 +200,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 */

View File

@ -341,7 +341,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]) {
@ -365,11 +365,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 =
@ -386,18 +386,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;
@ -414,7 +414,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;
@ -424,11 +424,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;
}
@ -484,7 +484,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;
@ -507,7 +507,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: %" CURL_FORMAT_CURL_OFF_T"\r\n",
(data->set.upload ? putsize : postsize));
@ -517,7 +517,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)
@ -526,7 +526,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)

View File

@ -1067,6 +1067,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

View File

@ -1465,6 +1465,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(?) */

View File

@ -127,6 +127,8 @@ test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \
test1516 \
\
test1525 test1526 test1527 \
\
test1900 test1901 test1902 test1903 \
\
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \

76
tests/data/test1525 Normal file
View File

@ -0,0 +1,76 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
HTTP CONNECT
HTTP proxy
proxytunnel
CURLOPT_PROXYHEADER
</keywords>
</info>
# Server-side
<reply>
<connect>
HTTP/1.1 200 OK
Content-Length: 17
</connect>
<data>
HTTP/1.1 200 OK swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
</data>
<datacheck>
HTTP/1.1 200 OK
Content-Length: 17
HTTP/1.1 200 OK swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
</datacheck>
</reply>
# Client-side
<client>
<server>
http
http-proxy
</server>
<tool>
lib1525
</tool>
<name>
CURLOPT_PROXYHEADER: same headers for host and proxy
</name>
<command>
http://the.old.moo.1525:%HTTPPORT/1525 %HOSTIP:%PROXYPORT
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<proxy>
CONNECT the.old.moo.1525:%HTTPPORT HTTP/1.1
Host: the.old.moo.1525:%HTTPPORT
Proxy-Connection: Keep-Alive
User-Agent: Http Agent
</proxy>
<protocol>
PUT /1525 HTTP/1.1
Host: the.old.moo.1525:%HTTPPORT
Accept: */*
User-Agent: Http Agent
Content-Length: 13
Expect: 100-continue
Hello Cloud!
</protocol>
</verify>
</testcase>

76
tests/data/test1526 Normal file
View File

@ -0,0 +1,76 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
HTTP CONNECT
HTTP proxy
proxytunnel
CURLOPT_PROXYHEADER
</keywords>
</info>
# Server-side
<reply>
<connect>
HTTP/1.1 200 OK
Server: present
</connect>
<data>
HTTP/1.1 200 OK swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
</data>
<datacheck>
HTTP/1.1 200 OK
Server: present
HTTP/1.1 200 OK swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
</datacheck>
</reply>
# Client-side
<client>
<server>
http
http-proxy
</server>
<tool>
lib1526
</tool>
<name>
CURLOPT_PROXYHEADER: separate host/proxy headers
</name>
<command>
http://the.old.moo.1526:%HTTPPORT/1526 %HOSTIP:%PROXYPORT
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<proxy>
CONNECT the.old.moo.1526:%HTTPPORT HTTP/1.1
Host: the.old.moo.1526:%HTTPPORT
Proxy-Connection: Keep-Alive
User-Agent: Proxy Agent
</proxy>
<protocol>
PUT /1526 HTTP/1.1
Host: the.old.moo.1526:%HTTPPORT
Accept: */*
User-Agent: Http Agent
Content-Length: 13
Expect: 100-continue
Hello Cloud!
</protocol>
</verify>
</testcase>

76
tests/data/test1527 Normal file
View File

@ -0,0 +1,76 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
HTTP CONNECT
HTTP proxy
proxytunnel
</keywords>
</info>
# Server-side
<reply>
<connect>
HTTP/1.1 200 OK
We-are: good
</connect>
<data>
HTTP/1.1 200 OK swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
</data>
<datacheck>
HTTP/1.1 200 OK
We-are: good
HTTP/1.1 200 OK swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
</datacheck>
</reply>
# Client-side
<client>
<server>
http
http-proxy
</server>
<tool>
lib1527
</tool>
<name>
Check same headers are generated without CURLOPT_PROXYHEADER
</name>
<command>
http://the.old.moo.1527:%HTTPPORT/1527 %HOSTIP:%PROXYPORT
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<proxy>
CONNECT the.old.moo.1527:%HTTPPORT HTTP/1.1
Host: the.old.moo.1527:%HTTPPORT
Proxy-Connection: Keep-Alive
User-Agent: Http Agent
Expect: 100-continue
</proxy>
<protocol>
PUT /1527 HTTP/1.1
Host: the.old.moo.1527:%HTTPPORT
Accept: */*
User-Agent: Http Agent
Expect: 100-continue
Content-Length: 13
Hello Cloud!
</protocol>
</verify>
</testcase>

View File

@ -22,6 +22,8 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \
lib583 lib585 lib586 lib587 lib590 lib591 lib597 lib598 lib599 \
lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 \
lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515 \
lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515 \
lib1525 lib1526 lib1527 \
lib1900 \
lib2033
@ -353,7 +355,19 @@ lib1514_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1514
lib1515_SOURCES = lib1515.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1515_LDADD = $(TESTUTIL_LIBS)
lib1515_CPPFLAGS = $(AM_CPPFLAGS)
lib1515_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1515
lib1525_SOURCES = lib1525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1525_LDADD = $(TESTUTIL_LIBS)
lib1525_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1525
lib1526_SOURCES = lib1526.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1526_LDADD = $(TESTUTIL_LIBS)
lib1526_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1526
lib1527_SOURCES = lib1527.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1527_LDADD = $(TESTUTIL_LIBS)
lib1527_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1527
lib1900_SOURCES = lib1900.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1900_LDADD = $(TESTUTIL_LIBS)

96
tests/libtest/lib1525.c Normal file
View File

@ -0,0 +1,96 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2014, Vijay Panghal, <vpanghal@maginatics.com>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/*
* This unit test PUT http data over proxy. Proxy header will be different
* from server http header
*/
#include "test.h"
#include "memdebug.h"
static char data [] = "Hello Cloud!\n";
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t amount = nmemb * size; /* Total bytes curl wants */
if (amount < strlen(data)) {
return strlen(data);
}
(void)stream;
memcpy(ptr, data, strlen(data));
return strlen(data);
}
int test(char *URL)
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
/* http and proxy header list*/
struct curl_slist *hhl = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if((curl = curl_easy_init()) == NULL) {
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
hhl = curl_slist_append(hhl, "User-Agent: Http Agent");
if (!hhl) {
goto test_cleanup;
}
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_POST, 0L);
test_setopt(curl, CURLOPT_UPLOAD, 1L);
test_setopt(curl, CURLOPT_VERBOSE, 1L);
test_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
test_setopt(curl, CURLOPT_HEADER, 1L);
test_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
test_setopt(curl, CURLOPT_READFUNCTION, read_callback);
test_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L);
test_setopt(curl, CURLOPT_INFILESIZE, strlen(data));
res = curl_easy_perform(curl);
test_cleanup:
curl_easy_cleanup(curl);
curl_slist_free_all(hhl);
curl_global_cleanup();
return (int)res;
}

99
tests/libtest/lib1526.c Normal file
View File

@ -0,0 +1,99 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2014, Vijay Panghal, <vpanghal@maginatics.com>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/*
* This unit test PUT http data over proxy. Proxy header will be different
* from server http header
*/
#include "test.h"
#include "memdebug.h"
static char data [] = "Hello Cloud!\n";
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t amount = nmemb * size; /* Total bytes curl wants */
if (amount < strlen(data)) {
return strlen(data);
}
(void)stream;
memcpy(ptr, data, strlen(data));
return strlen(data);
}
int test(char *URL)
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
/* http and proxy header list*/
struct curl_slist *hhl = NULL, *phl = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if((curl = curl_easy_init()) == NULL) {
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
hhl = curl_slist_append(hhl, "User-Agent: Http Agent");
phl = curl_slist_append(phl, "User-Agent: Proxy Agent");
phl = curl_slist_append(phl, "Expect:");
if (!hhl || !phl) {
goto test_cleanup;
}
test_setopt(curl, CURLOPT_URL, URL);
test_setopt(curl, CURLOPT_PROXY, libtest_arg2);
test_setopt(curl, CURLOPT_HTTPHEADER, hhl);
test_setopt(curl, CURLOPT_PROXYHEADER, phl);
test_setopt(curl, CURLOPT_POST, 0L);
test_setopt(curl, CURLOPT_UPLOAD, 1L);
test_setopt(curl, CURLOPT_VERBOSE, 1L);
test_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
test_setopt(curl, CURLOPT_HEADER, 1L);
test_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
test_setopt(curl, CURLOPT_READFUNCTION, read_callback);
test_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L);
test_setopt(curl, CURLOPT_INFILESIZE, strlen(data));
res = curl_easy_perform(curl);
test_cleanup:
curl_easy_cleanup(curl);
curl_slist_free_all(hhl);
curl_slist_free_all(phl);
curl_global_cleanup();
return (int)res;
}

95
tests/libtest/lib1527.c Normal file
View File

@ -0,0 +1,95 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2014, Vijay Panghal, <vpanghal@maginatics.com>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/*
* This unit test PUT http data over proxy. Same http header will be generated
* for server and proxy
*/
#include "test.h"
#include "memdebug.h"
static char data [] = "Hello Cloud!\n";
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t amount = nmemb * size; /* Total bytes curl wants */
if (amount < strlen(data)) {
return strlen(data);
}
(void)stream;
memcpy(ptr, data, strlen(data));
return strlen(data);
}
int test(char *URL)
{
CURL *curl = NULL;
CURLcode res = CURLE_FAILED_INIT;
/* http header list*/
struct curl_slist *hhl = NULL;
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
return TEST_ERR_MAJOR_BAD;
}
if((curl = curl_easy_init()) == NULL) {
fprintf(stderr, "curl_easy_init() failed\n");
curl_global_cleanup();
return TEST_ERR_MAJOR_BAD;
}
hhl = curl_slist_append(hhl, "User-Agent: Http Agent");
hhl = curl_slist_append(hhl, "Expect: 100-continue");
if (!hhl) {
goto test_cleanup;
}
test_setopt(curl, CURLOPT_URL, URL);
test_setopt(curl, CURLOPT_PROXY, libtest_arg2);
test_setopt(curl, CURLOPT_HTTPHEADER, hhl);
test_setopt(curl, CURLOPT_POST, 0L);
test_setopt(curl, CURLOPT_UPLOAD, 1L);
test_setopt(curl, CURLOPT_VERBOSE, 1L);
test_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
test_setopt(curl, CURLOPT_HEADER, 1L);
test_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
test_setopt(curl, CURLOPT_READFUNCTION, read_callback);
test_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L);
test_setopt(curl, CURLOPT_INFILESIZE, strlen(data));
res = curl_easy_perform(curl);
test_cleanup:
curl_easy_cleanup(curl);
curl_slist_free_all(hhl);
curl_global_cleanup();
return (int)res;
}