|
|
|
@ -2,8 +2,8 @@ extern crate native_tls;
|
|
|
|
|
|
|
|
|
|
/// Types representing the gemini specification
|
|
|
|
|
pub mod gemini; |
|
|
|
|
pub mod error; |
|
|
|
|
|
|
|
|
|
mod error; |
|
|
|
|
mod io; |
|
|
|
|
mod logger; |
|
|
|
|
|
|
|
|
@ -13,7 +13,7 @@ use std::net::{TcpListener, TcpStream};
|
|
|
|
|
use std::path::PathBuf; |
|
|
|
|
use std::sync::Arc; |
|
|
|
|
|
|
|
|
|
use error::{GempressError, GempressResult}; |
|
|
|
|
pub use error::{GempressError, GempressResult}; |
|
|
|
|
use native_tls::{TlsAcceptor, TlsStream}; |
|
|
|
|
|
|
|
|
|
/// Configuration for a Gempress server.
|
|
|
|
@ -30,7 +30,7 @@ impl Config {
|
|
|
|
|
/// To generate a self-signed certificate, you can execute the following commands (substitute
|
|
|
|
|
/// `localhost` with your hostname, if applicable):
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// ```sh
|
|
|
|
|
/// openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'
|
|
|
|
|
/// openssl pkcs12 -export -out identity.pfx -inkey key.pem -in cert.pem
|
|
|
|
|
///
|
|
|
|
@ -57,7 +57,7 @@ impl Config {
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// use gempress::Gempress;
|
|
|
|
|
/// use gempress::*;
|
|
|
|
|
/// use gempress::gemini;
|
|
|
|
|
/// use std::path::PathBuf;
|
|
|
|
|
///
|
|
|
|
@ -65,8 +65,10 @@ impl Config {
|
|
|
|
|
/// let mut app = Gempress::new(config);
|
|
|
|
|
///
|
|
|
|
|
/// // Define a function handler
|
|
|
|
|
/// fn index_handler(req: Box<gemini::Request>, mut res: Box<gemini::Response>) {
|
|
|
|
|
/// res.send("Hello from index route!".as_bytes());
|
|
|
|
|
/// fn index_handler(req: Box<gemini::Request>, mut res: Box<gemini::Response>) ->
|
|
|
|
|
/// GempressResult<()> {
|
|
|
|
|
/// res.send("Hello from index route!".as_bytes())?;
|
|
|
|
|
/// Ok(())
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// // Apply function handler to path
|
|
|
|
@ -77,7 +79,7 @@ impl Config {
|
|
|
|
|
/// })
|
|
|
|
|
/// .unwrap();
|
|
|
|
|
/// ```
|
|
|
|
|
pub type Handler = dyn Fn(Box<gemini::Request>, Box<gemini::Response>); |
|
|
|
|
pub type Handler = dyn Fn(Box<gemini::Request>, Box<gemini::Response>) -> error::GempressResult<()>; |
|
|
|
|
|
|
|
|
|
struct Layer { |
|
|
|
|
handler: Box<Handler>, |
|
|
|
@ -119,16 +121,21 @@ impl Gempress {
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// use gempress::gemini;
|
|
|
|
|
/// use gempress::*;
|
|
|
|
|
///
|
|
|
|
|
/// let config = gempress::Config::from_identity(PathBuf::from("identity.pfx"), "password".into());
|
|
|
|
|
/// let mut app = Gempress::new(config);
|
|
|
|
|
///
|
|
|
|
|
/// fn index_handler(req: Box<gemini::Request>, mut res: Box<gemini::Response>) {
|
|
|
|
|
/// res.send("Hello from index route!".as_bytes());
|
|
|
|
|
/// fn index_handler(req: Box<gemini::Request>, mut res: Box<gemini::Response>) ->
|
|
|
|
|
/// GempressResult<()> {
|
|
|
|
|
/// res.send("Hello from index route!".as_bytes())?;
|
|
|
|
|
/// Ok(())
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// fn foo_handler(req: Box<gemini::Request>, mut res: Box<gemini::Response>) {
|
|
|
|
|
/// fn foo_handler(req: Box<gemini::Request>, mut res: Box<gemini::Response>) ->
|
|
|
|
|
/// GempressResult<()> {
|
|
|
|
|
/// res.send("This is the /foo route".as_bytes());
|
|
|
|
|
/// Ok(())
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// app.on("/", &index_handler);
|
|
|
|
@ -198,15 +205,19 @@ impl Gempress {
|
|
|
|
|
let raw_request = String::from_utf8(buffer.to_vec())?; |
|
|
|
|
|
|
|
|
|
let request = gemini::Request::parse(&raw_request)?; |
|
|
|
|
let response = gemini::Response::new(stream); |
|
|
|
|
let mut response = gemini::Response::new(stream); |
|
|
|
|
|
|
|
|
|
let layer = self |
|
|
|
|
let maybe_layer = self |
|
|
|
|
.stack |
|
|
|
|
.iter() |
|
|
|
|
.find(|&l| l.path == request.url.path()) |
|
|
|
|
.unwrap(); |
|
|
|
|
.find(|&l| l.path == request.url.path()); |
|
|
|
|
|
|
|
|
|
response.status(gemini::StatusCode::Success)?; |
|
|
|
|
|
|
|
|
|
(layer.handler)(Box::new(request), Box::new(response)); |
|
|
|
|
match maybe_layer { |
|
|
|
|
Some(layer) => { (layer.handler)(Box::new(request), Box::new(response)); }, |
|
|
|
|
None => { response.status(gemini::StatusCode::NotFound)?.send("Not found".as_bytes()); }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|