seanmonstar / reqwest

An easy and powerful Rust HTTP Client
https://docs.rs/reqwest
Apache License 2.0
9.8k stars 1.1k forks source link

`ClientBuilder` support for `basic_auth` #1822

Closed EstebanBorai closed 4 days ago

EstebanBorai commented 1 year ago

Hi! I would love to have the capability to set basic_auth when building a Client instance using the ClientBuilder. This way every request from a Client would reuse the same Authorization header.

Currently I have a use case for this when I would like to apply such behavior, this PR. I could replace most of this code here:

https://github.com/whizzes/imagekit/pull/5/files#diff-7f93c4e263c4e9ec748f804c7fd04a3b2fde86ffd741fb5516d67e1097bae4c1R35-R43

By being able to do:

  let client = ClientBuilder::new()
             .basic_auth(Some(value), None)
             .build()
             .unwrap();

Thanks in advance!

ducaale commented 1 year ago

One way to approach this is to use a middleware crate like reqwest-middleware, but it would be nice if reqwest had a native solution for this pattern.

Example ```rs // [dependencies] // async-trait = "0.1.68" // reqwest = { version = "0.11.17" } // reqwest-middleware = "0.2.1" // task-local-extensions = "0.1.4" // tokio = { version = "1", features = ["full"] } use reqwest::{Client, Request, RequestBuilder, Response}; use reqwest_middleware::{ClientBuilder, Middleware, Next}; use task_local_extensions::Extensions; struct AuthMiddleware(Client); #[async_trait::async_trait] impl Middleware for AuthMiddleware { async fn handle( &self, req: Request, extensions: &mut Extensions, next: Next<'_>, ) -> reqwest_middleware::Result { let req = RequestBuilder::from_parts(self.0.clone(), req) .basic_auth("user", Some("pass")) .build()?; let resp = next.run(req, extensions).await?; Ok(resp) } } #[tokio::main] async fn main() -> Result<(), Box> { let client = { let client = reqwest::Client::new(); ClientBuilder::new(client.clone()) .with(AuthMiddleware(client.clone())) .build() }; let resp = client .get("https://httpbin.org/get") .send() .await? .text() .await?; println!("{resp}"); Ok(()) } ```

Also, see https://truelayer.com/blog/engineering/adding-middleware-support-to-rust-reqwest/

EstebanBorai commented 1 year ago

One way to approach this is to use a middleware crate like reqwest-middleware, but it would be nice if reqwest had a native solution for this pattern.

Example ```rs // [dependencies] // async-trait = "0.1.68" // reqwest = { version = "0.11.17" } // reqwest-middleware = "0.2.1" // task-local-extensions = "0.1.4" // tokio = { version = "1", features = ["full"] } use reqwest::{Client, Request, RequestBuilder, Response}; use reqwest_middleware::{ClientBuilder, Middleware, Next}; use task_local_extensions::Extensions; struct AuthMiddleware(Client); #[async_trait::async_trait] impl Middleware for AuthMiddleware { async fn handle( &self, req: Request, extensions: &mut Extensions, next: Next<'_>, ) -> reqwest_middleware::Result { let req = RequestBuilder::from_parts(self.0.clone(), req) .basic_auth("user", Some("pass")) .build()?; let resp = next.run(req, extensions).await?; Ok(resp) } } #[tokio::main] async fn main() -> Result<(), Box> { let client = { let client = reqwest::Client::new(); ClientBuilder::new(client.clone()) .with(AuthMiddleware(client.clone())) .build() }; let resp = client .get("https://httpbin.org/get") .send() .await? .text() .await?; println!("{resp}"); Ok(()) } ```

Also, see https://truelayer.com/blog/engineering/adding-middleware-support-to-rust-reqwest/

Yeah looks like a good workaround!

hawkrives commented 6 days ago

Seems like a dup of https://github.com/seanmonstar/reqwest/issues/1383, which has an open MR to add this functionality.

EstebanBorai commented 4 days ago

Seems like a dup of https://github.com/seanmonstar/reqwest/issues/1383, which has an open MR to add this functionality.

Closing in favor of https://github.com/seanmonstar/reqwest/issues/1383