diff --git a/site/src/main.rs b/site/src/main.rs index 0d7387f..cf0667d 100644 --- a/site/src/main.rs +++ b/site/src/main.rs @@ -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 { +fn index(_req: Request) -> Result { 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 { +fn majc(_req: Request) -> Result { 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 { - 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 { + 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()) } } diff --git a/src/response.rs b/src/response.rs index 46b0cf2..d70409e 100644 --- a/src/response.rs +++ b/src/response.rs @@ -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, } +impl Response { + pub fn gemini(body: Vec) -> Response { + Response { + status: StatusCode::Success, + meta: "text/gemini".to_string(), + body: body, + } + } + + pub fn render(body: Vec) -> Response { + let mut buf: Vec = 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") + } + } } } }