More macros
This commit is contained in:
parent
edc21b4403
commit
21b47409f1
3 changed files with 63 additions and 32 deletions
|
@ -29,6 +29,46 @@ macro_rules! fuck {
|
|||
};
|
||||
}
|
||||
|
||||
// Makes a response.
|
||||
macro_rules! respond {
|
||||
($($arg:tt)*) => {
|
||||
crate::api::Resp {
|
||||
$($arg)*,
|
||||
.. crate::api::Resp::default()
|
||||
}.into()
|
||||
};
|
||||
}
|
||||
|
||||
/// Parameters for a response
|
||||
struct Resp<'s> {
|
||||
body: Option<&'s Value>,
|
||||
kind: &'s str,
|
||||
code: u16,
|
||||
}
|
||||
|
||||
impl<'s> Default for Resp<'s> {
|
||||
fn default() -> Self {
|
||||
Resp {
|
||||
body: None,
|
||||
kind: "application/json",
|
||||
code: 200,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Resp<'a>> for Response {
|
||||
fn from(Resp { body, kind, code }: Resp<'_>) -> Response {
|
||||
let resp = Response::<()>::builder()
|
||||
.status(code)
|
||||
.header("content-type", kind);
|
||||
resp.body(match body {
|
||||
Some(data) => Full::new(serde_json::to_vec(&data).unwrap().into()),
|
||||
None => Full::new(Bytes::default()),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub mod ap;
|
||||
pub mod wf;
|
||||
|
||||
|
@ -205,23 +245,6 @@ fn with_json(
|
|||
}
|
||||
}
|
||||
|
||||
/// A quick, simple way to construct a response.
|
||||
fn respond<const N: usize>(
|
||||
status: u16,
|
||||
body: Option<impl Into<Bytes>>,
|
||||
headers: [(&str, &str); N],
|
||||
) -> Response {
|
||||
let mut resp = Response::<()>::builder().status(status);
|
||||
for (name, data) in headers {
|
||||
resp = resp.header(name, data);
|
||||
}
|
||||
resp.body(match body {
|
||||
Some(bytes) => Full::new(bytes.into()),
|
||||
None => Full::new(Bytes::default()),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
mod error {
|
||||
//! Pre-baked error responses.
|
||||
|
||||
|
@ -261,10 +284,13 @@ mod error {
|
|||
}
|
||||
/// Check whether the requester wants json from us.
|
||||
pub fn accepts_json(&self) -> bool {
|
||||
fn is_json((k, v): (&str, &str)) -> bool {
|
||||
k == "application" && v.split('+').any(|p| p == "json")
|
||||
}
|
||||
self.accept
|
||||
.iter()
|
||||
.filter_map(|s| s.split_once('/'))
|
||||
.any(|(k, v)| k == "application" && v.split('+').any(|p| p == "json"))
|
||||
.any(is_json)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,19 +6,19 @@ use puppy::{
|
|||
actor::{get_signing_key, Actor},
|
||||
get_local_ap_object, Context, Error, Key,
|
||||
};
|
||||
use serde_json::{to_string, Value};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::sig::{Signer, Verifier};
|
||||
use super::{error::Message, respond, Response};
|
||||
use super::{error::Message, Response};
|
||||
|
||||
/// Proxy a request through the instance.
|
||||
pub async fn proxy(cx: &Context, params: &[(&str, &str)]) -> Result<Response, Message> {
|
||||
// Extract our query parameters.
|
||||
let Some(user) = params.iter().find_map(|(k, v)| (*k == "user").then_some(v)) else {
|
||||
fuck!(400: "Expected `user` query param");
|
||||
fuck!(400: "expected `user` query param");
|
||||
};
|
||||
let Some(url) = params.iter().find_map(|(k, v)| (*k == "url").then_some(v)) else {
|
||||
fuck!(400: "Expected `url` query param");
|
||||
fuck!(400: "expected `url` query param");
|
||||
};
|
||||
|
||||
// Look up the actor's key in the store (which is accessible through the puppy context).
|
||||
|
@ -48,19 +48,22 @@ pub fn serve_object(cx: &Context, object_ulid: &str) -> Result<Response, Message
|
|||
let Ok(parsed) = object_ulid.parse::<Key>() else {
|
||||
fuck!(400: "improperly formatted ulid");
|
||||
};
|
||||
|
||||
let result = cx.run(|tx| get_local_ap_object(&tx, parsed));
|
||||
let Ok(object) = result else {
|
||||
fuck!(404: "object does not exist");
|
||||
};
|
||||
let json = to_string(&object.to_json_ld()).unwrap();
|
||||
Ok(respond(200, Some(json), [AP_CONTENT_TYPE]))
|
||||
}
|
||||
|
||||
const AP_CONTENT_TYPE: (&str, &str) = ("content-type", "application/activity+json");
|
||||
Ok(respond! {
|
||||
kind: "application/activity+json",
|
||||
body: Some(&object.to_json_ld())
|
||||
})
|
||||
}
|
||||
|
||||
/// Serve the special actor used for signing requests.
|
||||
pub fn serve_verifier_actor(verifier: &Verifier) -> Response {
|
||||
let body = verifier.to_json_ld();
|
||||
let encoded = serde_json::to_vec(&body).unwrap();
|
||||
respond(200, Some(encoded), [AP_CONTENT_TYPE])
|
||||
respond! {
|
||||
kind: "application/activity+json",
|
||||
body: Some(&verifier.to_json_ld())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use puppy::{
|
|||
use serde_json::{json, Value};
|
||||
use derive_more::Display;
|
||||
|
||||
use super::{error::Message, respond, Response};
|
||||
use super::{error::Message, Response};
|
||||
|
||||
const WF_CONTENT_TYPE: (&str, &str) = ("content-type", "application/jrd+json");
|
||||
|
||||
|
@ -23,8 +23,10 @@ pub fn resolve(cx: &Context, params: &[(&str, &str)]) -> Result<Response, Messag
|
|||
fuck!(500: "internal error");
|
||||
};
|
||||
let jrd = make_jrd(handle, &id);
|
||||
let encoded = serde_json::to_vec(&jrd).unwrap();
|
||||
Ok(respond(200, Some(encoded), [WF_CONTENT_TYPE]))
|
||||
Ok(respond! {
|
||||
body: Some(&jrd),
|
||||
kind: "application/jrd+json"
|
||||
})
|
||||
}
|
||||
Some(_) | None => fuck!(400: "missing/invalid resource param"),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue