Compare commits

..

3 Commits

Author SHA1 Message Date
Brian Picciano
b1717b6ded WIP: full gemini support
- DomainNotFound needs to be handled. Probably makes sense to not
  generate certs for unconfigured domains, to prevent DOS.

- Probably needs more testing.
2023-07-31 20:49:00 +02:00
Brian Picciano
d429b51cf8 Fix self-signed cert generation, not_before is required apparently 2023-07-31 20:48:00 +02:00
Brian Picciano
8a530d4f7d Fix static file index.gmi 2023-07-31 20:47:14 +02:00
5 changed files with 53 additions and 24 deletions

View File

@ -35,6 +35,12 @@ impl Certificate {
.set_subject_name(&name)
.or_unexpected_while("setting subject name")?;
// 1970/01/01
let not_before = Asn1Time::from_unix(0).expect("initializing not_before");
builder
.set_not_before(not_before.as_ref())
.or_unexpected_while("setting not_before")?;
// 9999/07/23
let not_after = Asn1Time::from_unix(253388296800).expect("initializing not_after");
builder

View File

@ -3,3 +3,32 @@ pub mod gemini;
pub mod http;
pub use config::*;
use std::borrow;
fn append_index_to_path<'path, 'index>(
path: &'path str,
index: &'index str,
) -> borrow::Cow<'path, str> {
if path.len() == 0 {
let mut path = String::with_capacity(1 + index.len());
path.push('/');
path.push_str(index);
return borrow::Cow::Owned(path);
}
if path.ends_with('/') {
let mut indexed_path = String::with_capacity(path.len() + index.len());
indexed_path.push_str(path.as_ref());
indexed_path.push_str(index);
return borrow::Cow::Owned(indexed_path);
}
borrow::Cow::Borrowed(path)
}
fn guess_mime(path: &str) -> String {
mime_guess::from_path(path)
.first_or_octet_stream()
.to_string()
}

View File

@ -88,14 +88,22 @@ impl Service {
.into_gemini_request()
.map_err(|e| HandleConnError::ClientError(format!("failed to parse request: {e}")))?;
let f = match self.domain_manager.get_file(domain, req.path()) {
let path = service::append_index_to_path(req.path(), "index.gmi");
let f = match self.domain_manager.get_file(domain, &path) {
Ok(f) => f,
Err(domain::manager::GetFileError::DomainNotFound) => panic!("TODO"),
Err(domain::manager::GetFileError::FileNotFound) => panic!("TODO"),
Err(domain::manager::GetFileError::FileNotFound) => {
return Ok(self.respond_conn(w, "51", "File not found", None).await?)
}
Err(domain::manager::GetFileError::Unexpected(e)) => return Err(e.into()),
};
Ok(self.respond_conn(w, "20", "TODO", Some(f)).await?)
let content_type = service::guess_mime(&path);
Ok(self
.respond_conn(w, "20", content_type.as_str(), Some(f))
.await?)
}
async fn proxy_conn<IO>(

View File

@ -79,13 +79,9 @@ struct DomainSyncArgs {
impl<'svc> Service {
fn serve(&self, status_code: u16, path: &str, body: Body) -> Response<Body> {
let content_type = mime_guess::from_path(path)
.first_or_octet_stream()
.to_string();
match Response::builder()
.status(status_code)
.header("Content-Type", content_type)
.header("Content-Type", service::guess_mime(path))
.body(body)
{
Ok(res) => res,
@ -161,20 +157,10 @@ impl<'svc> Service {
}
async fn serve_origin(&self, domain: domain::Name, req: Request<Body>) -> Response<Body> {
let mut path_owned;
let path = req.uri().path();
let path = service::append_index_to_path(req.uri().path(), "index.html");
let path = match path.ends_with('/') {
true => {
path_owned = String::from(path);
path_owned.push_str("index.html");
path_owned.as_str()
}
false => path,
};
match self.domain_manager.get_file(&domain, path) {
Ok(f) => self.serve(200, path, Body::wrap_stream(f)),
match self.domain_manager.get_file(&domain, &path) {
Ok(f) => self.serve(200, &path, Body::wrap_stream(f)),
Err(domain::manager::GetFileError::DomainNotFound) => {
return self.render_error_page(404, "Domain not found")
}

View File

@ -2,8 +2,8 @@
This is the gemini index.
=> foo /foo.gmi
=> /foo.gmi foo
=> bar /subdir/bar.gmi
=> /subdir/bar.gmi bar
=> penguin /penguin.jpg
=> /penguin.jpg penguin