response building helpers
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Cadey Ratio 2020-07-27 20:50:42 -04:00
parent dd6f7f4e7d
commit b47c1a69a2
2 changed files with 86 additions and 44 deletions

View File

@ -1,4 +1,9 @@
use async_std::task;
use maj::{
route, seg,
server::{Error, Handler as MajHandler, Request},
split, Response,
};
use rustls::internal::pemfile::{certs, rsa_private_keys};
use rustls::{Certificate, NoClientAuth, PrivateKey, ServerConfig};
use std::fs::File;
@ -50,7 +55,12 @@ fn main() -> Result<(), maj::server::Error> {
let certs = load_certs(&opts.cert)?;
let mut keys = load_keys(&opts.key)?;
log::info!("{:?}", opts);
log::info!(
"serving gemini://{} on {}:{}",
opts.hostname,
opts.host,
opts.port
);
let mut config = ServerConfig::new(NoClientAuth::new());
config
@ -73,50 +83,35 @@ struct Handler {
hostname: String,
}
fn index() -> Result<maj::Response, maj::server::Error> {
fn index(_req: Request) -> Result<maj::Response, maj::server::Error> {
let msg = include_bytes!("index.gmi");
Ok(maj::Response {
status: maj::StatusCode::Success,
meta: "text/gemini".to_string(),
body: msg.to_vec(),
})
Ok(Response::gemini(msg.to_vec()))
}
fn majc() -> Result<maj::Response, maj::server::Error> {
fn majc(_req: Request) -> Result<maj::Response, maj::server::Error> {
let msg = include_bytes!("majc.gmi");
Ok(maj::Response {
status: maj::StatusCode::Success,
meta: "text/gemini".to_string(),
body: msg.to_vec(),
})
Ok(Response::gemini(msg.to_vec()))
}
#[async_trait::async_trait]
impl maj::server::Handler for Handler {
async fn handle(&self, r: maj::server::Request) -> Result<maj::Response, maj::server::Error> {
if r.url.has_host() && r.url.host_str().unwrap().to_string() != self.hostname {
return Ok(maj::Response {
status: maj::StatusCode::ProxyRequestRefused,
meta: "Wrong host".to_string(),
body: vec![],
});
impl MajHandler for Handler {
async fn handle(&self, req: Request) -> Result<Response, Error> {
if req.url.has_host() && req.url.host_str().unwrap().to_string() != self.hostname {
return Ok(Response::no_proxy());
}
match r.url.path() {
"" => Ok(maj::Response {
status: maj::StatusCode::PermanentRedirect,
meta: format!("gemini://{}/", self.hostname),
body: vec![],
}),
"/" => index(),
"/majc" => majc(),
_ => Ok(maj::Response {
status: maj::StatusCode::NotFound,
meta: "Not found".to_string(),
body: vec![],
}),
if req.url.path() == "" {
return Ok(Response::perm_redirect(format!(
"gemini://{}/",
self.hostname
)));
}
route!(req.url.path(), {
(/) => index(req);
(/"majc") => majc(req);
});
Ok(Response::not_found())
}
}

View File

@ -1,6 +1,6 @@
use crate::StatusCode;
use crate::{gemini, StatusCode};
use num::FromPrimitive;
use std::io::{prelude::*, ErrorKind, self};
use std::io::{self, prelude::*, ErrorKind};
/// A Gemini response as specified in [the spec](https://gemini.circumlunar.space/docs/specification.html).
#[derive(Default)]
@ -10,6 +10,51 @@ pub struct Response {
pub body: Vec<u8>,
}
impl Response {
pub fn gemini(body: Vec<u8>) -> Response {
Response {
status: StatusCode::Success,
meta: "text/gemini".to_string(),
body: body,
}
}
pub fn render(body: Vec<gemini::Node>) -> Response {
let mut buf: Vec<u8> = vec![];
gemini::render(body, &mut buf).unwrap();
Response {
status: StatusCode::Success,
meta: "text/gemini".to_string(),
body: buf,
}
}
pub fn perm_redirect(to: String) -> Response {
Response {
status: StatusCode::PermanentRedirect,
meta: to,
body: vec![],
}
}
pub fn no_proxy() -> Response {
Response {
status: StatusCode::ProxyRequestRefused,
meta: "Wrong host".to_string(),
body: vec![],
}
}
pub fn not_found() -> Response {
Response {
status: StatusCode::NotFound,
meta: "Not found".to_string(),
body: vec![],
}
}
}
/// The parser state.
#[derive(Debug)]
enum State {
@ -103,7 +148,7 @@ impl Response {
}
_ => {
if data.len() == 1024 {
return Err(Error::ResponseMetaTooLong)
return Err(Error::ResponseMetaTooLong);
}
data.push(buf[0]);
}
@ -168,11 +213,13 @@ mod tests {
match Response::parse(&mut fin) {
Ok(_) => panic!("wanted error but didn't get one"),
Err(why) => if let ResponseError::ResponseMetaTooLong = why {
println!("ok");
} else {
panic!("wanted ResponseError::ResponseMetaTooLong")
},
Err(why) => {
if let ResponseError::ResponseMetaTooLong = why {
println!("ok");
} else {
panic!("wanted ResponseError::ResponseMetaTooLong")
}
}
}
}
}