Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't set User-Agent header by default #751

Merged
merged 1 commit into from Dec 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 46 additions & 5 deletions src/async_impl/client.rs
@@ -1,3 +1,4 @@
use std::convert::TryInto;
use std::net::IpAddr;
use std::sync::Arc;
#[cfg(feature = "cookies")]
Expand Down Expand Up @@ -36,8 +37,6 @@ use crate::tls::TlsBackend;
use crate::{Certificate, Identity};
use crate::{IntoUrl, Method, Proxy, StatusCode, Url};

static DEFAULT_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));

/// An asynchronous `Client` to make Requests with.
///
/// The Client has various configuration values to tweak, but the defaults
Expand Down Expand Up @@ -85,6 +84,7 @@ struct Config {
nodelay: bool,
#[cfg(feature = "cookies")]
cookie_store: Option<cookie::CookieStore>,
error: Option<crate::Error>,
}

impl Default for ClientBuilder {
Expand All @@ -99,11 +99,11 @@ impl ClientBuilder {
/// This is the same as `Client::builder()`.
pub fn new() -> ClientBuilder {
let mut headers: HeaderMap<HeaderValue> = HeaderMap::with_capacity(2);
headers.insert(USER_AGENT, HeaderValue::from_static(DEFAULT_USER_AGENT));
headers.insert(ACCEPT, HeaderValue::from_static("*/*"));

ClientBuilder {
config: Config {
error: None,
gzip: cfg!(feature = "gzip"),
headers,
#[cfg(feature = "native-tls")]
Expand Down Expand Up @@ -143,6 +143,11 @@ impl ClientBuilder {
/// cannot load the system configuration.
pub fn build(self) -> crate::Result<Client> {
let config = self.config;

if let Some(err) = config.error {
return Err(err);
}

let mut proxies = config.proxies;
if config.auto_sys_proxy {
proxies.push(Proxy::system());
Expand All @@ -151,8 +156,8 @@ impl ClientBuilder {

let mut connector = {
#[cfg(feature = "__tls")]
fn user_agent(headers: &HeaderMap) -> HeaderValue {
headers[USER_AGENT].clone()
fn user_agent(headers: &HeaderMap) -> Option<HeaderValue> {
headers.get(USER_AGENT).cloned()
}

#[cfg(feature = "__tls")]
Expand Down Expand Up @@ -270,6 +275,42 @@ impl ClientBuilder {

// Higher-level options


/// Sets the `User-Agent` header to be used by this client.
///
/// # Example
///
/// ```rust
/// # async fn doc() -> Result<(), reqwest::Error> {
/// // Name your user agent after your app?
/// static APP_USER_AGENT: &str = concat!(
/// env!("CARGO_PKG_NAME"),
/// "/",
/// env!("CARGO_PKG_VERSION"),
/// );
///
/// let client = reqwest::Client::builder()
/// .user_agent(APP_USER_AGENT)
/// .build()?;
/// let res = client.get("https://www.rust-lang.org").send().await?;
/// # Ok(())
/// # }
/// ```
pub fn user_agent<V>(mut self, value: V) -> ClientBuilder
where
V: TryInto<HeaderValue>,
V::Error: Into<http::Error>,
{
match value.try_into() {
Ok(value) => {
self.config.headers.insert(USER_AGENT, value);
}
Err(e) => {
self.config.error = Some(crate::error::builder(e.into()));
}
};
self
}
/// Sets the default headers for every request.
///
/// # Example
Expand Down
31 changes: 31 additions & 0 deletions src/blocking/client.rs
@@ -1,10 +1,12 @@
use std::convert::TryInto;
use std::fmt;
use std::future::Future;
use std::net::IpAddr;
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use http::header::HeaderValue;
use log::{error, trace};
use tokio::sync::{mpsc, oneshot};

Expand Down Expand Up @@ -85,6 +87,35 @@ impl ClientBuilder {

// Higher-level options


/// Sets the `User-Agent` header to be used by this client.
///
/// # Example
///
/// ```rust
/// # fn doc() -> Result<(), reqwest::Error> {
/// // Name your user agent after your app?
/// static APP_USER_AGENT: &str = concat!(
/// env!("CARGO_PKG_NAME"),
/// "/",
/// env!("CARGO_PKG_VERSION"),
/// );
///
/// let client = reqwest::blocking::Client::builder()
/// .user_agent(APP_USER_AGENT)
/// .build()?;
/// let res = client.get("https://www.rust-lang.org").send()?;
/// # Ok(())
/// # }
/// ```
pub fn user_agent<V>(self, value: V) -> ClientBuilder
where
V: TryInto<HeaderValue>,
V::Error: Into<http::Error>,
{
self.with_inner(move |inner| inner.user_agent(value))
}

/// Sets the default headers for every request.
///
/// # Example
Expand Down
20 changes: 11 additions & 9 deletions src/connect.rs
Expand Up @@ -41,7 +41,7 @@ pub(crate) struct Connector {
#[cfg(feature = "__tls")]
nodelay: bool,
#[cfg(feature = "__tls")]
user_agent: HeaderValue,
user_agent: Option<HeaderValue>,
}

#[derive(Clone)]
Expand Down Expand Up @@ -82,7 +82,7 @@ impl Connector {
pub(crate) fn new_default_tls<T>(
tls: TlsConnectorBuilder,
proxies: Arc<Vec<Proxy>>,
user_agent: HeaderValue,
user_agent: Option<HeaderValue>,
local_addr: T,
nodelay: bool,
) -> crate::Result<Connector>
Expand All @@ -108,7 +108,7 @@ impl Connector {
pub(crate) fn new_rustls_tls<T>(
tls: rustls::ClientConfig,
proxies: Arc<Vec<Proxy>>,
user_agent: HeaderValue,
user_agent: Option<HeaderValue>,
local_addr: T,
nodelay: bool,
) -> crate::Result<Connector>
Expand Down Expand Up @@ -515,7 +515,7 @@ async fn tunnel<T>(
mut conn: T,
host: String,
port: u16,
user_agent: HeaderValue,
user_agent: Option<HeaderValue>,
auth: Option<HeaderValue>,
) -> Result<T, io::Error>
where
Expand All @@ -534,9 +534,11 @@ where


// user-agent
buf.extend_from_slice(b"User-Agent: ");
buf.extend_from_slice(user_agent.as_bytes());
buf.extend_from_slice(b"\r\n");
if let Some(user_agent) = user_agent {
buf.extend_from_slice(b"User-Agent: ");
buf.extend_from_slice(user_agent.as_bytes());
buf.extend_from_slice(b"\r\n");
}


// proxy-authorization
Expand Down Expand Up @@ -888,8 +890,8 @@ mod tests {
}};
}

fn ua() -> http::header::HeaderValue {
http::header::HeaderValue::from_static(TUNNEL_UA)
fn ua() -> Option<http::header::HeaderValue> {
Some(http::header::HeaderValue::from_static(TUNNEL_UA))
}

#[test]
Expand Down
24 changes: 23 additions & 1 deletion tests/client.rs
Expand Up @@ -11,7 +11,7 @@ async fn auto_headers() {
assert_eq!(req.method(), "GET");

assert_eq!(req.headers()["accept"], "*/*");
assert_eq!(req.headers()["user-agent"], DEFAULT_USER_AGENT);
assert_eq!(req.headers().get("user-agent"), None);
if cfg!(feature = "gzip") {
assert_eq!(req.headers()["accept-encoding"], "gzip");
}
Expand All @@ -28,6 +28,28 @@ async fn auto_headers() {
assert_eq!(res.remote_addr(), Some(server.addr()));
}

#[tokio::test]
async fn user_agent() {
let server = server::http(move |req| {
async move {
assert_eq!(req.headers()["user-agent"], "reqwest-test-agent");
http::Response::default()
}
});

let url = format!("http://{}/ua", server.addr());
let res = reqwest::Client::builder()
.user_agent("reqwest-test-agent")
.build()
.expect("client builder")
.get(&url)
.send()
.await
.expect("request");

assert_eq!(res.status(), reqwest::StatusCode::OK);
}

#[tokio::test]
async fn response_text() {
let _ = env_logger::try_init();
Expand Down