/// A Response represents a response from an HTTP server. /// /// The structure is created from a request and then used to either create (server) or validate /// (client) a `Server-Authentication` header. /// /// Like `Request`, Responses are built with `ResponseBuilders`. /// /// # Examples /// /// See the documentation in the crate root for examples. #[derive(Debug, Clone)] pubstruct Response<'a> {
method: &'a str,
host: &'a str,
port: u16,
path: &'a str,
req_header: &'a Header,
hash: Option<&'a [u8]>,
ext: Option<&'a str>,
}
impl<'a> Response<'a> { /// Create a new Header for this response, based on the given request and request header pubfn make_header(&self, key: &Key) -> Result<Header> { let ts = self.req_header.ts.ok_or(Error::MissingTs)?; let nonce = self.req_header.nonce.as_ref().ok_or(Error::MissingNonce)?; let mac = Mac::new(
MacType::Response,
key,
ts,
nonce, self.method, self.host, self.port, self.path, self.hash, self.ext,
)?;
// Per JS implementation, the Server-Authorization header includes only mac, hash, and ext
Header::new(
None,
None,
None,
Some(mac), self.ext.map(|v| v.to_string()), self.hash.map(|v| v.to_vec()),
None,
None,
)
}
/// Validate a Server-Authorization header. /// /// This checks that the MAC matches and, if a hash has been supplied locally, /// checks that one was provided from the server and that it, too, matches. pubfn validate_header(&self, response_header: &Header, key: &Key) -> bool { // extract required fields, returning early if they are not present let ts = matchself.req_header.ts {
Some(ts) => ts,
None => { returnfalse;
}
}; let nonce = matchself.req_header.nonce {
Some(ref nonce) => nonce,
None => { returnfalse;
}
}; let header_mac = match response_header.mac {
Some(ref mac) => mac,
None => { returnfalse;
}
}; let header_ext = response_header.ext.as_ref().map(|ext| &ext[..]); let header_hash = response_header.hash.as_ref().map(|hash| &hash[..]);
// first verify the MAC match Mac::new(
MacType::Response,
key,
ts,
nonce, self.method, self.host, self.port, self.path,
header_hash,
header_ext,
) {
Ok(calculated_mac) => { if &calculated_mac != header_mac { returnfalse;
}
}
Err(_) => { returnfalse;
}
};
impl<'a> ResponseBuilder<'a> { /// Generate a new Response from a request header. /// /// This is more commonly accessed through `Request::make_response`. pubfn from_request_header(
req_header: &'a Header,
method: &'a str,
host: &'a str,
port: u16,
path: &'a str,
) -> Self {
ResponseBuilder(Response {
method,
host,
port,
path,
req_header,
hash: None,
ext: None,
})
}
/// Set the content hash for the response. /// /// This should always be calculated from the response payload, not copied from a header. pubfn hash<H: Into<Option<&'a [u8]>>>(mut self, hash: H) -> Self { self.0.hash = hash.into(); self
}
/// Set the `ext` Hawk property for the response. /// /// This need only be set on the server; it is ignored in validating responses on the client. pubfn ext<S: Into<Option<&'a str>>>(mut self, ext: S) -> Self { self.0.ext = ext.into(); self
}
/// Get the response from this builder pubfn response(self) -> Response<'a> { self.0
}
}
#[cfg(all(test, any(feature = "use_ring", feature = "use_openssl")))] mod test { usesuper::ResponseBuilder; usecrate::credentials::Key; usecrate::header::Header; usecrate::mac::Mac; use std::time::{Duration, UNIX_EPOCH};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.