use reqwest::{
blocking::Response,
header::{HeaderName, WWW_AUTHENTICATE},
};
use thiserror::Error;
use url::Url;
use crate::api::request::{ensure_success, ResponseError};
use crate::client::Client;
use crate::crypto::b64;
const HEADER_NONCE: HeaderName = WWW_AUTHENTICATE;
pub fn request_nonce(client: &Client, url: Url) -> Result<Vec<u8>, NonceError> {
let response = client.get(url).send().map_err(|_| NonceError::Request)?;
ensure_success(&response)?;
header_nonce(&response)
}
pub fn header_nonce(response: &Response) -> Result<Vec<u8>, NonceError> {
b64::decode(
response
.headers()
.get(HEADER_NONCE)
.ok_or(NonceError::NoNonceHeader)?
.to_str()
.map_err(|_| NonceError::MalformedNonce)?
.split_terminator(' ')
.nth(1)
.ok_or(NonceError::MalformedNonce)?,
)
.map_err(|_| NonceError::MalformedNonce)
}
#[derive(Error, Debug)]
pub enum NonceError {
#[error("the file has expired or did never exist")]
Expired,
#[error("failed to request encryption nonce")]
Request,
#[error("bad response from server while requesting encryption nonce")]
Response(#[from] ResponseError),
#[error("missing nonce in server response")]
NoNonceHeader,
#[error("received malformed nonce")]
MalformedNonce,
}