Expand description
Hyper adaptor
Implements hyper::service::Service
for StaticFiles
allowing to use it to serve http connections
Usage
ⓘ
use hyper::server::conn::http1;
use tokio::net::TcpListener;
use pin_project_lite::pin_project;
use http_fs::config::{self, StaticFileConfig, TokioWorker};
use http_fs::StaticFiles;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::path::Path;
use core::task;
use core::pin::Pin;
#[derive(Clone)]
pub struct DirectoryConfig;
impl StaticFileConfig for DirectoryConfig {
type FileService = config::DefaultConfig;
type DirService = config::DefaultConfig;
fn handle_directory(&self, _path: &Path) -> bool {
true
}
}
//Fucking retarded hyper traits need wrapper
pin_project! {
struct IoWrapper<T> {
io: T,
}
}
impl<T: tokio::io::AsyncRead + Unpin> hyper::rt::Read for IoWrapper<T> {
fn poll_read(self: Pin<&mut Self>, ctx: &mut task::Context<'_>, mut buf: hyper::rt::ReadBufCursor<'_>) -> task::Poll<Result<(), std::io::Error>> {
let n = unsafe {
let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut());
match tokio::io::AsyncRead::poll_read(Pin::new(self.project().io), ctx, &mut tbuf) {
task::Poll::Ready(Ok(())) => tbuf.filled().len(),
other => return other,
}
};
unsafe {
buf.advance(n);
}
task::Poll::Ready(Ok(()))
}
}
impl<T: tokio::io::AsyncWrite + Unpin> hyper::rt::Write for IoWrapper<T> {
fn poll_write(self: Pin<&mut Self>, ctx: &mut task::Context<'_>, buf: &[u8]) -> task::Poll<Result<usize, std::io::Error>> {
tokio::io::AsyncWrite::poll_write(Pin::new(self.project().io), ctx, buf)
}
fn poll_flush(self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> task::Poll<Result<(), std::io::Error>> {
tokio::io::AsyncWrite::poll_flush(Pin::new(self.project().io), ctx)
}
fn poll_shutdown(self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> task::Poll<Result<(), std::io::Error>> {
tokio::io::AsyncWrite::poll_shutdown(Pin::new(self.project().io), ctx)
}
fn is_write_vectored(&self) -> bool {
tokio::io::AsyncWrite::is_write_vectored(&self.io)
}
fn poll_write_vectored(self: Pin<&mut Self>, ctx: &mut task::Context<'_>, bufs: &[std::io::IoSlice<'_>]) -> task::Poll<Result<usize, std::io::Error>> {
tokio::io::AsyncWrite::poll_write_vectored(Pin::new(self.project().io), ctx, bufs)
}
}
async fn example() {
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);;
let listener = TcpListener::bind(addr).await.expect("bind");
println!("Listening on http://{}", addr);
let static_files = StaticFiles::new(TokioWorker, DirectoryConfig);
loop {
let (io, _) = listener.accept().await.expect("accept");
let io = IoWrapper {
io,
};
let static_files = static_files.clone();
tokio::task::spawn(async move {
http1::Builder::new().serve_connection(io, static_files).await
});
}
}