Proxy pictshare requests (fixes #371)

This commit is contained in:
Felix 2020-01-11 19:20:37 +01:00
parent 3b12f92752
commit a0e180994e
11 changed files with 137 additions and 7 deletions

View file

@ -70,6 +70,7 @@ server {
proxy_cache_min_uses 5;
}
# TODO: probably remove this (at least the proxy_pass)
location /pictshare/ {
proxy_pass http://0.0.0.0:8537/;
proxy_set_header X-Real-IP $remote_addr;

View file

@ -14,6 +14,8 @@ services:
build:
context: ../../
dockerfile: docker/dev/Dockerfile
environment:
- RUST_LOG=actix_web=info
ports:
- "127.0.0.1:8536:8536"
restart: always
@ -21,10 +23,9 @@ services:
- ../lemmy.hjson:/config/config.hjson:ro
depends_on:
- lemmy_db
lemmy_pictshare:
- pictshare
pictshare:
image: shtripok/pictshare:latest
ports:
- "127.0.0.1:8537:80"
volumes:
- lemmy_pictshare:/usr/share/nginx/html/data
restart: always

2
docker/lemmy.hjson vendored
View file

@ -23,6 +23,8 @@
jwt_secret: "changeme"
# The dir for the front end
front_end_dir: "/app/dist"
# The url where pictshare is available (this should only be exposed to lemmy, not to the outside)
pictshare_url: "http://pictshare:80"
# whether to enable activitypub federation. this feature is in alpha, do not enable in production, as might
# cause problems like remote instances fetching and permanently storing bad data.
federation_enabled: false

View file

@ -19,10 +19,9 @@ services:
- ./lemmy.hjson:/config/config.hjson:ro
depends_on:
- lemmy_db
lemmy_pictshare:
- pictshare
pictshare:
image: shtripok/pictshare:latest
ports:
- "127.0.0.1:8537:80"
volumes:
- lemmy_pictshare:/usr/share/nginx/html/data
restart: always

29
server/Cargo.lock generated vendored
View file

@ -1206,6 +1206,16 @@ name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "idna"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "idna"
version = "0.2.0"
@ -1323,6 +1333,7 @@ dependencies = [
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"strum 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strum_macros 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1650,6 +1661,11 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "percent-encoding"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "percent-encoding"
version = "2.1.0"
@ -2503,6 +2519,16 @@ name = "untrusted"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "url"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "url"
version = "2.1.0"
@ -2781,6 +2807,7 @@ dependencies = [
"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2"
"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
@ -2827,6 +2854,7 @@ dependencies = [
"checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f"
"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
"checksum pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469"
"checksum pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355"
@ -2928,6 +2956,7 @@ dependencies = [
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61"
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"

1
server/Cargo.toml vendored
View file

@ -33,3 +33,4 @@ rss = "1.8.0"
htmlescape = "0.3.1"
config = "0.10.1"
hjson = "0.8.2"
url = "1.7.1"

View file

@ -24,6 +24,8 @@
jwt_secret: "changeme"
# The dir for the front end
front_end_dir: "../ui/dist"
# The url where pictshare is available (this should only be exposed to lemmy, not to the outside)
pictshare_url: "http://localhost:80"
# whether to enable activitypub federation. this feature is in alpha, do not enable in production, as might
# cause problems like remote instances fetching and permanently storing bad data.
federation_enabled: false

View file

@ -3,10 +3,12 @@ extern crate lemmy_server;
extern crate diesel_migrations;
use actix::prelude::*;
use actix_web::middleware::Logger;
use actix_web::*;
use diesel::r2d2::{ConnectionManager, Pool};
use diesel::PgConnection;
use lemmy_server::routes::{api, federation, feeds, index, nodeinfo, webfinger, websocket};
use env_logger;
use lemmy_server::routes::{api, federation, feeds, images, index, nodeinfo, webfinger, websocket};
use lemmy_server::settings::Settings;
use lemmy_server::websocket::server::*;
use std::io;
@ -45,8 +47,10 @@ async fn main() -> io::Result<()> {
.data(server.clone())
// The routes
.configure(api::config)
.wrap(Logger::default())
.configure(federation::config)
.configure(feeds::config)
.configure(images::config)
.configure(index::config)
.configure(nodeinfo::config)
.configure(webfinger::config)

View file

@ -0,0 +1,76 @@
use crate::settings::Settings;
use actix_web::{web, Error, HttpRequest, HttpResponse};
use crate::routes::get_jwt_token_from_cookies;
use actix_web::client::Client;
use url::Url;
pub fn config(cfg: &mut web::ServiceConfig) {
cfg
.data(Client::new())
.route("/pictshare/api/upload.php", web::post().to(upload))
.route("/pictshare/{image}", web::get().to(get_image))
.route(
"/pictshare/{resolution}/{image}",
web::get().to(get_thumbnail),
);
}
/// For uploads, check the jwt token to make sure the user is logged in.
async fn upload(
req: HttpRequest,
body: web::Bytes,
client: web::Data<Client>,
) -> Result<HttpResponse, Error> {
match get_jwt_token_from_cookies(req.headers()) {
Ok(_) => forward(req, body, client, "/api/upload.php").await,
Err(_) => Ok(HttpResponse::Forbidden().finish()),
}
}
async fn get_image(
req: HttpRequest,
body: web::Bytes,
client: web::Data<Client>,
path: web::Path<String>,
) -> Result<HttpResponse, Error> {
forward(req, body, client, &path.into_inner()).await
}
async fn get_thumbnail(
req: HttpRequest,
body: web::Bytes,
client: web::Data<Client>,
path: web::Path<(String, String)>,
) -> Result<HttpResponse, Error> {
forward(req, body, client, &format!("/{}/{}", path.0, path.1)).await
}
/// Based on https://github.com/actix/examples/blob/master/http-proxy/src/main.rs
async fn forward(
req: HttpRequest,
body: web::Bytes,
client: web::Data<Client>,
path: &str,
) -> Result<HttpResponse, Error> {
let mut new_url = match Url::parse(&Settings::get().pictshare_url) {
Ok(u) => u,
Err(_) => return Ok(HttpResponse::InternalServerError().finish()),
};
new_url.set_path(path);
let forwarded_req = client
.request_from(new_url.as_str(), req.head())
.no_decompress();
let mut res = forwarded_req.send_body(body).await.map_err(Error::from)?;
let mut client_resp = HttpResponse::build(res.status());
// Remove `Connection` as per
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection#Directives
for (header_name, header_value) in res.headers().iter().filter(|(h, _)| *h != "connection") {
client_resp.header(header_name.clone(), header_value.clone());
}
Ok(client_resp.body(res.body().await?))
}

View file

@ -1,7 +1,21 @@
pub mod api;
use crate::db::user::Claims;
use actix_web::http::HeaderMap;
use jsonwebtoken::TokenData;
pub mod federation;
pub mod feeds;
pub mod images;
pub mod index;
pub mod nodeinfo;
pub mod webfinger;
pub mod websocket;
fn get_jwt_token_from_cookies(headers: &HeaderMap) -> Result<TokenData<Claims>, failure::Error> {
// TODO: this parsing will break if we add any new cookies
let jwt = headers.get("Cookie").unwrap().to_str()?;
match Claims::decode(&jwt.replace("jwt=", "")) {
Ok(o) => Ok(o),
Err(e) => Err(format_err!("{}", e)),
}
}

View file

@ -18,6 +18,7 @@ pub struct Settings {
pub rate_limit: RateLimitConfig,
pub email: Option<EmailConfig>,
pub federation_enabled: bool,
pub pictshare_url: String,
}
#[derive(Debug, Deserialize)]