Proxy pictshare requests (fixes #371)
This commit is contained in:
parent
3b12f92752
commit
a0e180994e
11 changed files with 137 additions and 7 deletions
1
ansible/templates/nginx.conf
vendored
1
ansible/templates/nginx.conf
vendored
|
@ -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;
|
||||
|
|
7
docker/dev/docker-compose.yml
vendored
7
docker/dev/docker-compose.yml
vendored
|
@ -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
2
docker/lemmy.hjson
vendored
|
@ -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
|
||||
|
|
5
docker/prod/docker-compose.yml
vendored
5
docker/prod/docker-compose.yml
vendored
|
@ -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
29
server/Cargo.lock
generated
vendored
|
@ -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
1
server/Cargo.toml
vendored
|
@ -33,3 +33,4 @@ rss = "1.8.0"
|
|||
htmlescape = "0.3.1"
|
||||
config = "0.10.1"
|
||||
hjson = "0.8.2"
|
||||
url = "1.7.1"
|
||||
|
|
2
server/config/defaults.hjson
vendored
2
server/config/defaults.hjson
vendored
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
76
server/src/routes/images.rs
Normal file
76
server/src/routes/images.rs
Normal 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?))
|
||||
}
|
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
Reference in a new issue