mirror of
https://github.com/mikedilger/chorus.git
synced 2026-01-03 06:15:33 +00:00
Blossom stubbed out
This commit is contained in:
parent
28fb96a9d5
commit
da4ec4b5c8
136
src/web/blossom/mod.rs
Normal file
136
src/web/blossom/mod.rs
Normal file
@ -0,0 +1,136 @@
|
||||
use crate::error::{ChorusError, Error};
|
||||
use http::header::{
|
||||
ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS, ACCESS_CONTROL_ALLOW_ORIGIN,
|
||||
ACCESS_CONTROL_REQUEST_HEADERS, ACCESS_CONTROL_REQUEST_METHOD, ALLOW, CONTENT_LENGTH, ORIGIN,
|
||||
WWW_AUTHENTICATE,
|
||||
};
|
||||
use http::{Method, StatusCode};
|
||||
//ACCEPT, AUTHORIZATION, CONTENT_TYPE, DATE, ETAG, ORIGIN
|
||||
use http_body_util::combinators::BoxBody;
|
||||
use http_body_util::{BodyExt, Empty};
|
||||
use hyper::body::{Bytes, Incoming};
|
||||
use hyper::{Request, Response};
|
||||
|
||||
pub async fn handle(request: &Request<Incoming>) -> Result<Response<BoxBody<Bytes, Error>>, Error> {
|
||||
match route(request).await {
|
||||
Ok(response) => Ok(response),
|
||||
Err(e) => match e.inner {
|
||||
ChorusError::SignalNotBlossom => Err(e),
|
||||
_ => error_response(e),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn route(request: &Request<Incoming>) -> Result<Response<BoxBody<Bytes, Error>>, Error> {
|
||||
let p = request.uri().path();
|
||||
if p.starts_with("/")
|
||||
&& p.len() >= 1 + 64
|
||||
&& p.chars().skip(1).take(64).all(|c| c.is_ascii_hexdigit())
|
||||
{
|
||||
handle_hash(request).await
|
||||
} else if p == "/upload" {
|
||||
handle_upload(request).await
|
||||
} else if p.starts_with("/list/")
|
||||
&& p.len() >= 6 + 64
|
||||
&& p.chars().skip(6).take(64).all(|c| c.is_ascii_hexdigit())
|
||||
{
|
||||
handle_list(request).await
|
||||
} else if p == "/mirror" {
|
||||
handle_mirror(request).await
|
||||
} else {
|
||||
Err(ChorusError::SignalNotBlossom.into())
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(e: Error) -> Result<Response<BoxBody<Bytes, Error>>, Error> {
|
||||
use std::io::ErrorKind;
|
||||
|
||||
let mut response = Response::builder().header(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
|
||||
|
||||
let (status, reason) = match e.inner {
|
||||
ChorusError::BlossomAuthFailure(m) => {
|
||||
response = response.header(WWW_AUTHENTICATE, "Nostr");
|
||||
(StatusCode::UNAUTHORIZED, m)
|
||||
}
|
||||
ChorusError::FromHex(_) => (StatusCode::BAD_REQUEST, format!("{e}")),
|
||||
ChorusError::Io(ref ioerror) => match ioerror.kind() {
|
||||
ErrorKind::NotFound => (StatusCode::NOT_FOUND, "Not Found".to_owned()),
|
||||
_ => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e}")),
|
||||
},
|
||||
_ => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e}")),
|
||||
};
|
||||
|
||||
Ok(response
|
||||
.header("X-Reason", reason)
|
||||
.status(status)
|
||||
.body(Empty::new().map_err(|e| e.into()).boxed())?)
|
||||
}
|
||||
|
||||
fn options_response(
|
||||
request: &Request<Incoming>,
|
||||
methods: &str,
|
||||
) -> Result<Response<BoxBody<Bytes, Error>>, Error> {
|
||||
if request
|
||||
.headers()
|
||||
.contains_key(ACCESS_CONTROL_REQUEST_HEADERS)
|
||||
|| request
|
||||
.headers()
|
||||
.contains_key(ACCESS_CONTROL_REQUEST_METHOD)
|
||||
|| request.headers().contains_key(ORIGIN)
|
||||
{
|
||||
// CORS OPTIONS response
|
||||
Ok(Response::builder()
|
||||
.header(ACCESS_CONTROL_ALLOW_ORIGIN, "*")
|
||||
.header(ACCESS_CONTROL_ALLOW_HEADERS, "Authorization, *")
|
||||
.header(ACCESS_CONTROL_ALLOW_METHODS, methods)
|
||||
.header(CONTENT_LENGTH, "0")
|
||||
.status(StatusCode::OK)
|
||||
.body(Empty::new().map_err(|e| e.into()).boxed())?)
|
||||
} else {
|
||||
// Normal OPTIONS response
|
||||
Ok(Response::builder()
|
||||
.header(ALLOW, methods)
|
||||
.status(StatusCode::NO_CONTENT)
|
||||
.body(Empty::new().map_err(|e| e.into()).boxed())?)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_hash(
|
||||
request: &Request<Incoming>,
|
||||
) -> Result<Response<BoxBody<Bytes, Error>>, Error> {
|
||||
if matches!(request.method(), &Method::OPTIONS) {
|
||||
return options_response(request, "OPTIONS, HEAD, GET, DELETE");
|
||||
}
|
||||
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub async fn handle_upload(
|
||||
request: &Request<Incoming>,
|
||||
) -> Result<Response<BoxBody<Bytes, Error>>, Error> {
|
||||
if matches!(request.method(), &Method::OPTIONS) {
|
||||
return options_response(request, "OPTIONS, HEAD, PUT");
|
||||
}
|
||||
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub async fn handle_list(
|
||||
request: &Request<Incoming>,
|
||||
) -> Result<Response<BoxBody<Bytes, Error>>, Error> {
|
||||
if matches!(request.method(), &Method::OPTIONS) {
|
||||
return options_response(request, "OPTIONS, GET");
|
||||
}
|
||||
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub async fn handle_mirror(
|
||||
request: &Request<Incoming>,
|
||||
) -> Result<Response<BoxBody<Bytes, Error>>, Error> {
|
||||
if matches!(request.method(), &Method::OPTIONS) {
|
||||
return options_response(request, "OPTIONS, PUT");
|
||||
}
|
||||
|
||||
unimplemented!()
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
mod blossom;
|
||||
mod management;
|
||||
mod nip11;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::error::{ChorusError, Error};
|
||||
use crate::globals::GLOBALS;
|
||||
use crate::ip::HashedPeer;
|
||||
use http::Method;
|
||||
use http_body_util::combinators::BoxBody;
|
||||
@ -41,6 +43,18 @@ pub async fn serve_http(
|
||||
}
|
||||
}
|
||||
|
||||
// Try blossom if enabled
|
||||
if GLOBALS.config.read().blossom_directory.is_some() {
|
||||
match blossom::handle(&request).await {
|
||||
Ok(response) => return Ok(response),
|
||||
Err(e) => {
|
||||
if !matches!(e.inner, ChorusError::SignalNotBlossom) {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log::debug!(target: "Client", "{}: HTTP request for {}", peer, request.uri());
|
||||
let response = Response::builder()
|
||||
.header("Access-Control-Allow-Origin", "*")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user