add route for gemini requests

This commit is contained in:
yggverse 2025-02-22 01:33:38 +02:00
parent a4f5c75bd0
commit 2532b3e11c

View file

@ -56,134 +56,169 @@ fn handle(argument: Arc<Argument>, peer: SocketAddr, stream: &mut TlsStream<TcpS
let mut input = vec![0; 1024]; let mut input = vec![0; 1024];
match stream.read(&mut input) { match stream.read(&mut input) {
Ok(0) => println!("[{}] [warning] [{peer}] Connection closed by peer", now()), Ok(0) => println!("[{}] [warning] [{peer}] Connection closed by peer", now()),
Ok(l) => match request::Titan::from_bytes(&input[..l]) { Ok(l) => {
Ok(titan) => { match Request::from_bytes(&input[..l]) {
// init memory pool Ok(request) => {
let mut data: Vec<u8> = Vec::with_capacity(titan.size); match request {
loop { Request::Gemini(gemini) => println!("request: {}", gemini.url), // @TODO
// read data bytes Request::Titan(titan) => {
let mut input = vec![0; argument.chunk]; // init memory pool
match stream.read(&mut input) { let mut data: Vec<u8> = Vec::with_capacity(titan.size);
Ok(0) => { loop {
println!("[{}] [warning] [{peer}] Connection closed by peer", now()) // read data bytes
} let mut input = vec![0; argument.chunk];
Ok(l) => { match stream.read(&mut input) {
data.extend(&input[..l]); Ok(0) => {
println!(
// calculate once "[{}] [warning] [{peer}] Connection closed by peer",
let total = data.len(); now()
)
// validate server-side limits
if argument.size.is_some_and(|limit| total > limit) {
const MESSAGE: &str = "Allowed max length limit reached";
return send(
&response::failure::permanent::BadRequest {
message: Some(MESSAGE.to_string()),
} }
.into_bytes(), Ok(l) => {
stream, data.extend(&input[..l]);
|result| match result {
Ok(()) => {
println!("[{}] [warning] [{peer}] {MESSAGE}", now())
}
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
},
);
}
// all expected data received // calculate once
if titan.size >= total { let total = data.len();
// validate client-side limits
if titan.size > total {
const MESSAGE: &str = "Data size mismatch header declaration";
return send(
&response::failure::permanent::BadRequest {
message: Some(MESSAGE.to_string()),
}
.into_bytes(),
stream,
|result| match result {
Ok(()) => {
println!("[{}] [warning] [{peer}] {MESSAGE}", now())
}
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
},
);
}
// @TODO detect/validate/cache mime based on data received // validate server-side limits
if argument.size.is_some_and(|limit| total > limit) {
// success const MESSAGE: &str =
match storage::Item::create(&argument.directory) { "Allowed max length limit reached";
Ok(mut tmp) => match tmp.file.write(titan.data) { return send(
Ok(_) => match tmp.commit() { &response::failure::permanent::BadRequest {
Ok(pmt) => send( message: Some(MESSAGE.to_string()),
&response::redirect::Permanent {
target: pmt.path.to_str().unwrap().to_owned(),
} }
.into_bytes(), .into_bytes(),
stream, stream,
|result| match result { |result| match result {
Ok(()) => println!(
"[{}] [info] [{peer}] Data saved to {}",
now(),
pmt.path.to_string_lossy()
),
Err(e) => println!(
"[{}] [warning] [{peer}] {e}",
now()
),
},
),
Err((tmp, e)) => send(
&response::failure::temporary::General {
message: Some(
"Internal server error".to_string(),
),
}
.into_bytes(),
stream,
|result| {
match result {
Ok(()) => println!(
"[{}] [error] [{peer}] {e}",
now()
),
Err(e) => println!(
"[{}] [error] [{peer}] {e}",
now()
),
};
if let Err(e) = tmp.delete() {
println!(
"[{}] [error] [{peer}] {e}",
now()
);
}
},
),
},
Err(e) => send(
&response::failure::temporary::General {
message: Some("Internal server error".to_string()),
}
.into_bytes(),
stream,
|result| {
match result {
Ok(()) => { Ok(()) => {
println!("[{}] [error] [{peer}] {e}", now()) println!(
"[{}] [warning] [{peer}] {MESSAGE}",
now()
)
} }
Err(e) => { Err(e) => {
println!("[{}] [error] [{peer}] {e}", now()) println!("[{}] [error] [{peer}] {e}", now())
} }
}; },
if let Err(e) = tmp.delete() { );
println!("[{}] [error] [{peer}] {e}", now()); }
}
}, // all expected data received
), if titan.size >= total {
}, // validate client-side limits
if titan.size > total {
const MESSAGE: &str =
"Data size mismatch header declaration";
return send(
&response::failure::permanent::BadRequest {
message: Some(MESSAGE.to_string()),
}
.into_bytes(),
stream,
|result| match result {
Ok(()) => {
println!(
"[{}] [warning] [{peer}] {MESSAGE}",
now()
)
}
Err(e) => println!(
"[{}] [error] [{peer}] {e}",
now()
),
},
);
}
// @TODO detect/validate/cache mime based on data received
// success
match storage::Item::create(&argument.directory) {
Ok(mut tmp) => match tmp.file.write(titan.data) {
Ok(_) => match tmp.commit() {
Ok(pmt) => send(
&response::redirect::Permanent {
target: pmt.path.to_str().unwrap().to_owned(),
}
.into_bytes(),
stream,
|result| match result {
Ok(()) => println!(
"[{}] [info] [{peer}] Data saved to {}",
now(),
pmt.path.to_string_lossy()
),
Err(e) => println!(
"[{}] [warning] [{peer}] {e}",
now()
),
},
),
Err((tmp, e)) => send(
&response::failure::temporary::General {
message: Some(
"Internal server error".to_string(),
),
}
.into_bytes(),
stream,
|result| {
match result {
Ok(()) => println!(
"[{}] [error] [{peer}] {e}",
now()
),
Err(e) => println!(
"[{}] [error] [{peer}] {e}",
now()
),
};
if let Err(e) = tmp.delete() {
println!(
"[{}] [error] [{peer}] {e}",
now()
);
}
},
),
},
Err(e) => send(
&response::failure::temporary::General {
message: Some("Internal server error".to_string()),
}
.into_bytes(),
stream,
|result| {
match result {
Ok(()) => {
println!("[{}] [error] [{peer}] {e}", now())
}
Err(e) => {
println!("[{}] [error] [{peer}] {e}", now())
}
};
if let Err(e) = tmp.delete() {
println!("[{}] [error] [{peer}] {e}", now());
}
},
),
},
Err(e) => send(
&response::failure::temporary::General {
message: Some("Internal server error".to_string()),
}
.into_bytes(),
stream,
|result| match result {
Ok(()) => println!("[{}] [error] [{peer}] {e}", now()),
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
},
),
}
break;
}
}
Err(e) => send( Err(e) => send(
&response::failure::temporary::General { &response::failure::temporary::General {
message: Some("Internal server error".to_string()), message: Some("Internal server error".to_string()),
@ -196,35 +231,23 @@ fn handle(argument: Arc<Argument>, peer: SocketAddr, stream: &mut TlsStream<TcpS
}, },
), ),
} }
break;
} }
} }
Err(e) => send(
&response::failure::temporary::General {
message: Some("Internal server error".to_string()),
}
.into_bytes(),
stream,
|result| match result {
Ok(()) => println!("[{}] [error] [{peer}] {e}", now()),
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
},
),
} }
} }
Err(e) => send(
&response::failure::temporary::General {
message: Some("Internal server error".to_string()),
}
.into_bytes(),
stream,
|result| match result {
Ok(()) => println!("[{}] [error] [{peer}] {e}", now()),
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
},
),
} }
Err(e) => send( }
&response::failure::temporary::General {
message: Some("Internal server error".to_string()),
}
.into_bytes(),
stream,
|result| match result {
Ok(()) => println!("[{}] [error] [{peer}] {e}", now()),
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
},
),
},
Err(e) => send( Err(e) => send(
&response::failure::temporary::General { &response::failure::temporary::General {
message: Some("Internal server error".to_string()), message: Some("Internal server error".to_string()),