mirror of
https://github.com/sigoden/dufs.git
synced 2026-04-09 00:59:02 +03:00
refactor: digest_auth related tests (#372)
This commit is contained in:
91
tests/digest_auth_util.rs
Normal file
91
tests/digest_auth_util.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
/// Refs https://github.dev/maoertel/diqwest/blob/main/src/blocking.rs
|
||||
use anyhow::{anyhow, Result};
|
||||
use digest_auth::{AuthContext, AuthorizationHeader, HttpMethod};
|
||||
use hyper::{header::AUTHORIZATION, HeaderMap, StatusCode};
|
||||
use reqwest::blocking::{RequestBuilder, Response};
|
||||
use url::Position;
|
||||
|
||||
pub fn send_with_digest_auth(
|
||||
request_builder: RequestBuilder,
|
||||
username: &str,
|
||||
password: &str,
|
||||
) -> Result<Response> {
|
||||
let first_response = try_clone_request_builder(&request_builder)?.send()?;
|
||||
match first_response.status() {
|
||||
StatusCode::UNAUTHORIZED => {
|
||||
try_digest_auth(request_builder, first_response, username, password)
|
||||
}
|
||||
_ => Ok(first_response),
|
||||
}
|
||||
}
|
||||
|
||||
fn try_digest_auth(
|
||||
request_builder: RequestBuilder,
|
||||
first_response: Response,
|
||||
username: &str,
|
||||
password: &str,
|
||||
) -> Result<Response> {
|
||||
if let Some(answer) = get_answer(
|
||||
&request_builder,
|
||||
first_response.headers(),
|
||||
username,
|
||||
password,
|
||||
)? {
|
||||
return Ok(request_builder
|
||||
.header(AUTHORIZATION, answer.to_header_string())
|
||||
.send()?);
|
||||
};
|
||||
|
||||
Ok(first_response)
|
||||
}
|
||||
|
||||
fn try_clone_request_builder(request_builder: &RequestBuilder) -> Result<RequestBuilder> {
|
||||
request_builder
|
||||
.try_clone()
|
||||
.ok_or_else(|| anyhow!("Request body must not be a stream"))
|
||||
}
|
||||
|
||||
fn get_answer(
|
||||
request_builder: &RequestBuilder,
|
||||
first_response: &HeaderMap,
|
||||
username: &str,
|
||||
password: &str,
|
||||
) -> Result<Option<AuthorizationHeader>> {
|
||||
let answer = calculate_answer(request_builder, first_response, username, password);
|
||||
match answer {
|
||||
Ok(answer) => Ok(Some(answer)),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_answer(
|
||||
request_builder: &RequestBuilder,
|
||||
headers: &HeaderMap,
|
||||
username: &str,
|
||||
password: &str,
|
||||
) -> Result<AuthorizationHeader> {
|
||||
let request = try_clone_request_builder(request_builder)?.build()?;
|
||||
let path = &request.url()[Position::AfterPort..];
|
||||
let method = HttpMethod::from(request.method().as_str());
|
||||
let body = request.body().and_then(|b| b.as_bytes());
|
||||
|
||||
parse_digest_auth_header(headers, path, method, body, username, password)
|
||||
}
|
||||
|
||||
fn parse_digest_auth_header(
|
||||
header: &HeaderMap,
|
||||
path: &str,
|
||||
method: HttpMethod,
|
||||
body: Option<&[u8]>,
|
||||
username: &str,
|
||||
password: &str,
|
||||
) -> Result<AuthorizationHeader> {
|
||||
let www_auth = header
|
||||
.get("www-authenticate")
|
||||
.ok_or_else(|| anyhow!("The header 'www-authenticate' is missing."))?
|
||||
.to_str()?;
|
||||
let context = AuthContext::new_with_method(username, password, path, body, method);
|
||||
let mut prompt = digest_auth::parse(www_auth)?;
|
||||
|
||||
Ok(prompt.respond(&context)?)
|
||||
}
|
||||
Reference in New Issue
Block a user