From a404f9a997da70e97c63b615044f7d8138976e4b Mon Sep 17 00:00:00 2001 From: HeapUnderflow Date: Wed, 12 Oct 2022 17:13:21 +0200 Subject: [PATCH 1/3] Allow setting a public url for all paths --- src/args.rs | 24 ++++++++++++++++++++++++ src/endpoints/create.rs | 4 ++-- src/endpoints/edit.rs | 6 +++--- src/endpoints/pastalist.rs | 2 +- src/endpoints/remove.rs | 4 ++-- templates/error.html | 2 +- templates/header.html | 8 ++++---- templates/pasta.html | 10 +++++----- templates/pastalist.html | 20 ++++++++++---------- 9 files changed, 52 insertions(+), 28 deletions(-) diff --git a/src/args.rs b/src/args.rs index 577fa0f..37b6461 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,4 +1,7 @@ +use std::convert::Infallible; +use std::fmt; use std::net::IpAddr; +use std::str::FromStr; use clap::Parser; use lazy_static::lazy_static; @@ -48,6 +51,9 @@ pub struct Args { #[clap(long, env="MICROBIN_PURE_HTML")] pub pure_html: bool, + #[clap(long, env="MICROBIN_PUBLIC_PATH", default_value_t = PublicUrl(String::from("/")))] + pub public_path: PublicUrl, + #[clap(long, env="MICROBIN_READONLY")] pub readonly: bool, @@ -59,4 +65,22 @@ pub struct Args { #[clap(long, env="MICROBIN_WIDE")] pub wide: bool, +} + +#[derive(Debug, Clone)] +pub struct PublicUrl(pub String); + +impl fmt::Display for PublicUrl { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl FromStr for PublicUrl { + type Err = Infallible; + + fn from_str(s: &str) -> Result { + let uri = s.strip_suffix('/').unwrap_or(s).to_owned(); + Ok(PublicUrl(uri)) + } } \ No newline at end of file diff --git a/src/endpoints/create.rs b/src/endpoints/create.rs index 8c8b1a3..fe39c94 100644 --- a/src/endpoints/create.rs +++ b/src/endpoints/create.rs @@ -32,7 +32,7 @@ pub async fn create( ) -> Result { if ARGS.readonly { return Ok(HttpResponse::Found() - .append_header(("Location", "/")) + .append_header(("Location", format!("{}/", ARGS.public_path))) .finish()); } @@ -154,6 +154,6 @@ pub async fn create( save_to_file(&pastas); Ok(HttpResponse::Found() - .append_header(("Location", format!("/pasta/{}", to_animal_names(id)))) + .append_header(("Location", format!("{}/pasta/{}", ARGS.public_path, to_animal_names(id)))) .finish()) } diff --git a/src/endpoints/edit.rs b/src/endpoints/edit.rs index f928324..54ef1f6 100644 --- a/src/endpoints/edit.rs +++ b/src/endpoints/edit.rs @@ -28,7 +28,7 @@ pub async fn get_edit(data: web::Data, id: web::Path) -> HttpR if pasta.id == id { if !pasta.editable { return HttpResponse::Found() - .append_header(("Location", "/")) + .append_header(("Location", format!("{}/", ARGS.public_path))) .finish(); } return HttpResponse::Ok().content_type("text/html").body( @@ -55,7 +55,7 @@ pub async fn post_edit( ) -> Result { if ARGS.readonly { return Ok(HttpResponse::Found() - .append_header(("Location", "/")) + .append_header(("Location", format!("{}/", ARGS.public_path))) .finish()); } @@ -85,7 +85,7 @@ pub async fn post_edit( save_to_file(&pastas); return Ok(HttpResponse::Found() - .append_header(("Location", format!("/pasta/{}", pastas[i].id_as_animals()))) + .append_header(("Location", format!("{}/pasta/{}", ARGS.public_path, pastas[i].id_as_animals()))) .finish()); } else { break; diff --git a/src/endpoints/pastalist.rs b/src/endpoints/pastalist.rs index 3e3dec4..e2536e5 100644 --- a/src/endpoints/pastalist.rs +++ b/src/endpoints/pastalist.rs @@ -17,7 +17,7 @@ struct PastaListTemplate<'a> { pub async fn list(data: web::Data) -> HttpResponse { if ARGS.no_listing { return HttpResponse::Found() - .append_header(("Location", "/")) + .append_header(("Location", format!("{}/", ARGS.public_path))) .finish(); } diff --git a/src/endpoints/remove.rs b/src/endpoints/remove.rs index 7b95553..6d552b0 100644 --- a/src/endpoints/remove.rs +++ b/src/endpoints/remove.rs @@ -13,7 +13,7 @@ use std::fs; pub async fn remove(data: web::Data, id: web::Path) -> HttpResponse { if ARGS.readonly { return HttpResponse::Found() - .append_header(("Location", "/")) + .append_header(("Location", format!("{}/", ARGS.public_path))) .finish(); } @@ -39,7 +39,7 @@ pub async fn remove(data: web::Data, id: web::Path) -> HttpRes // remove it from in-memory pasta list pastas.remove(i); return HttpResponse::Found() - .append_header(("Location", "/pastalist")) + .append_header(("Location", format!("{}/pastalist", ARGS.public_path))) .finish(); } } diff --git a/templates/error.html b/templates/error.html index 05f55d5..6e60b7c 100644 --- a/templates/error.html +++ b/templates/error.html @@ -4,7 +4,7 @@ Not Found

- Go Home + Go Home

{% include "footer.html" %} diff --git a/templates/header.html b/templates/header.html index 37d2de0..96729da 100644 --- a/templates/header.html +++ b/templates/header.html @@ -10,7 +10,7 @@ {% if !args.pure_html %} - + {%- endif %} {% if args.wide %} @@ -49,11 +49,11 @@ {%- endif %} -New Pasta +New Pasta -Pasta List +Pasta List -Help +Help
diff --git a/templates/pasta.html b/templates/pasta.html index 879c948..9514702 100644 --- a/templates/pasta.html +++ b/templates/pasta.html @@ -1,19 +1,19 @@ {% include "header.html" %}
diff --git a/templates/pastalist.html b/templates/pastalist.html index 4de2d2b..c3d15a2 100644 --- a/templates/pastalist.html +++ b/templates/pastalist.html @@ -4,7 +4,7 @@ {% if pastas.is_empty() %}

- No pastas yet. 😔 Create one here. + No pastas yet. 😔 Create one here.


{%- else %} @@ -38,7 +38,7 @@ {% if pasta.pasta_type == "text" && !pasta.private %} - {{pasta.id_as_animals()}} + {{pasta.id_as_animals()}} {{pasta.created_as_string()}} @@ -47,14 +47,14 @@ {{pasta.expiration_as_string()}} - Raw + Raw {% if pasta.file.is_some() %} - File + File {%- endif %} {% if pasta.editable %} - Edit + Edit {%- endif %} - Remove + Remove {%- endif %} @@ -90,7 +90,7 @@ {% if pasta.pasta_type == "url" && !pasta.private %} - {{pasta.id_as_animals()}} + {{pasta.id_as_animals()}} {{pasta.created_as_string()}} @@ -99,11 +99,11 @@ {{pasta.expiration_as_string()}} - Raw + Raw {% if pasta.editable %} - Edit + Edit {%- endif %} - Remove + Remove {%- endif %} From cfd494f80dae4cc9da5aad491f632c07861dd053 Mon Sep 17 00:00:00 2001 From: HeapUnderflow Date: Wed, 12 Oct 2022 17:42:42 +0200 Subject: [PATCH 2/3] Do not append a second slash when no public path is set --- src/args.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/args.rs b/src/args.rs index 37b6461..ac5b525 100644 --- a/src/args.rs +++ b/src/args.rs @@ -51,7 +51,7 @@ pub struct Args { #[clap(long, env="MICROBIN_PURE_HTML")] pub pure_html: bool, - #[clap(long, env="MICROBIN_PUBLIC_PATH", default_value_t = PublicUrl(String::from("/")))] + #[clap(long, env="MICROBIN_PUBLIC_PATH", default_value_t = PublicUrl(String::from("")))] pub public_path: PublicUrl, #[clap(long, env="MICROBIN_READONLY")] From 4980d72df278a2c4a15efdef8d3d482cffad7bf2 Mon Sep 17 00:00:00 2001 From: HeapUnderflow Date: Mon, 24 Oct 2022 12:55:09 +0200 Subject: [PATCH 3/3] Add example to README.MD --- README.MD | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/README.MD b/README.MD index 18006f6..b24f7a6 100644 --- a/README.MD +++ b/README.MD @@ -329,3 +329,61 @@ Displays your MicroBin's version information. ### --wide Changes the maximum width of the UI from 720 pixels to 1080 pixels. + +### --public-path [PUBLIC_PATH] + +Add the given public path prefix to all urls. + +This allows you to host MicroBin behind a reverse proxy on a subpath. +Note that MicroBin itself still expects all routes to be as without this option, and thus is unsuited +if you are running MicroBin directly. + +#### Example Usage (caddy) + +An example of running MicroBin behind the reverse proxy `caddy` on the path `/paste` (using systemd) + +**microbin.service** + +```unit file (systemd) +[Unit] +Description=Micobin Paste + +[Service] +Type=simple +User=microbin +# Path to your binary +ExecStart=/home/microbin/microbin/target/release/microbin +# Set your desired working directory, eg where microbin places its data +WorkingDirectory=/home/pi/bin/micro + +# bind to localhost, as its exposed via Caddy +Environment=MICROBIN_BIND=127.0.0.1 +# bind to a unused port +Environment=MICROBIN_PORT=31333 +# All your other config (change and add as needed) +Environment=MICROBIN_EDITABLE=true +Environment=MICROBIN_HIGHLIGHTSYNTAX=true +Environment=MICROBIN_THREADS=2 +Environment=MICROBIN_FOOTER_TEXT="Bin the bytes" +# Set your **public** url. Eg the one you will later use to access microbin +# Ensure it either starts with http(s):// or with a / +Environment=MICROBIN_PUBLIC_PATH="http://100.127.233.32/paste" + +[Install] +WantedBy=multi-user.target +``` + +**Caddyfile** + +```caddy +example.com { + # Your normal http root + root * /var/www/html + file_server + + # Route all requests to past + handle_path /paste/* { + reverse_proxy http://127.0.0.1:31333 + } +} +``` \ No newline at end of file