From 43aea48816b1e7f7f05b9cffd63a8269c1b7c6a7 Mon Sep 17 00:00:00 2001 From: alemi Date: Fri, 7 Jun 2024 06:20:25 +0200 Subject: [PATCH] feat: proxy should work for anything, more options --- Cargo.lock | 3 +- upub/routes/Cargo.toml | 1 + upub/routes/src/activitypub/application.rs | 63 +++++++++++----------- upub/routes/src/activitypub/mod.rs | 3 +- web/src/page/debug.rs | 2 +- 5 files changed, 38 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1607bd9..f53c1de6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4782,6 +4782,7 @@ dependencies = [ "tower-http", "tracing", "upub", + "uriproxy", ] [[package]] @@ -4834,7 +4835,7 @@ dependencies = [ [[package]] name = "uriproxy" -version = "0.1.0" +version = "0.1.1" dependencies = [ "base64 0.22.1", ] diff --git a/upub/routes/Cargo.toml b/upub/routes/Cargo.toml index 1a996d53..978525fd 100644 --- a/upub/routes/Cargo.toml +++ b/upub/routes/Cargo.toml @@ -26,6 +26,7 @@ axum = "0.7" tower-http = { version = "0.5", features = ["cors", "trace"] } httpsign = { path = "../../utils/httpsign/", features = ["axum"] } apb = { path = "../../apb", features = ["unstructured", "orm", "activitypub-fe", "activitypub-counters", "litepub", "ostatus", "toot", "jsonld"] } +uriproxy = { path = "../../utils/uriproxy" } sea-orm = { version = "0.12", features = ["macros", "sqlx-sqlite", "runtime-tokio-rustls"] } # nodeinfo = "0.0.2" # the version on crates.io doesn't re-export necessary types to build the struct!!! nodeinfo = { git = "https://codeberg.org/thefederationinfo/nodeinfo-rs", rev = "e865094804" } diff --git a/upub/routes/src/activitypub/application.rs b/upub/routes/src/activitypub/application.rs index 365e531a..a62e0180 100644 --- a/upub/routes/src/activitypub/application.rs +++ b/upub/routes/src/activitypub/application.rs @@ -1,9 +1,9 @@ use apb::{LD, ActorMut, BaseMut, ObjectMut, PublicKeyMut}; -use axum::{extract::{Query, State}, http::HeaderMap, response::{IntoResponse, Redirect, Response}, Form, Json}; +use axum::{extract::{Path, Query, State}, http::{HeaderMap, HeaderName, HeaderValue}, response::{IntoResponse, Redirect, Response}, Form, Json}; use reqwest::Method; use upub::{traits::Fetcher, Context}; -use crate::{builders::JsonLD, AuthIdentity}; +use crate::{builders::JsonLD, AuthIdentity, Identity}; pub async fn view( @@ -39,55 +39,56 @@ pub async fn view( ).into_response()) } +pub async fn proxy_path( + State(ctx): State, + AuthIdentity(auth): AuthIdentity, + Path(uri): Path, +) -> crate::ApiResult { + let query = uriproxy::expand(&uri) + .ok_or_else(crate::ApiError::bad_request)?; + proxy(ctx, query, auth).await +} + #[derive(Debug, serde::Deserialize)] -pub struct FetchPath { - id: String, +pub struct ProxyQuery { + uri: String, } pub async fn proxy_get( State(ctx): State, - Query(query): Query, AuthIdentity(auth): AuthIdentity, -) -> crate::ApiResult> { - // only local users can request fetches - if !ctx.cfg().security.allow_public_debugger && !auth.is_local() { - return Err(crate::ApiError::unauthorized()); - } - Ok(Json( - Context::request( - Method::GET, - &query.id, - None, - ctx.base(), - ctx.pkey(), - &format!("{}+proxy", ctx.domain()), - ) - .await? - .json::() - .await? - )) + Query(query): Query, +) -> crate::ApiResult { + proxy(ctx, query.uri, auth).await } pub async fn proxy_form( State(ctx): State, AuthIdentity(auth): AuthIdentity, - Form(query): Form, -) -> crate::ApiResult> { + Form(query): Form, +) -> crate::ApiResult { + proxy(ctx, query, auth).await +} + +async fn proxy(ctx: Context, query: String, auth: Identity) -> crate::ApiResult { // only local users can request fetches - if !ctx.cfg().security.allow_public_debugger && auth.is_local() { + if !ctx.cfg().security.allow_public_debugger && !auth.is_local() { return Err(crate::ApiError::unauthorized()); } - Ok(Json( - Context::request( + + let resp = Context::request( Method::GET, - &query.id, + &query, None, ctx.base(), ctx.pkey(), &format!("{}+proxy", ctx.domain()), ) .await? - .json::() - .await? + .error_for_status()?; + + Ok(( + resp.headers().clone(), + resp.bytes().await?.to_vec(), )) } diff --git a/upub/routes/src/activitypub/mod.rs b/upub/routes/src/activitypub/mod.rs index f7e74d28..f1ab91af 100644 --- a/upub/routes/src/activitypub/mod.rs +++ b/upub/routes/src/activitypub/mod.rs @@ -21,8 +21,9 @@ impl ActivityPubRouter for Router { // core server inbox/outbox, maybe for feeds? TODO do we need these? .route("/", get(ap::application::view)) // fetch route, to debug and retreive remote objects - .route("/proxy", get(ap::application::proxy_get)) .route("/proxy", post(ap::application::proxy_form)) + .route("/proxy", get(ap::application::proxy_get)) + .route("/proxy/:uri", get(ap::application::proxy_path)) // TODO shared inboxes and instance stream will come later, just use users *boxes for now .route("/inbox", post(ap::inbox::post)) .route("/inbox", get(ap::inbox::get)) diff --git a/web/src/page/debug.rs b/web/src/page/debug.rs index 08fa9d27..d11ed8f8 100644 --- a/web/src/page/debug.rs +++ b/web/src/page/debug.rs @@ -31,7 +31,7 @@ pub fn DebugPage() -> impl IntoView { }, } } else { - debug_fetch(&format!("{URL_BASE}/proxy?id={query}"), auth, set_error).await + debug_fetch(&format!("{URL_BASE}/proxy?uri={query}"), auth, set_error).await } } );