"memchr",
"mime",
"parking_lot",
+ "pin-project-lite",
"regex",
"sha2",
"structopt",
lazy_static = "1.4"
log = "0.4"
memchr = "2"
+pin-project-lite = "0.2"
sha2 = "0.9"
structopt = "0.3"
subtle = "2"
}
} {
let response = WebResponse {
- data: Ok(vec![ /* xxx */ ]),
+ data: Ok(default()),
warnings: default(),
};
pub data: Result<WebResponseData, AE>,
}
-pub type WebResponseData = Vec<u8>;
+pub type WebResponseData = FrameQueueBuf;
+pub type WebResponseBody = BufBody<FrameQueueBuf>;
pub async fn handle(
conn: Arc<String>,
global: Arc<Global>,
req: hyper::Request<hyper::Body>
-) -> Result<hyper::Response<hyper::Body>, hyper::http::Error> {
+) -> Result<hyper::Response<WebResponseBody>, hyper::http::Error> {
if req.method() == Method::GET {
- let mut resp = hyper::Response::new(hyper::Body::from("hippotat\r\n"));
+ let mut resp = hyper::Response::new(BufBody::display("hippotat\r\n"));
resp.headers_mut().insert(
"Content-Type",
"text/plain; charset=US-ASCII".try_into().unwrap()
//dbg!(DumpHex(hmac_got), hmac_ok, client_exists);
if ! bool::from(hmac_ok & client_exists) {
debug!("{} rejected client {}", &conn, &client_name);
- let body = hyper::Body::from("Not authorised\r\n");
+ let body = BufBody::display("Not authorised\r\n");
return Ok(
hyper::Response::builder()
.status(hyper::StatusCode::FORBIDDEN)
&warnings.warnings);
}
- let data = hyper::Body::from(data);
+ let data = BufBody::new(data);
Ok::<_,AE>(
hyper::Response::builder()
.header("Content-Type", r#"application/octet-stream"#)
hyper::Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.header("Content-Type", r#"text/plain; charset="utf-8""#)
- .body(errmsg.into())
+ .body(BufBody::display(errmsg))
})
}
pub use extend::ext;
pub use fehler::{throw, throws};
pub use futures::{poll, future, FutureExt, StreamExt, TryStreamExt};
-pub use hyper::body::{Bytes, Buf};
+pub use hyper::body::{Bytes, Buf, HttpBody};
pub use hyper::{Method, Uri};
pub use hyper_tls::HttpsConnector;
pub use ipnet::IpNet;
pub use lazy_static::lazy_static;
pub use log::{trace, debug, info, warn, error};
pub use memchr::memmem;
+pub use pin_project_lite::pin_project;
pub use structopt::StructOpt;
pub use subtle::ConstantTimeEq;
pub use thiserror::Error;
self.content += l;
}
pub fn is_empty(&self) -> bool { self.content == 0 }
+ pub fn len(&self) -> usize { self.content }
}
impl FrameQueueBuf {
self.queue.push_(Cervine::Borrowed(&SLIP_END_SLICE));
}
pub fn is_empty(&self) -> bool { self.queue.is_empty() }
+ pub fn len(&self) -> usize { self.queue.len() }
}
impl<E> Extend<E> for FrameQueueBuf where E: Into<Box<[u8]>> {
fn chunk(&self) -> &[u8] { self.queue.chunk() }
fn advance(&mut self, cnt: usize) { self.queue.advance(cnt) }
}
+
+pin_project!{
+ pub struct BufBody<B:Buf> {
+ body: Option<B>,
+ }
+}
+impl<B:Buf> BufBody<B> {
+ pub fn new(body: B) -> Self { Self { body: Some(body ) } }
+}
+impl BufBody<FrameQueueBuf> {
+ pub fn display<S:Display>(s: S) -> Self {
+ let s = s.to_string().into_bytes();
+ let mut buf: FrameQueueBuf = default();
+ buf.push(s);
+ Self::new(buf)
+ }
+}
+
+impl<B:Buf> HttpBody for BufBody<B> {
+ type Error = Void;
+ type Data = B;
+ fn poll_data(self: Pin<&mut Self>, _: &mut std::task::Context<'_>)
+ -> Poll<Option<Result<B, Void>>> {
+ Poll::Ready(Ok(self.project().body.take()).transpose())
+ }
+ fn poll_trailers(self: Pin<&mut Self>, _: &mut std::task::Context<'_>)
+ -> Poll<Result<Option<hyper::HeaderMap<hyper::header::HeaderValue>>, Void>> {
+ Poll::Ready(Ok(None))
+ }
+}