mod config;
mod connection;
mod status;
use std::str;
use self::connection::HttpConnection;
use super::{Connection, ConnectionError, ConnectionErrorKind::ResponseError, Connector};
use crate::serial_number::SerialNumber;
pub use self::{config::HttpConfig, status::ConnectorStatus};
pub const USER_AGENT: &str = concat!("yubihsm.rs ", env!("CARGO_PKG_VERSION"));
pub const MAX_RESPONSE_SIZE: usize = 4096;
const CONNECTOR_STATUS_PATH: &str = "/connector/status";
#[derive(Clone, Default, Debug)]
pub struct HttpConnector(HttpConfig);
impl HttpConnector {
pub fn create(config: &HttpConfig) -> Result<Self, ConnectionError> {
Ok(HttpConnector(config.clone()))
}
pub fn status(&self) -> Result<ConnectorStatus, ConnectionError> {
let http_response = HttpConnection::open(&self.0)?.get(CONNECTOR_STATUS_PATH)?;
ConnectorStatus::parse(str::from_utf8(&http_response)?)
}
}
impl Connector for HttpConnector {
fn connect(&self) -> Result<Box<dyn Connection>, ConnectionError> {
Ok(Box::new(HttpConnection::open(&self.0)?))
}
fn healthcheck(&self) -> Result<(), ConnectionError> {
let status = self.status()?;
if status.message == self::status::CONNECTOR_STATUS_OK {
Ok(())
} else {
fail!(
ResponseError,
"yubihsm-connector returned unhealthy /connector/status: {}",
&status.message
);
}
}
fn serial_number(&self) -> Result<SerialNumber, ConnectionError> {
self.status()?.serial_number.ok_or_else(|| {
err!(
ResponseError,
"no serial number in yubihsm-connector /connector/status"
)
})
}
}
impl Into<Box<dyn Connector>> for HttpConnector {
fn into(self) -> Box<dyn Connector> {
Box::new(self)
}
}