Don't set User-Agent header by default (#751)
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
use std::convert::TryInto;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
#[cfg(feature = "cookies")]
|
#[cfg(feature = "cookies")]
|
||||||
@@ -36,8 +37,6 @@ use crate::tls::TlsBackend;
|
|||||||
use crate::{Certificate, Identity};
|
use crate::{Certificate, Identity};
|
||||||
use crate::{IntoUrl, Method, Proxy, StatusCode, Url};
|
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.
|
/// An asynchronous `Client` to make Requests with.
|
||||||
///
|
///
|
||||||
/// The Client has various configuration values to tweak, but the defaults
|
/// The Client has various configuration values to tweak, but the defaults
|
||||||
@@ -85,6 +84,7 @@ struct Config {
|
|||||||
nodelay: bool,
|
nodelay: bool,
|
||||||
#[cfg(feature = "cookies")]
|
#[cfg(feature = "cookies")]
|
||||||
cookie_store: Option<cookie::CookieStore>,
|
cookie_store: Option<cookie::CookieStore>,
|
||||||
|
error: Option<crate::Error>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ClientBuilder {
|
impl Default for ClientBuilder {
|
||||||
@@ -99,11 +99,11 @@ impl ClientBuilder {
|
|||||||
/// This is the same as `Client::builder()`.
|
/// This is the same as `Client::builder()`.
|
||||||
pub fn new() -> ClientBuilder {
|
pub fn new() -> ClientBuilder {
|
||||||
let mut headers: HeaderMap<HeaderValue> = HeaderMap::with_capacity(2);
|
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("*/*"));
|
headers.insert(ACCEPT, HeaderValue::from_static("*/*"));
|
||||||
|
|
||||||
ClientBuilder {
|
ClientBuilder {
|
||||||
config: Config {
|
config: Config {
|
||||||
|
error: None,
|
||||||
gzip: cfg!(feature = "gzip"),
|
gzip: cfg!(feature = "gzip"),
|
||||||
headers,
|
headers,
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
@@ -143,6 +143,11 @@ impl ClientBuilder {
|
|||||||
/// cannot load the system configuration.
|
/// cannot load the system configuration.
|
||||||
pub fn build(self) -> crate::Result<Client> {
|
pub fn build(self) -> crate::Result<Client> {
|
||||||
let config = self.config;
|
let config = self.config;
|
||||||
|
|
||||||
|
if let Some(err) = config.error {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
|
||||||
let mut proxies = config.proxies;
|
let mut proxies = config.proxies;
|
||||||
if config.auto_sys_proxy {
|
if config.auto_sys_proxy {
|
||||||
proxies.push(Proxy::system());
|
proxies.push(Proxy::system());
|
||||||
@@ -151,8 +156,8 @@ impl ClientBuilder {
|
|||||||
|
|
||||||
let mut connector = {
|
let mut connector = {
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
fn user_agent(headers: &HeaderMap) -> HeaderValue {
|
fn user_agent(headers: &HeaderMap) -> Option<HeaderValue> {
|
||||||
headers[USER_AGENT].clone()
|
headers.get(USER_AGENT).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
@@ -270,6 +275,42 @@ impl ClientBuilder {
|
|||||||
|
|
||||||
// Higher-level options
|
// 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.
|
/// Sets the default headers for every request.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::convert::TryInto;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
@@ -5,6 +6,7 @@ use std::sync::Arc;
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use http::header::HeaderValue;
|
||||||
use log::{error, trace};
|
use log::{error, trace};
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
@@ -85,6 +87,35 @@ impl ClientBuilder {
|
|||||||
|
|
||||||
// Higher-level options
|
// 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.
|
/// Sets the default headers for every request.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ pub(crate) struct Connector {
|
|||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
nodelay: bool,
|
nodelay: bool,
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
user_agent: HeaderValue,
|
user_agent: Option<HeaderValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -82,7 +82,7 @@ impl Connector {
|
|||||||
pub(crate) fn new_default_tls<T>(
|
pub(crate) fn new_default_tls<T>(
|
||||||
tls: TlsConnectorBuilder,
|
tls: TlsConnectorBuilder,
|
||||||
proxies: Arc<Vec<Proxy>>,
|
proxies: Arc<Vec<Proxy>>,
|
||||||
user_agent: HeaderValue,
|
user_agent: Option<HeaderValue>,
|
||||||
local_addr: T,
|
local_addr: T,
|
||||||
nodelay: bool,
|
nodelay: bool,
|
||||||
) -> crate::Result<Connector>
|
) -> crate::Result<Connector>
|
||||||
@@ -108,7 +108,7 @@ impl Connector {
|
|||||||
pub(crate) fn new_rustls_tls<T>(
|
pub(crate) fn new_rustls_tls<T>(
|
||||||
tls: rustls::ClientConfig,
|
tls: rustls::ClientConfig,
|
||||||
proxies: Arc<Vec<Proxy>>,
|
proxies: Arc<Vec<Proxy>>,
|
||||||
user_agent: HeaderValue,
|
user_agent: Option<HeaderValue>,
|
||||||
local_addr: T,
|
local_addr: T,
|
||||||
nodelay: bool,
|
nodelay: bool,
|
||||||
) -> crate::Result<Connector>
|
) -> crate::Result<Connector>
|
||||||
@@ -515,7 +515,7 @@ async fn tunnel<T>(
|
|||||||
mut conn: T,
|
mut conn: T,
|
||||||
host: String,
|
host: String,
|
||||||
port: u16,
|
port: u16,
|
||||||
user_agent: HeaderValue,
|
user_agent: Option<HeaderValue>,
|
||||||
auth: Option<HeaderValue>,
|
auth: Option<HeaderValue>,
|
||||||
) -> Result<T, io::Error>
|
) -> Result<T, io::Error>
|
||||||
where
|
where
|
||||||
@@ -534,9 +534,11 @@ where
|
|||||||
|
|
||||||
|
|
||||||
// user-agent
|
// user-agent
|
||||||
buf.extend_from_slice(b"User-Agent: ");
|
if let Some(user_agent) = user_agent {
|
||||||
buf.extend_from_slice(user_agent.as_bytes());
|
buf.extend_from_slice(b"User-Agent: ");
|
||||||
buf.extend_from_slice(b"\r\n");
|
buf.extend_from_slice(user_agent.as_bytes());
|
||||||
|
buf.extend_from_slice(b"\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// proxy-authorization
|
// proxy-authorization
|
||||||
@@ -888,8 +890,8 @@ mod tests {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ua() -> http::header::HeaderValue {
|
fn ua() -> Option<http::header::HeaderValue> {
|
||||||
http::header::HeaderValue::from_static(TUNNEL_UA)
|
Some(http::header::HeaderValue::from_static(TUNNEL_UA))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ async fn auto_headers() {
|
|||||||
assert_eq!(req.method(), "GET");
|
assert_eq!(req.method(), "GET");
|
||||||
|
|
||||||
assert_eq!(req.headers()["accept"], "*/*");
|
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") {
|
if cfg!(feature = "gzip") {
|
||||||
assert_eq!(req.headers()["accept-encoding"], "gzip");
|
assert_eq!(req.headers()["accept-encoding"], "gzip");
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,28 @@ async fn auto_headers() {
|
|||||||
assert_eq!(res.remote_addr(), Some(server.addr()));
|
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]
|
#[tokio::test]
|
||||||
async fn response_text() {
|
async fn response_text() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|||||||
Reference in New Issue
Block a user