From 7f885ce55b66025253175cde871c0df7dbb94171 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Fri, 4 Nov 2022 15:26:38 +0100 Subject: [PATCH 1/2] Forward inbox requests to Lemmy --- docker/nginx.conf | 11 +---- src/main.rs | 5 ++- src/routes/{redirects.rs => federation.rs} | 49 +++++++++++++++++++++- src/routes/mod.rs | 2 +- 4 files changed, 53 insertions(+), 14 deletions(-) rename src/routes/{redirects.rs => federation.rs} (51%) diff --git a/docker/nginx.conf b/docker/nginx.conf index 07eec16..fa3c4d1 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -57,16 +57,7 @@ server { # lemmybb frontend location / { - set $proxpass "http://0.0.0.0:8701"; - # federation requests go to backend - if ($http_accept ~ "^application/.*$") { - set $proxpass "http://0.0.0.0:8703"; - } - # fonts have similar accept header but need to be handled by frontend - if ($http_accept ~ "^application/font.*$") { - set $proxpass "http://0.0.0.0:8701"; - } - proxy_pass $proxpass; + proxy_pass "http://0.0.0.0:8701"; rewrite ^(.+)/+$ $1 permanent; } diff --git a/src/main.rs b/src/main.rs index 1623229..25a19d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,9 +20,9 @@ use crate::{ routes::{ comment::*, community::*, + federation::*, post::*, private_message::*, - redirects::*, site::*, user::*, }, @@ -114,7 +114,8 @@ fn init_rocket() -> Result, Error> { do_report, edit_profile, do_edit_profile, - community_list + community_list, + inboxes ], ) .mount("/assets", FileServer::from(relative!("assets")))) diff --git a/src/routes/redirects.rs b/src/routes/federation.rs similarity index 51% rename from src/routes/redirects.rs rename to src/routes/federation.rs index 481c9d3..3351b6f 100644 --- a/src/routes/redirects.rs +++ b/src/routes/federation.rs @@ -1,12 +1,16 @@ use crate::{ - api::{comment::get_comment, community::get_community, user::get_person, NameOrId}, + api::{comment::get_comment, community::get_community, user::get_person, NameOrId, CLIENT}, + env::lemmy_backend, error::ErrorPage, rocket_uri_macro_view_forum, rocket_uri_macro_view_profile, rocket_uri_macro_view_topic, routes::auth, }; +use anyhow::Error; +use reqwest::header::{HeaderMap, HeaderName, HeaderValue}; use rocket::{http::CookieJar, response::Redirect}; +use std::{path::PathBuf, str::FromStr}; #[get("/c/")] pub async fn redirect_apub_community( @@ -46,3 +50,46 @@ pub async fn redirect_apub_comment(t: i32, cookies: &CookieJar<'_>) -> Result", data = "")] +pub async fn inboxes( + path: PathBuf, + body: String, + headers: Headers<'_>, +) -> Result { + let url = format!("{}/{}", lemmy_backend(), path.to_str().unwrap()); + let headers = headers + .0 + .iter() + .map(|h| { + Ok(( + HeaderName::from_str(h.name.as_str())?, + HeaderValue::from_str(&h.value)?, + )) + }) + .collect::>()?; + + Ok(CLIENT + .post(url) + .headers(headers) + .body(body) + .send() + .await? + .text() + .await?) +} + +// Retrieve request headers +// https://github.com/SergioBenitez/Rocket/issues/178#issuecomment-953370904 +pub struct Headers<'r>(&'r rocket::http::HeaderMap<'r>); + +#[rocket::async_trait] +impl<'r> rocket::request::FromRequest<'r> for Headers<'r> { + type Error = std::convert::Infallible; + + async fn from_request( + req: &'r rocket::Request<'_>, + ) -> rocket::request::Outcome { + rocket::request::Outcome::Success(Headers(req.headers())) + } +} diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 0ff17ce..0f7c1cb 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,8 +1,8 @@ pub mod comment; pub mod community; +pub mod federation; pub mod post; pub mod private_message; -pub mod redirects; pub mod site; pub mod user; From ec789fc0ebea392c365e30171cd6389323ac8f48 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Fri, 4 Nov 2022 15:55:07 +0100 Subject: [PATCH 2/2] Forward activitypub fetches to Lemmy backend to simplify nginx routing --- src/main.rs | 8 ++-- src/routes/federation.rs | 85 ++++++++++++++++++++++++++++++---------- 2 files changed, 68 insertions(+), 25 deletions(-) diff --git a/src/main.rs b/src/main.rs index 25a19d3..250287d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -106,10 +106,10 @@ fn init_rocket() -> Result, Error> { private_message_editor, do_send_private_message, image, - redirect_apub_community, - redirect_apub_user, - redirect_apub_post, - redirect_apub_comment, + apub_community, + apub_user, + apub_post, + apub_comment, report, do_report, edit_profile, diff --git a/src/routes/federation.rs b/src/routes/federation.rs index 3351b6f..b72db6e 100644 --- a/src/routes/federation.rs +++ b/src/routes/federation.rs @@ -9,46 +9,75 @@ use crate::{ }; use anyhow::Error; use reqwest::header::{HeaderMap, HeaderName, HeaderValue}; -use rocket::{http::CookieJar, response::Redirect}; +use rocket::{ + http::CookieJar, + request::{FromRequest, Outcome}, + response::Redirect, + Either, +}; use std::{path::PathBuf, str::FromStr}; +type ReturnType = Result, ErrorPage>; + #[get("/c/")] -pub async fn redirect_apub_community( +pub async fn apub_community( name: String, + accept: AcceptHeader, cookies: &CookieJar<'_>, -) -> Result { +) -> ReturnType { + if accept.0.starts_with("application/") { + return foward_apub_fetch(format!("{}/c/{}", lemmy_backend(), name), accept).await; + } let community = get_community(NameOrId::Name(name), auth(cookies)).await?; let f = community.community_view.community.id.0; - Ok(Redirect::to(uri!(view_forum( + Ok(Either::Left(Redirect::to(uri!(view_forum( f, Some(1), Option::::None - )))) + ))))) } #[get("/u/")] -pub async fn redirect_apub_user( - name: String, - cookies: &CookieJar<'_>, -) -> Result { +pub async fn apub_user(name: String, accept: AcceptHeader, cookies: &CookieJar<'_>) -> ReturnType { + if accept.0.starts_with("application/") { + return foward_apub_fetch(format!("{}/u/{}", lemmy_backend(), name), accept).await; + } let user = get_person(NameOrId::Name(name), auth(cookies)).await?; let u = user.person_view.person.id.0; - Ok(Redirect::to(uri!(view_profile(u)))) + Ok(Either::Left(Redirect::to(uri!(view_profile(u))))) } #[get("/post/")] -pub async fn redirect_apub_post(id: i32) -> Redirect { - Redirect::to(uri!(view_topic(id, Some(1)))) +pub async fn apub_post(id: i32, accept: AcceptHeader) -> ReturnType { + if accept.0.starts_with("application/") { + return foward_apub_fetch(format!("{}/post/{}", lemmy_backend(), id), accept).await; + } + Ok(Either::Left(Redirect::to(uri!(view_topic(id, Some(1)))))) } #[get("/comment/")] -pub async fn redirect_apub_comment(t: i32, cookies: &CookieJar<'_>) -> Result { +pub async fn apub_comment(t: i32, accept: AcceptHeader, cookies: &CookieJar<'_>) -> ReturnType { + if accept.0.starts_with("application/") { + return foward_apub_fetch(format!("{}/comment/{}", lemmy_backend(), t), accept).await; + } let comment = get_comment(t, auth(cookies)).await?; // TODO: figure out actual page - Ok(Redirect::to(format!( - "/viewtopic?t={}&page=1#p{}", + Ok(Either::Left(Redirect::to(format!( + "/view_topic?t={}&page=1#p{}", t, comment.comment_view.comment.id - ))) + )))) +} + +/// In case an activitypub object is being fetched, forward request to Lemmy backend +async fn foward_apub_fetch(url: String, accept: AcceptHeader) -> ReturnType { + let res = CLIENT + .get(url) + .header("accept", accept.0) + .send() + .await? + .text() + .await?; + Ok(Either::Right(res)) } #[post("/", data = "")] @@ -84,12 +113,26 @@ pub async fn inboxes( pub struct Headers<'r>(&'r rocket::http::HeaderMap<'r>); #[rocket::async_trait] -impl<'r> rocket::request::FromRequest<'r> for Headers<'r> { +impl<'r> FromRequest<'r> for Headers<'r> { + type Error = std::convert::Infallible; + + async fn from_request(req: &'r rocket::Request<'_>) -> Outcome { + Outcome::Success(Headers(req.headers())) + } +} + +pub struct AcceptHeader(String); + +#[rocket::async_trait] +impl<'r> FromRequest<'r> for AcceptHeader { type Error = std::convert::Infallible; - async fn from_request( - req: &'r rocket::Request<'_>, - ) -> rocket::request::Outcome { - rocket::request::Outcome::Success(Headers(req.headers())) + async fn from_request(req: &'r rocket::Request<'_>) -> Outcome { + Outcome::Success(AcceptHeader( + req.headers() + .get_one("accept") + .unwrap_or_default() + .to_string(), + )) } }