use std::io::{Cursor, Read};
use std::net::SocketAddr;
use conduit::{Extensions, HeaderMap, Host, Method, RequestExt, Scheme, StartInstant, Version};
use http::request::Parts as HttpParts;
use http::Request;
use hyper::body::Bytes;
pub(crate) struct ConduitRequest {
parts: HttpParts,
path: String,
remote_addr: SocketAddr,
body: Cursor<Bytes>,
}
impl ConduitRequest {
pub(crate) fn new(request: Request<Bytes>, remote_addr: SocketAddr, now: StartInstant) -> Self {
let (mut parts, body) = request.into_parts();
let path = parts.uri.path().as_bytes();
let path = percent_encoding::percent_decode(path)
.decode_utf8_lossy()
.into_owned();
parts.extensions.insert(now);
Self {
parts,
path,
remote_addr,
body: Cursor::new(body),
}
}
}
impl RequestExt for ConduitRequest {
fn http_version(&self) -> Version {
self.parts.version
}
fn method(&self) -> &Method {
&self.parts.method
}
fn scheme(&self) -> Scheme {
Scheme::Http
}
fn headers(&self) -> &HeaderMap {
&self.parts.headers
}
fn content_length(&self) -> Option<u64> {
Some(self.body.get_ref().len() as u64)
}
fn remote_addr(&self) -> SocketAddr {
self.remote_addr
}
fn virtual_root(&self) -> Option<&str> {
None
}
fn path(&self) -> &str {
&*self.path
}
fn path_mut(&mut self) -> &mut String {
&mut self.path
}
fn extensions(&self) -> &Extensions {
&self.parts.extensions
}
fn mut_extensions(&mut self) -> &mut Extensions {
&mut self.parts.extensions
}
fn host(&self) -> Host<'_> {
let host = self
.headers()
.get(http::header::HOST)
.map(|h| h.to_str().unwrap_or(""))
.unwrap_or("");
Host::Name(host)
}
fn query_string(&self) -> Option<&str> {
self.parts.uri.query()
}
fn body(&mut self) -> &mut dyn Read {
&mut self.body
}
}