Merge pull request #78 from HeapUnderfl0w/public-path

Public Url for Paths
This commit is contained in:
Dániel Szabó 2022-10-25 12:24:33 +03:00 committed by GitHub
commit dc2c7094a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 112 additions and 31 deletions

View file

@ -330,6 +330,64 @@ Displays your MicroBin's version information.
Changes the maximum width of the UI from 720 pixels to 1080 pixels. 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-file-upload ### --no-file-upload
Disables and hides the file upload option in the UI. Disables and hides the file upload option in the UI.

View file

@ -1,4 +1,7 @@
use std::convert::Infallible;
use std::fmt;
use std::net::IpAddr; use std::net::IpAddr;
use std::str::FromStr;
use clap::Parser; use clap::Parser;
use lazy_static::lazy_static; use lazy_static::lazy_static;
@ -48,6 +51,9 @@ pub struct Args {
#[clap(long, env="MICROBIN_PURE_HTML")] #[clap(long, env="MICROBIN_PURE_HTML")]
pub pure_html: bool, 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")] #[clap(long, env="MICROBIN_READONLY")]
pub readonly: bool, pub readonly: bool,
@ -59,7 +65,24 @@ pub struct Args {
#[clap(long, env="MICROBIN_WIDE")] #[clap(long, env="MICROBIN_WIDE")]
pub wide: bool, pub wide: bool,
#[clap(short, long, env="MICROBIN_NO_FILE_UPLOAD")] #[clap(short, long, env="MICROBIN_NO_FILE_UPLOAD")]
pub no_file_upload: bool, pub no_file_upload: 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<Self, Self::Err> {
let uri = s.strip_suffix('/').unwrap_or(s).to_owned();
Ok(PublicUrl(uri))
}

View file

@ -32,7 +32,7 @@ pub async fn create(
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
if ARGS.readonly { if ARGS.readonly {
return Ok(HttpResponse::Found() return Ok(HttpResponse::Found()
.append_header(("Location", "/")) .append_header(("Location", format!("{}/", ARGS.public_path)))
.finish()); .finish());
} }
@ -158,6 +158,6 @@ pub async fn create(
save_to_file(&pastas); save_to_file(&pastas);
Ok(HttpResponse::Found() 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()) .finish())
} }

View file

@ -28,7 +28,7 @@ pub async fn get_edit(data: web::Data<AppState>, id: web::Path<String>) -> HttpR
if pasta.id == id { if pasta.id == id {
if !pasta.editable { if !pasta.editable {
return HttpResponse::Found() return HttpResponse::Found()
.append_header(("Location", "/")) .append_header(("Location", format!("{}/", ARGS.public_path)))
.finish(); .finish();
} }
return HttpResponse::Ok().content_type("text/html").body( return HttpResponse::Ok().content_type("text/html").body(
@ -55,7 +55,7 @@ pub async fn post_edit(
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
if ARGS.readonly { if ARGS.readonly {
return Ok(HttpResponse::Found() return Ok(HttpResponse::Found()
.append_header(("Location", "/")) .append_header(("Location", format!("{}/", ARGS.public_path)))
.finish()); .finish());
} }
@ -85,7 +85,7 @@ pub async fn post_edit(
save_to_file(&pastas); save_to_file(&pastas);
return Ok(HttpResponse::Found() 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()); .finish());
} else { } else {
break; break;

View file

@ -17,7 +17,7 @@ struct PastaListTemplate<'a> {
pub async fn list(data: web::Data<AppState>) -> HttpResponse { pub async fn list(data: web::Data<AppState>) -> HttpResponse {
if ARGS.no_listing { if ARGS.no_listing {
return HttpResponse::Found() return HttpResponse::Found()
.append_header(("Location", "/")) .append_header(("Location", format!("{}/", ARGS.public_path)))
.finish(); .finish();
} }

View file

@ -13,7 +13,7 @@ use std::fs;
pub async fn remove(data: web::Data<AppState>, id: web::Path<String>) -> HttpResponse { pub async fn remove(data: web::Data<AppState>, id: web::Path<String>) -> HttpResponse {
if ARGS.readonly { if ARGS.readonly {
return HttpResponse::Found() return HttpResponse::Found()
.append_header(("Location", "/")) .append_header(("Location", format!("{}/", ARGS.public_path)))
.finish(); .finish();
} }
@ -39,7 +39,7 @@ pub async fn remove(data: web::Data<AppState>, id: web::Path<String>) -> HttpRes
// remove it from in-memory pasta list // remove it from in-memory pasta list
pastas.remove(i); pastas.remove(i);
return HttpResponse::Found() return HttpResponse::Found()
.append_header(("Location", "/pastalist")) .append_header(("Location", format!("{}/pastalist", ARGS.public_path)))
.finish(); .finish();
} }
} }

View file

@ -4,7 +4,7 @@
<b>Not Found</b> <b>Not Found</b>
<br> <br>
<br> <br>
<a href="/" > Go Home</a> <a href="{{ args.public_path }}/" > Go Home</a>
<br> <br>
<br> <br>
{% include "footer.html" %} {% include "footer.html" %}

View file

@ -11,7 +11,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg"> <link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
{% if !args.pure_html %} {% if !args.pure_html %}
<link rel="stylesheet" href="/static/water.css"> <link rel="stylesheet" href="{{ args.public_path }}/static/water.css">
{%- endif %} {%- endif %}
</head> </head>
{% if args.wide %} {% if args.wide %}
@ -50,11 +50,11 @@
{%- endif %} {%- endif %}
</b> </b>
<a href="/" style="margin-right: 0.5rem; margin-left: 0.5rem">New Pasta</a> <a href="{{ args.public_path }}/" style="margin-right: 0.5rem; margin-left: 0.5rem">New Pasta</a>
<a href="/pastalist" style="margin-right: 0.5rem; margin-left: 0.5rem">Pasta List</a> <a href="{{ args.public_path }}/pastalist" style="margin-right: 0.5rem; margin-left: 0.5rem">Pasta List</a>
<a href="/help" style="margin-right: 0.5rem; margin-left: 0.5rem">Help</a> <a href="{{ args.public_path }}/help" style="margin-right: 0.5rem; margin-left: 0.5rem">Help</a>
<hr> <hr>

View file

@ -1,19 +1,19 @@
{% include "header.html" %} {% include "header.html" %}
<div style="float: left"> <div style="float: left">
<a style="margin-right: 0.5rem" href="/raw/{{pasta.id_as_animals()}}">Raw Text Content</a> <a style="margin-right: 0.5rem" href="{{ args.public_path }}/raw/{{pasta.id_as_animals()}}">Raw Text Content</a>
{% if pasta.file.is_some() %} {% if pasta.file.is_some() %}
<a style="margin-right: 0.5rem; margin-left: 0.5rem" <a style="margin-right: 0.5rem; margin-left: 0.5rem"
href="/file/{{pasta.id_as_animals()}}/{{pasta.file.as_ref().unwrap().name()}}"> href="{{ args.public_path }}/file/{{pasta.id_as_animals()}}/{{pasta.file.as_ref().unwrap().name()}}">
Attached file'{{pasta.file.as_ref().unwrap().name()}}' [{{pasta.file.as_ref().unwrap().size}}] Attached file'{{pasta.file.as_ref().unwrap().name()}}' [{{pasta.file.as_ref().unwrap().size}}]
</a> </a>
{%- endif %} {%- endif %}
{% if pasta.editable %} {% if pasta.editable %}
<a style="margin-right: 0.5rem; margin-left: 0.5rem" href="/edit/{{pasta.id_as_animals()}}">Edit</a> <a style="margin-right: 0.5rem; margin-left: 0.5rem" href="{{ args.public_path }}/edit/{{pasta.id_as_animals()}}">Edit</a>
{%- endif %} {%- endif %}
<a style="margin-right: 0.5rem; margin-left: 0.5rem" href="/remove/{{pasta.id_as_animals()}}">Remove</a> <a style="margin-right: 0.5rem; margin-left: 0.5rem" href="{{ args.public_path }}/remove/{{pasta.id_as_animals()}}">Remove</a>
</div> </div>
<div style="float: right"> <div style="float: right">
<a href="/pasta/{{pasta.id_as_animals()}}"><i>{{pasta.id_as_animals()}}</i></a> <a href="{{ args.public_path }}/pasta/{{pasta.id_as_animals()}}"><i>{{pasta.id_as_animals()}}</i></a>
</div> </div>
<br> <br>
<div class="code-container"> <div class="code-container">

View file

@ -4,7 +4,7 @@
{% if pastas.is_empty() %} {% if pastas.is_empty() %}
<br> <br>
<p> <p>
No pastas yet. 😔 Create one <a href="/">here</a>. No pastas yet. 😔 Create one <a href="{{ args.public_path }}/">here</a>.
</p> </p>
<br> <br>
{%- else %} {%- else %}
@ -38,7 +38,7 @@
{% if pasta.pasta_type == "text" && !pasta.private %} {% if pasta.pasta_type == "text" && !pasta.private %}
<tr> <tr>
<td> <td>
<a href="/pasta/{{pasta.id_as_animals()}}">{{pasta.id_as_animals()}}</a> <a href="{{ args.public_path }}/pasta/{{pasta.id_as_animals()}}">{{pasta.id_as_animals()}}</a>
</td> </td>
<td> <td>
{{pasta.created_as_string()}} {{pasta.created_as_string()}}
@ -47,14 +47,14 @@
{{pasta.expiration_as_string()}} {{pasta.expiration_as_string()}}
</td> </td>
<td> <td>
<a style="margin-right:1rem" href="/raw/{{pasta.id_as_animals()}}">Raw</a> <a style="margin-right:1rem" href="{{ args.public_path }}/raw/{{pasta.id_as_animals()}}">Raw</a>
{% if pasta.file.is_some() %} {% if pasta.file.is_some() %}
<a style="margin-right:1rem" href="/file/{{pasta.id_as_animals()}}/{{pasta.file.as_ref().unwrap().name()}}">File</a> <a style="margin-right:1rem" href="{{ args.public_path }}/file/{{pasta.id_as_animals()}}/{{pasta.file.as_ref().unwrap().name()}}">File</a>
{%- endif %} {%- endif %}
{% if pasta.editable %} {% if pasta.editable %}
<a style="margin-right:1rem" href="/edit/{{pasta.id_as_animals()}}">Edit</a> <a style="margin-right:1rem" href="{{ args.public_path }}/edit/{{pasta.id_as_animals()}}">Edit</a>
{%- endif %} {%- endif %}
<a href="/remove/{{pasta.id_as_animals()}}">Remove</a> <a href="{{ args.public_path }}/remove/{{pasta.id_as_animals()}}">Remove</a>
</td> </td>
</tr> </tr>
{%- endif %} {%- endif %}
@ -90,7 +90,7 @@
{% if pasta.pasta_type == "url" && !pasta.private %} {% if pasta.pasta_type == "url" && !pasta.private %}
<tr> <tr>
<td> <td>
<a href="/url/{{pasta.id_as_animals()}}">{{pasta.id_as_animals()}}</a> <a href="{{ args.public_path }}/url/{{pasta.id_as_animals()}}">{{pasta.id_as_animals()}}</a>
</td> </td>
<td> <td>
{{pasta.created_as_string()}} {{pasta.created_as_string()}}
@ -99,11 +99,11 @@
{{pasta.expiration_as_string()}} {{pasta.expiration_as_string()}}
</td> </td>
<td> <td>
<a style="margin-right:1rem" href="/raw/{{pasta.id_as_animals()}}">Raw</a> <a style="margin-right:1rem" href="{{ args.public_path }}raw/{{pasta.id_as_animals()}}">Raw</a>
{% if pasta.editable %} {% if pasta.editable %}
<a style="margin-right:1rem" href="/edit/{{pasta.id_as_animals()}}">Edit</a> <a style="margin-right:1rem" href="{{ args.public_path }}/edit/{{pasta.id_as_animals()}}">Edit</a>
{%- endif %} {%- endif %}
<a href="/remove/{{pasta.id_as_animals()}}">Remove</a> <a href="{{ args.public_path }}/remove/{{pasta.id_as_animals()}}">Remove</a>
</td> </td>
</tr> </tr>
{%- endif %} {%- endif %}