Compare commits

...

2 commits

Author SHA1 Message Date
6eb964275e
docs: add media proxy cache example for nginx 2024-07-16 00:52:51 +02:00
af5f5e2554
fix: oops not yet stable if let && 2024-07-16 00:52:25 +02:00
3 changed files with 43 additions and 8 deletions

View file

@ -34,6 +34,32 @@ most instances will have "authorized fetch" which kind of makes the issue less b
note that followers get expanded: addressing to example.net/actor/followers will address to anyone following actor that the server knows of, at that time
## media caching
μpub doesn't download remote media to both minimize local resources requirement and avoid storing media that remotes want gone. to prevent leaking local user ip addresses, all media links are cloaked and proxied.
while this just works for small instances, larger servers should set up aggressive caching on `/proxy/...` path
for example, on `nginx`:
```nginx
proxy_cache_path /tmp/upub/cache levels=1:2 keys_zone=upub_cache:100m max_size=50g inactive=168h use_temp_path=off;
server {
location /proxy/ {
# use our configured cache
slice 1m;
proxy_set_header Range $slice_range;
chunked_transfer_encoding on;
proxy_buffering on;
proxy_cache upub_cache;
proxy_cache_key $host$uri$is_args$args$slice_range;
proxy_cache_valid 200 206 301 304 1h;
proxy_cache_lock on;
proxy_pass http://127.0.0.1/;
}
}
```
## contributing
all help is extremely welcome! development mostly happens on [moonlit.technology](https://moonlit.technology/alemi/upub.git), but there's a [github mirror](https://github.com/alemidev/upub) available too

View file

@ -1,12 +1,12 @@
use futures::TryStreamExt;
use sea_orm::{ActiveModelTrait, ActiveValue::{Set, Unchanged}, ColumnTrait, Condition, EntityTrait, IntoActiveModel, QueryFilter, QuerySelect, SelectColumns, TransactionTrait};
use sea_orm::{ActiveModelTrait, ActiveValue::{NotSet, Set, Unchanged}, ColumnTrait, Condition, EntityTrait, IntoActiveModel, QueryFilter, QuerySelect, SelectColumns};
use upub::traits::{fetch::RequestError, Cloaker};
pub async fn cloak(ctx: upub::Context, post_contents: bool, actors: bool) -> Result<(), RequestError> {
let local_base = format!("{}%", ctx.base()));
let local_base = format!("{}%", ctx.base());
{
let mut stream = upub::model::attachment::Entity::find()
.filter(upub::model::attachment::Column::Url.not_like(&local_base)
.filter(upub::model::attachment::Column::Url.not_like(&local_base))
.stream(ctx.db())
.await?;
@ -60,13 +60,22 @@ pub async fn cloak(ctx: upub::Context, post_contents: bool, actors: bool) -> Res
while let Some((internal, image, icon)) = stream.try_next().await? {
if image.is_none() && icon.is_none() { continue }
let image = if let Some(img) = image && !img.starts_with(ctx.base()) {
Set(ctx.cloaked(&img))
// TODO can this if/else/else be made nicer??
let image = if let Some(img) = image {
if !img.starts_with(ctx.base()) {
Set(Some(ctx.cloaked(&img)))
} else {
NotSet
}
} else {
NotSet
};
let icon = if let Some(icn) = icon && !icn.starts_with(ctx.base()) {
Set(ctx.cloaked(&icn))
let icon = if let Some(icn) = icon {
if !icn.starts_with(ctx.base()) {
Set(Some(ctx.cloaked(&icn)))
} else {
NotSet
}
} else {
NotSet
};

View file

@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use apb::{Activity, Actor, ActorMut, Base, Collection, Object};
use reqwest::{header::{ACCEPT, CONTENT_TYPE, USER_AGENT}, Method, Response};
use sea_orm::{ConnectionTrait, DbErr, EntityTrait, IntoActiveModel, NotSet, ActiveValue::{Set, NotSet, Unchanged}};
use sea_orm::{ConnectionTrait, DbErr, EntityTrait, IntoActiveModel, NotSet, ActiveValue::Set};
use crate::traits::normalize::AP;