Added a static handler type. Impl AsRef<Body> for Response

im so tired i havent slept enough in so long but also i havent done any productive work like do you think im using this project as an excuse or like a bad coping mechanism for my mental health or something like that cause thats what its starting to feel like
This commit is contained in:
Emi Tatsuo 2020-11-23 23:30:59 -05:00
parent 7990739884
commit c3d7381860
Signed by: Emi
GPG key ID: 68FAB2E2E6DFC98B
4 changed files with 80 additions and 11 deletions

View file

@ -1,6 +1,6 @@
use anyhow::*;
use log::LevelFilter;
use northstar::{Server, Request, Response, GEMINI_PORT, Document};
use northstar::{Server, Response, GEMINI_PORT, Document};
use northstar::document::HeadingLevel::*;
#[tokio::main]
@ -9,14 +9,7 @@ async fn main() -> Result<()> {
.filter_module("northstar", LevelFilter::Debug)
.init();
Server::bind(("localhost", GEMINI_PORT))
.add_route("/",handle_request)
.serve()
.await
}
async fn handle_request(_request: Request) -> Result<Response> {
let response = Document::new()
let response: Response = Document::new()
.add_preformatted(include_str!("northstar_logo.txt"))
.add_blank_line()
.add_link("https://docs.rs/northstar", "Documentation")
@ -41,5 +34,9 @@ async fn handle_request(_request: Request) -> Result<Response> {
"openssl req -x509 -nodes -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365",
))
.into();
Ok(response)
Server::bind(("localhost", GEMINI_PORT))
.add_route("/", response)
.serve()
.await
}

View file

@ -15,7 +15,7 @@ use std::{
panic::{catch_unwind, AssertUnwindSafe},
};
use crate::types::{Response, Request};
use crate::{Document, types::{Body, Response, Request}};
/// A struct representing something capable of handling a request.
///
@ -29,6 +29,7 @@ use crate::types::{Response, Request};
/// response is produced.
pub enum Handler {
FnHandler(HandlerInner),
StaticHandler(Response),
}
/// Since we can't store train objects, we need to wrap fn handlers in a box
@ -57,6 +58,26 @@ impl Handler {
Response::server_error("").unwrap()
})
},
Self::StaticHandler(response) => {
let body = response.as_ref();
match body {
None => Response::new(response.header().clone()),
Some(Body::Bytes(bytes)) => {
Response::new(response.header().clone())
.with_body(bytes.clone())
},
_ => {
error!(concat!(
"Cannot construct a static handler with a reader-based body! ",
" We're sending a response so that the client doesn't crash, but",
" given that this is a release build you should really fix this."
));
Response::server_error(
"Very bad server error, go tell the sysadmin to look at the logs."
).unwrap()
}
}
}
}
}
}
@ -81,6 +102,44 @@ where
}
}
// We tolerate a fallible `impl From` because this is *really* not the kind of thing the
// user should be catching in runtime.
#[allow(clippy::fallible_impl_from)]
impl From<Response> for Handler {
/// Serve an unchanging response
///
/// Any and all requests to this handler will be responded to with the same response,
/// no matter what. This is good for static content that is provided by your app.
/// For serving files & directories, try looking at creating a handler from a path
///
/// ## Panics
/// This response type **CANNOT** be created using Responses with [`Reader`] bodies.
/// Attempting to do this will cause a panic. Don't.
///
/// [`Reader`]: Body::Reader
fn from(response: Response) -> Self {
#[cfg(debug_assertions)] {
// We have another check once the handler is actually called that is not
// disabled for release builds
if let Some(Body::Reader(_)) = response.as_ref() {
panic!("Cannot construct a static handler with a reader-based body");
}
}
Self::StaticHandler(response)
}
}
impl From<&Document> for Handler {
/// Serve an unchanging response, shorthand for From<Response>
///
/// This document will be sent in response to any requests that arrive at this
/// handler. As with all documents, this will be a successful response with a
/// `text/gemini` MIME.
fn from(doc: &Document) -> Self {
Self::StaticHandler(doc.into())
}
}
/// A utility for catching unwinds on Futures.
///
/// This is adapted from the futures-rs CatchUnwind, in an effort to reduce the large

View file

@ -96,6 +96,18 @@ impl Response {
}
}
impl AsRef<Option<Body>> for Response {
fn as_ref(&self) -> &Option<Body> {
&self.body
}
}
impl AsMut<Option<Body>> for Response {
fn as_mut(&mut self) -> &mut Option<Body> {
&mut self.body
}
}
impl<D: Borrow<Document>> From<D> for Response {
fn from(doc: D) -> Self {
Self::document(doc)

View file

@ -10,6 +10,7 @@ use tokio::{
};
#[cfg(feature="serve_dir")]
use crate::types::{Document, document::HeadingLevel::*};
#[cfg(feature="serve_dir")]
use crate::types::Response;
use std::future::Future;
use tokio::time;