use reqwest::{Client, Response};
use url::Url;
use api::request::{ensure_success, ResponseError};
use crypto::b64;
use reqwest::header::{HeaderName, WWW_AUTHENTICATE};
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(Fail, Debug)]
pub enum NonceError {
#[fail(display = "the file has expired or did never exist")]
Expired,
#[fail(display = "failed to request encryption nonce")]
Request,
#[fail(display = "bad response from server while requesting encryption nonce")]
Response(#[cause] ResponseError),
#[fail(display = "missing nonce in server response")]
NoNonceHeader,
#[fail(display = "received malformed nonce")]
MalformedNonce,
}
impl From<ResponseError> for NonceError {
fn from(err: ResponseError) -> Self {
match err {
ResponseError::Expired => NonceError::Expired,
err => NonceError::Response(err),
}
}
}