use crate::error::MppError;
use crate::protocol::core::PaymentChallenge;
pub trait Transport: Send + Sync {
type Request;
type Response;
fn name(&self) -> &str;
fn is_payment_required(&self, response: &Self::Response) -> bool;
fn get_challenge(&self, response: &Self::Response) -> Result<PaymentChallenge, MppError>;
fn set_credential(&self, request: Self::Request, credential: &str) -> Self::Request;
}
pub struct HttpTransport;
pub fn http() -> HttpTransport {
HttpTransport
}
impl Transport for HttpTransport {
type Request = reqwest::RequestBuilder;
type Response = reqwest::Response;
fn name(&self) -> &str {
"http"
}
fn is_payment_required(&self, response: &Self::Response) -> bool {
response.status() == reqwest::StatusCode::PAYMENT_REQUIRED
}
fn get_challenge(&self, response: &Self::Response) -> Result<PaymentChallenge, MppError> {
let header = response
.headers()
.get(reqwest::header::WWW_AUTHENTICATE)
.ok_or_else(|| MppError::MissingHeader("WWW-Authenticate".to_string()))?;
let header_str = header.to_str().map_err(|e| {
MppError::MalformedCredential(Some(format!("invalid WWW-Authenticate header: {e}")))
})?;
crate::protocol::core::parse_www_authenticate(header_str)
}
fn set_credential(&self, request: Self::Request, credential: &str) -> Self::Request {
request.header(reqwest::header::AUTHORIZATION, credential)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_http_transport_name() {
let transport = http();
assert_eq!(transport.name(), "http");
}
}