use url::Url;
use reqwest::{Client, Response};
use api::request::{ensure_success, ResponseError};
use crypto::b64;
const HEADER_NONCE: &str = "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_raw(HEADER_NONCE)
.ok_or(NonceError::NoNonceHeader)?
.one()
.ok_or(NonceError::MalformedNonce)
.and_then(|line| String::from_utf8(line.to_vec())
.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),
}
}
}