Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions curl-sys/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@ pub const CURLPROXY_SOCKS5: curl_proxytype = 5;
pub const CURLPROXY_SOCKS4A: curl_proxytype = 6;
pub const CURLPROXY_SOCKS5_HOSTNAME: curl_proxytype = 7;

pub const CURLHEADER_UNIFIED: c_long = 0;
pub const CURLHEADER_SEPARATE: c_long = 1 << 0;

pub const CURLAUTH_NONE: c_ulong = 0;
pub const CURLAUTH_BASIC: c_ulong = 1 << 0;
pub const CURLAUTH_DIGEST: c_ulong = 1 << 1;
Expand Down Expand Up @@ -595,6 +598,7 @@ pub const CURLOPT_SSL_OPTIONS: CURLoption = CURLOPTTYPE_LONG + 216;
// pub const CURLOPT_LOGIN_OPTIONS: CURLoption = CURLOPTTYPE_OBJECTPOINT + 224;
pub const CURLOPT_EXPECT_100_TIMEOUT_MS: CURLoption = CURLOPTTYPE_LONG + 227;
pub const CURLOPT_PROXYHEADER: CURLoption = CURLOPTTYPE_OBJECTPOINT + 228;
pub const CURLOPT_HEADEROPT: CURLoption = CURLOPTTYPE_LONG + 229;
pub const CURLOPT_PINNEDPUBLICKEY: CURLoption = CURLOPTTYPE_OBJECTPOINT + 230;
pub const CURLOPT_UNIX_SOCKET_PATH: CURLoption = CURLOPTTYPE_OBJECTPOINT + 231;
pub const CURLOPT_PATH_AS_IS: CURLoption = CURLOPTTYPE_LONG + 234;
Expand Down
5 changes: 5 additions & 0 deletions src/easy/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,11 @@ impl Easy {
self.inner.proxy_headers(list)
}

/// Same as [`Easy2::proxy_headers_separate`](struct.Easy2.html#method.proxy_headers_separate)
pub fn proxy_headers_separate(&mut self, separate: bool) -> Result<(), Error> {
self.inner.proxy_headers_separate(separate)
}

/// Same as [`Easy2::cookie`](struct.Easy2.html#method.cookie)
pub fn cookie(&mut self, cookie: &str) -> Result<(), Error> {
self.inner.cookie(cookie)
Expand Down
24 changes: 23 additions & 1 deletion src/easy/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1598,7 +1598,9 @@ impl<H> Easy2<H> {

/// Add some headers to send to the HTTP proxy.
///
/// This function is essentially the same as `http_headers`.
/// This function is essentially the same as `http_headers`, but libcurl
/// only uses the list once [`proxy_headers_separate`](Easy2::proxy_headers_separate)
/// is on.
///
/// By default this option is not set and corresponds to
/// `CURLOPT_PROXYHEADER`
Expand All @@ -1608,6 +1610,26 @@ impl<H> Easy2<H> {
self.setopt_ptr(curl_sys::CURLOPT_PROXYHEADER, ptr as *const _)
}

/// Keep the headers for the proxy apart from the headers for the server.
///
/// Off, libcurl's default, the `http_headers` list is also sent to the
/// proxy in a `CONNECT` request, which hands an `Authorization` or
/// `Cookie` header meant for the server to the proxy, and the
/// `proxy_headers` list is ignored. On, `http_headers` go only to the
/// server and `proxy_headers` only to the proxy; a request that is not
/// a `CONNECT` (plain `http://` through a proxy) gets both lists.
///
/// By default this option is `false` and corresponds to
/// `CURLOPT_HEADEROPT` with `CURLHEADER_SEPARATE`.
pub fn proxy_headers_separate(&mut self, separate: bool) -> Result<(), Error> {
let mode = if separate {
curl_sys::CURLHEADER_SEPARATE
} else {
curl_sys::CURLHEADER_UNIFIED
};
self.setopt_long(curl_sys::CURLOPT_HEADEROPT, mode)
}

/// Set the contents of the HTTP Cookie header.
///
/// Pass a string of the form `name=contents` for one cookie value or
Expand Down
34 changes: 34 additions & 0 deletions tests/easy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1035,3 +1035,37 @@ fn test_timeout() {
.unwrap()
);
}

#[test]
fn proxy_headers_need_separate_mode() {
// the server plays a plain-http proxy, which gets both lists once the
// headers are kept separate and only the server list before
for (separate, expect_proxy_header) in [(false, false), (true, true)] {
let s = Server::new();
let mut expected = String::from(
"\
GET http://origin.invalid/ HTTP/1.1\r\n\
Host: origin.invalid\r\n\
Accept: */*\r\n\
X-Server: 1\r\n",
);
if expect_proxy_header {
expected.push_str("X-Proxy: 1\r\n");
}
expected.push_str("\r\n");
s.receive(&expected);
s.send("HTTP/1.1 200 OK\r\n\r\n");

let mut handle = handle();
t!(handle.url("http://origin.invalid/"));
t!(handle.proxy(&s.url("")));
let mut server_headers = List::new();
t!(server_headers.append("X-Server: 1"));
t!(handle.http_headers(server_headers));
let mut proxy_headers = List::new();
t!(proxy_headers.append("X-Proxy: 1"));
t!(handle.proxy_headers(proxy_headers));
t!(handle.proxy_headers_separate(separate));
t!(handle.perform());
}
}
Loading