1use reqwest::{
2 blocking::Response,
3 header::{HeaderName, WWW_AUTHENTICATE},
4};
5use thiserror::Error;
6use url::Url;
7
8use crate::api::request::{ensure_success, ResponseError};
9use crate::client::Client;
10use crate::crypto::b64;
11
12const HEADER_NONCE: HeaderName = WWW_AUTHENTICATE;
14
15pub fn request_nonce(client: &Client, url: Url) -> Result<Vec<u8>, NonceError> {
18 let response = client.get(url).send().map_err(|_| NonceError::Request)?;
20
21 ensure_success(&response)?;
23
24 header_nonce(&response)
26}
27
28pub fn header_nonce(response: &Response) -> Result<Vec<u8>, NonceError> {
30 b64::decode(
32 response
33 .headers()
34 .get(HEADER_NONCE)
35 .ok_or(NonceError::NoNonceHeader)?
36 .to_str()
37 .map_err(|_| NonceError::MalformedNonce)?
38 .split_terminator(' ')
39 .nth(1)
40 .ok_or(NonceError::MalformedNonce)?,
41 )
42 .map_err(|_| NonceError::MalformedNonce)
43}
44
45#[derive(Error, Debug)]
46pub enum NonceError {
47 #[error("the file has expired or did never exist")]
50 Expired,
51
52 #[error("failed to request encryption nonce")]
54 Request,
55
56 #[error("bad response from server while requesting encryption nonce")]
59 Response(#[from] ResponseError),
60
61 #[error("missing nonce in server response")]
63 NoNonceHeader,
64
65 #[error("received malformed nonce")]
69 MalformedNonce,
70}