use std::sync::Arc;
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper_util::rt::TokioIo;
use tokio::net::TcpListener;
use tokio_rustls::TlsAcceptor;
use dynomite::embed::Datastore;
use crate::error::RiakError;
pub mod content_type;
pub mod object;
pub mod routes;
#[cfg(feature = "search")]
pub mod search;
pub use crate::proto::http::content_type::{select_codec, SUPPORTED_CONTENT_TYPES};
#[cfg(feature = "search")]
pub use crate::proto::http::search::SearchState;
pub async fn serve_http(
listener: TcpListener,
datastore: Arc<dyn Datastore>,
) -> Result<(), RiakError> {
serve_http_ctx(listener, routes::RouteCtx::new(datastore)).await
}
pub async fn serve_http_with_routing(
listener: TcpListener,
datastore: Arc<dyn Datastore>,
hooks: crate::router::RoutingHooks,
) -> Result<(), RiakError> {
serve_http_ctx(listener, routes::RouteCtx::new(datastore).set_hooks(hooks)).await
}
pub async fn serve_http_tls_with_routing(
listener: TcpListener,
datastore: Arc<dyn Datastore>,
hooks: crate::router::RoutingHooks,
acceptor: tokio_rustls::TlsAcceptor,
) -> Result<(), RiakError> {
serve_http_tls_ctx(
listener,
routes::RouteCtx::new(datastore).set_hooks(hooks),
acceptor,
)
.await
}
#[cfg(feature = "search")]
pub async fn serve_http_with_search(
listener: TcpListener,
datastore: Arc<dyn Datastore>,
registry: Arc<dynomite_search::VectorRegistry>,
) -> Result<(), RiakError> {
let ctx = routes::RouteCtx::with_search(datastore, Arc::new(SearchState::new(registry)));
serve_http_ctx(listener, ctx).await
}
#[cfg(feature = "wasm")]
pub async fn serve_http_with_wasm(
listener: TcpListener,
datastore: Arc<dyn Datastore>,
wasm: Arc<crate::mapreduce::wasm::WasmModuleStore>,
) -> Result<(), RiakError> {
let ctx = routes::RouteCtx::with_wasm(datastore, wasm);
serve_http_ctx(listener, ctx).await
}
#[cfg(all(feature = "search", feature = "wasm"))]
pub async fn serve_http_with_search_and_wasm(
listener: TcpListener,
datastore: Arc<dyn Datastore>,
registry: Arc<dynomite_search::VectorRegistry>,
wasm: Arc<crate::mapreduce::wasm::WasmModuleStore>,
) -> Result<(), RiakError> {
let ctx = routes::RouteCtx::with_search(datastore, Arc::new(SearchState::new(registry)))
.set_wasm(wasm);
serve_http_ctx(listener, ctx).await
}
async fn serve_http_ctx(listener: TcpListener, ctx: routes::RouteCtx) -> Result<(), RiakError> {
loop {
let (sock, peer) = listener.accept().await?;
let ctx = ctx.clone();
let io = TokioIo::new(sock);
tokio::spawn(async move {
let svc = service_fn(move |req| {
let ctx = ctx.clone();
async move {
let resp = routes::dispatch(req, ctx).await;
Ok::<_, std::convert::Infallible>(resp)
}
});
if let Err(e) = http1::Builder::new().serve_connection(io, svc).await {
tracing::warn!(%peer, error = %e, "riak http connection ended with error");
}
});
}
}
pub async fn serve_http_tls(
listener: TcpListener,
datastore: Arc<dyn Datastore>,
acceptor: TlsAcceptor,
) -> Result<(), RiakError> {
serve_http_tls_ctx(listener, routes::RouteCtx::new(datastore), acceptor).await
}
#[cfg(feature = "search")]
pub async fn serve_http_tls_with_search(
listener: TcpListener,
datastore: Arc<dyn Datastore>,
registry: Arc<dynomite_search::VectorRegistry>,
acceptor: TlsAcceptor,
) -> Result<(), RiakError> {
let ctx = routes::RouteCtx::with_search(datastore, Arc::new(SearchState::new(registry)));
serve_http_tls_ctx(listener, ctx, acceptor).await
}
#[cfg(feature = "wasm")]
pub async fn serve_http_tls_with_wasm(
listener: TcpListener,
datastore: Arc<dyn Datastore>,
wasm: Arc<crate::mapreduce::wasm::WasmModuleStore>,
acceptor: TlsAcceptor,
) -> Result<(), RiakError> {
let ctx = routes::RouteCtx::with_wasm(datastore, wasm);
serve_http_tls_ctx(listener, ctx, acceptor).await
}
#[cfg(all(feature = "search", feature = "wasm"))]
pub async fn serve_http_tls_with_search_and_wasm(
listener: TcpListener,
datastore: Arc<dyn Datastore>,
registry: Arc<dynomite_search::VectorRegistry>,
wasm: Arc<crate::mapreduce::wasm::WasmModuleStore>,
acceptor: TlsAcceptor,
) -> Result<(), RiakError> {
let ctx = routes::RouteCtx::with_search(datastore, Arc::new(SearchState::new(registry)))
.set_wasm(wasm);
serve_http_tls_ctx(listener, ctx, acceptor).await
}
async fn serve_http_tls_ctx(
listener: TcpListener,
ctx: routes::RouteCtx,
acceptor: TlsAcceptor,
) -> Result<(), RiakError> {
loop {
let (sock, peer) = listener.accept().await?;
let ctx = ctx.clone();
let acc = acceptor.clone();
tokio::spawn(async move {
let tls = match acc.accept(sock).await {
Ok(s) => s,
Err(e) => {
tracing::warn!(%peer, error = %e, "riak http tls handshake failed");
return;
}
};
let io = TokioIo::new(tls);
let svc = service_fn(move |req| {
let ctx = ctx.clone();
async move {
let resp = routes::dispatch(req, ctx).await;
Ok::<_, std::convert::Infallible>(resp)
}
});
if let Err(e) = http1::Builder::new().serve_connection(io, svc).await {
tracing::warn!(%peer, error = %e, "riak http tls connection ended with error");
}
});
}
}