Add basic URI parsing
It works with Lagrange, but gemget still causes the server to throw "Operation would block"
This commit is contained in:
parent
591090c980
commit
0c46f27f89
3 changed files with 46 additions and 19 deletions
|
@ -18,8 +18,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let config = rustls::ServerConfig::builder()
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(certs, private_key)?;
|
||||
let listener = TcpListener::bind(format!("[::]:{}", 1965)).unwrap();
|
||||
let srv = server::Server {
|
||||
listener: TcpListener::bind(format!("[::]:{}", 1965)).unwrap(),
|
||||
listener,
|
||||
tls_config: config,
|
||||
};
|
||||
match srv.listen() {
|
||||
|
|
|
@ -81,21 +81,39 @@ pub struct Request {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum RequestParseError {
|
||||
NotTerminated,
|
||||
Error(Box<dyn std::error::Error>),
|
||||
UserInfoGiven,
|
||||
TooLarge,
|
||||
FragmentGiven,
|
||||
BadScheme,
|
||||
BadUrl(url::ParseError),
|
||||
}
|
||||
|
||||
impl From<url::ParseError> for RequestParseError {
|
||||
fn from(value: url::ParseError) -> Self {
|
||||
RequestParseError::BadUrl(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for RequestParseError {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
RequestParseError::Error(Box::new(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for RequestParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
RequestParseError::NotTerminated => write!(f, "Request not terminated with CRLF"),
|
||||
RequestParseError::Error(e) => write!(f, "Request read error: {}", e),
|
||||
RequestParseError::UserInfoGiven => write!(f, "URI userinfo not permitted"),
|
||||
RequestParseError::TooLarge => write!(f, "URI larger than permitted 1024 bytes"),
|
||||
RequestParseError::FragmentGiven => write!(f, "URI fragments not permitted"),
|
||||
RequestParseError::BadScheme => {
|
||||
write!(f, "URI schemes besides 'gemini' not supported")
|
||||
}
|
||||
RequestParseError::BadUrl(e) => e.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,12 +218,3 @@ impl From<RequestParseError> for ErrorResponse {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<url::ParseError> for ErrorResponse {
|
||||
fn from(value: url::ParseError) -> Self {
|
||||
ErrorResponse {
|
||||
code: ErrorStatus::BadRequest,
|
||||
error: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::protocol::{self, Response};
|
||||
use crate::protocol::*;
|
||||
use mime::Mime;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::{self, BufRead, Read, Write};
|
||||
use std::{net, str::FromStr, sync::Arc};
|
||||
use url::Url;
|
||||
|
||||
|
@ -12,24 +12,41 @@ pub struct Server {
|
|||
|
||||
impl Server {
|
||||
pub fn listen(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let (mut stream, _) = self.listener.accept().expect("15");
|
||||
let mut conn =
|
||||
rustls::ServerConnection::new(Arc::new(self.tls_config.clone())).expect("17");
|
||||
let (mut stream, _) = self.listener.accept()?;
|
||||
let mut conn = rustls::ServerConnection::new(Arc::new(self.tls_config.clone()))?;
|
||||
|
||||
let response = protocol::Request::try_from(Url::from_str("gemini://localhost")?)?.process();
|
||||
conn.complete_io(&mut stream)?;
|
||||
let response = read_request(conn.reader())?.process();
|
||||
|
||||
conn.writer()
|
||||
.write_all(response.serialize().as_slice())
|
||||
.expect("23");
|
||||
conn.complete_io(&mut stream).expect("24");
|
||||
conn.complete_io(&mut stream)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl protocol::Request {
|
||||
fn read_request(stream: rustls::Reader) -> Result<Request, RequestParseError> {
|
||||
let mut reader = io::BufReader::new(stream);
|
||||
let mut buf = String::new();
|
||||
// The URI can be 1024 bytes long, plus \r\n
|
||||
if reader.read_line(&mut buf)? > 1026 {
|
||||
return Err(RequestParseError::TooLarge);
|
||||
}
|
||||
match buf.char_indices().rev().nth(1) {
|
||||
Some((i, _)) if &buf[i..] != "\r\n" => Err(RequestParseError::NotTerminated),
|
||||
None => Err(RequestParseError::NotTerminated),
|
||||
Some(_) => Ok(()),
|
||||
}?;
|
||||
|
||||
let url = Url::from_str(buf.trim())?;
|
||||
Request::try_from(url)
|
||||
}
|
||||
|
||||
impl Request {
|
||||
fn process(&self) -> impl Response {
|
||||
protocol::SuccessResponse {
|
||||
SuccessResponse {
|
||||
mime: Mime::from_str("text/gemini").expect("Hardcoded mime value failed??"),
|
||||
body: b"Hiiiiii im gay :>".to_vec(),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue