feat: proxy should work for anything, more options

This commit is contained in:
əlemi 2024-06-07 06:20:25 +02:00
parent 8284130890
commit 43aea48816
Signed by: alemi
GPG key ID: A4895B84D311642C
5 changed files with 38 additions and 34 deletions

3
Cargo.lock generated
View file

@ -4782,6 +4782,7 @@ dependencies = [
"tower-http", "tower-http",
"tracing", "tracing",
"upub", "upub",
"uriproxy",
] ]
[[package]] [[package]]
@ -4834,7 +4835,7 @@ dependencies = [
[[package]] [[package]]
name = "uriproxy" name = "uriproxy"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
] ]

View file

@ -26,6 +26,7 @@ axum = "0.7"
tower-http = { version = "0.5", features = ["cors", "trace"] } tower-http = { version = "0.5", features = ["cors", "trace"] }
httpsign = { path = "../../utils/httpsign/", features = ["axum"] } httpsign = { path = "../../utils/httpsign/", features = ["axum"] }
apb = { path = "../../apb", features = ["unstructured", "orm", "activitypub-fe", "activitypub-counters", "litepub", "ostatus", "toot", "jsonld"] } 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"] } 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 = "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" } nodeinfo = { git = "https://codeberg.org/thefederationinfo/nodeinfo-rs", rev = "e865094804" }

View file

@ -1,9 +1,9 @@
use apb::{LD, ActorMut, BaseMut, ObjectMut, PublicKeyMut}; 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 reqwest::Method;
use upub::{traits::Fetcher, Context}; use upub::{traits::Fetcher, Context};
use crate::{builders::JsonLD, AuthIdentity}; use crate::{builders::JsonLD, AuthIdentity, Identity};
pub async fn view( pub async fn view(
@ -39,55 +39,56 @@ pub async fn view(
).into_response()) ).into_response())
} }
pub async fn proxy_path(
State(ctx): State<Context>,
AuthIdentity(auth): AuthIdentity,
Path(uri): Path<String>,
) -> crate::ApiResult<impl IntoResponse> {
let query = uriproxy::expand(&uri)
.ok_or_else(crate::ApiError::bad_request)?;
proxy(ctx, query, auth).await
}
#[derive(Debug, serde::Deserialize)] #[derive(Debug, serde::Deserialize)]
pub struct FetchPath { pub struct ProxyQuery {
id: String, uri: String,
} }
pub async fn proxy_get( pub async fn proxy_get(
State(ctx): State<Context>, State(ctx): State<Context>,
Query(query): Query<FetchPath>,
AuthIdentity(auth): AuthIdentity, AuthIdentity(auth): AuthIdentity,
) -> crate::ApiResult<Json<serde_json::Value>> { Query(query): Query<ProxyQuery>,
// only local users can request fetches ) -> crate::ApiResult<impl IntoResponse> {
if !ctx.cfg().security.allow_public_debugger && !auth.is_local() { proxy(ctx, query.uri, auth).await
return Err(crate::ApiError::unauthorized());
}
Ok(Json(
Context::request(
Method::GET,
&query.id,
None,
ctx.base(),
ctx.pkey(),
&format!("{}+proxy", ctx.domain()),
)
.await?
.json::<serde_json::Value>()
.await?
))
} }
pub async fn proxy_form( pub async fn proxy_form(
State(ctx): State<Context>, State(ctx): State<Context>,
AuthIdentity(auth): AuthIdentity, AuthIdentity(auth): AuthIdentity,
Form(query): Form<FetchPath>, Form(query): Form<String>,
) -> crate::ApiResult<Json<serde_json::Value>> { ) -> crate::ApiResult<impl IntoResponse> {
proxy(ctx, query, auth).await
}
async fn proxy(ctx: Context, query: String, auth: Identity) -> crate::ApiResult<impl IntoResponse> {
// only local users can request fetches // 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()); return Err(crate::ApiError::unauthorized());
} }
Ok(Json(
Context::request( let resp = Context::request(
Method::GET, Method::GET,
&query.id, &query,
None, None,
ctx.base(), ctx.base(),
ctx.pkey(), ctx.pkey(),
&format!("{}+proxy", ctx.domain()), &format!("{}+proxy", ctx.domain()),
) )
.await? .await?
.json::<serde_json::Value>() .error_for_status()?;
.await?
Ok((
resp.headers().clone(),
resp.bytes().await?.to_vec(),
)) ))
} }

View file

@ -21,8 +21,9 @@ impl ActivityPubRouter for Router<upub::Context> {
// core server inbox/outbox, maybe for feeds? TODO do we need these? // core server inbox/outbox, maybe for feeds? TODO do we need these?
.route("/", get(ap::application::view)) .route("/", get(ap::application::view))
// fetch route, to debug and retreive remote objects // fetch route, to debug and retreive remote objects
.route("/proxy", get(ap::application::proxy_get))
.route("/proxy", post(ap::application::proxy_form)) .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 // TODO shared inboxes and instance stream will come later, just use users *boxes for now
.route("/inbox", post(ap::inbox::post)) .route("/inbox", post(ap::inbox::post))
.route("/inbox", get(ap::inbox::get)) .route("/inbox", get(ap::inbox::get))

View file

@ -31,7 +31,7 @@ pub fn DebugPage() -> impl IntoView {
}, },
} }
} else { } 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
} }
} }
); );