Skip to content

Commit 1b90873

Browse files
committed
Support path prefix in reverse proxy scenarios.
1 parent aac3d94 commit 1b90873

8 files changed

Lines changed: 44 additions & 22 deletions

File tree

crates/wastebin_server/src/main.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use http::header::{
2323
X_XSS_PROTECTION,
2424
};
2525
use tokio::net::{TcpListener, UnixListener};
26+
use tokio::task_local;
2627
use tower::ServiceBuilder;
2728
use tower_http::compression::CompressionLayer;
2829
use tower_http::timeout::TimeoutLayer;
@@ -34,6 +35,14 @@ use crate::handlers::extract::Theme;
3435
use crate::handlers::{delete, download, html, insert, raw, robots, theme};
3536
use wastebin_core::db::Database;
3637

38+
task_local! {
39+
pub static PATH_PREFIX: String;
40+
}
41+
42+
pub fn path_prefix() -> String {
43+
PATH_PREFIX.with(|val| val.to_string())
44+
}
45+
3746
/// Reference counted [`page::Page`] wrapper.
3847
pub(crate) type Page = Arc<page::Page>;
3948

@@ -79,6 +88,17 @@ impl FromRef<AppState> for Cache {
7988
}
8089
}
8190

91+
async fn path_prefix_layer(req: Request, next: Next) -> Response {
92+
let prefix = req
93+
.headers()
94+
.get("x-forwarded-prefix")
95+
.and_then(|val| val.to_str().ok())
96+
.unwrap_or("")
97+
.to_string();
98+
99+
PATH_PREFIX.scope(prefix, next.run(req)).await
100+
}
101+
82102
async fn security_headers_layer(req: Request, next: Next) -> impl IntoResponse {
83103
const SECURITY_HEADERS: [(HeaderName, HeaderValue); 7] = [
84104
(SERVER, HeaderValue::from_static(env!("CARGO_PKG_NAME"))),
@@ -213,6 +233,7 @@ fn make_app(state: AppState, timeout: Duration, max_body_size: usize) -> Router
213233
timeout,
214234
))
215235
.layer(from_fn_with_state(state.clone(), handle_service_errors))
236+
.layer(from_fn(path_prefix_layer))
216237
.layer(from_fn(security_headers_layer)),
217238
)
218239
.with_state(state)

crates/wastebin_server/templates/base.html

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{% let path_prefix = crate::path_prefix() %}
12
<!DOCTYPE html>
23
<html lang="en">
34
<head>
@@ -7,26 +8,26 @@
78
<title>{{ page.title }}{% block title_content %}{% endblock %}</title>
89
{% match theme %}
910
{% when Some with (Theme::Dark) %}
10-
<link rel="stylesheet" href="{{ page.assets.css.dark.route() }}">
11+
<link rel="stylesheet" href="{{ path_prefix }}{{ page.assets.css.dark.route() }}">
1112
{% when Some with (Theme::Light) %}
12-
<link rel="stylesheet" href="{{ page.assets.css.light.route() }}">
13+
<link rel="stylesheet" href="{{ path_prefix }}{{ page.assets.css.light.route() }}">
1314
{% when Some with (Theme::System) %}
14-
<link rel="stylesheet" href="{{ page.assets.css.dark.route() }}" media="(prefers-color-scheme: dark)">
15-
<link rel="stylesheet" href="{{ page.assets.css.light.route() }}" media="(prefers-color-scheme: light)">
15+
<link rel="stylesheet" href="{{ path_prefix }}{{ page.assets.css.dark.route() }}" media="(prefers-color-scheme: dark)">
16+
<link rel="stylesheet" href="{{ path_prefix }}{{ page.assets.css.light.route() }}" media="(prefers-color-scheme: light)">
1617
{% when None %}
17-
<link rel="stylesheet" href="{{ page.assets.css.dark.route() }}" media="(prefers-color-scheme: dark)">
18-
<link rel="stylesheet" href="{{ page.assets.css.light.route() }}" media="(prefers-color-scheme: light)">
18+
<link rel="stylesheet" href="{{ path_prefix }}{{ page.assets.css.dark.route() }}" media="(prefers-color-scheme: dark)">
19+
<link rel="stylesheet" href="{{ path_prefix }}{{ page.assets.css.light.route() }}" media="(prefers-color-scheme: light)">
1920
{% endmatch %}
20-
<link rel="stylesheet" href="{{ page.assets.css.style.route() }}">
21-
<link rel="icon" href="{{ page.assets.favicon.route() }}" type="image/png">
21+
<link rel="stylesheet" href="{{ path_prefix }}{{ page.assets.css.style.route() }}">
22+
<link rel="icon" href="{{ path_prefix }}{{ page.assets.favicon.route() }}" type="image/png">
2223
{% block head %}{% endblock %}
2324
</head>
2425
<body>
2526
<div id="main-container">
2627
<header>
2728
<div class="nav-group">
2829
<div class="nav-item">
29-
<a href="/" class="nav-button" title="home" aria-label="home">
30+
<a href="{{ path_prefix }}/" class="nav-button" title="home" aria-label="home">
3031
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
3132
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m4 12 8-8 8 8M6 10.5V19a1 1 0 0 0 1 1h3v-3a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3h3a1 1 0 0 0 1-1v-8.5"/>
3233
</svg>
@@ -40,30 +41,30 @@
4041
{% match theme %}
4142
{% when None %}
4243
<div class="nav-item" id="dark-switch">
43-
<a href="/theme?pref=dark" class="nav-button" title="switch to dark" aria-label="switch to dark">
44+
<a href="{{ path_prefix }}/theme?pref=dark" class="nav-button" title="switch to dark" aria-label="switch to dark">
4445
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
4546
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 21a9 9 0 0 1-.5-17.986V3c-.354.966-.5 1.911-.5 3a9 9 0 0 0 9 9c.239 0 .254.018.488 0A9.004 9.004 0 0 1 12 21Z"/>
4647
</svg>
4748
</a>
4849
</div>
4950
{% when Some with (Theme::System) %}
5051
<div class="nav-item" id="dark-switch">
51-
<a href="/theme?pref=dark" class="nav-button" title="switch to dark" aria-label="switch to dark">
52+
<a href="{{ path_prefix }}/theme?pref=dark" class="nav-button" title="switch to dark" aria-label="switch to dark">
5253
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
5354
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 21a9 9 0 0 1-.5-17.986V3c-.354.966-.5 1.911-.5 3a9 9 0 0 0 9 9c.239 0 .254.018.488 0A9.004 9.004 0 0 1 12 21Z"/>
5455
</svg>
5556
</a>
5657
</div>
5758
{% when Some with (Theme::Dark) %}
5859
<div class="nav-item" id="light-switch">
59-
<a href="/theme?pref=light" class="nav-button" title="switch to light" aria-label="switch to light">
60+
<a href="{{ path_prefix }}/theme?pref=light" class="nav-button" title="switch to light" aria-label="switch to light">
6061
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
6162
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5V3m0 18v-2M7.05 7.05 5.636 5.636m12.728 12.728L16.95 16.95M5 12H3m18 0h-2M7.05 16.95l-1.414 1.414M18.364 5.636 16.95 7.05M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z"/>
6263
</svg>
6364
</a>
6465
</div>
6566
{% when Some with (Theme::Light) %}
66-
<div class="nav-item" id="system-switch"> <a href="/theme?pref=system" class="nav-button" title="switch to system" aria-label="switch to system">
67+
<div class="nav-item" id="system-switch"> <a href="{{ path_prefix }}/theme?pref=system" class="nav-button" title="switch to system" aria-label="switch to system">
6768
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
6869
<path stroke="currentColor" stroke-linecap="square" stroke-linejoin="round" stroke-width="2" d="M10 19H5a1 1 0 0 1-1-1v-1a3 3 0 0 1 3-3h2m10 1a3 3 0 0 1-3 3m3-3a3 3 0 0 0-3-3m3 3h1m-4 3a3 3 0 0 1-3-3m3 3v1m-3-4a3 3 0 0 1 3-3m-3 3h-1m4-3v-1m-2.121 1.879-.707-.707m5.656 5.656-.707-.707m-4.242 0-.707.707m5.656-5.656-.707.707M12 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/>
6970
</svg>

crates/wastebin_server/templates/burn.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{% block content %}
33
<div class="flex-center">
44
<div>
5-
Copy and send <a class="text-link" href="/{{ key }}">this link</a>. After opening it for the first time, it will be deleted.
5+
Copy and send <a class="text-link" href="{{ path_prefix }}/{{ key }}">this link</a>. After opening it for the first time, it will be deleted.
66
</div>
77
<div>
88
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 {{ code.size() + 4 }} {{ code.size() + 4 }}" stroke="none" width="16rem">

crates/wastebin_server/templates/encrypted.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
{% block content %}
44
<div class="flex-center">
5-
<form action="/{{ id }}" method="post">
5+
<form action="{{ path_prefix }}/{{ id }}" method="post">
66
<div class="controls">
77
<div class="controls-row">
88
<input type="password" id="password" name="password" placeholder="Password ..." autofocus>

crates/wastebin_server/templates/error.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
{% block content %}
33
<div class="flex-center">
44
<p>😢 {{ description }}</p>
5-
<p><a class="text-link" href="/">go back</a></p>
5+
<p><a class="text-link" href="{{ path_prefix }}/">go back</a></p>
66
</div>
77
{% endblock %}

crates/wastebin_server/templates/formatted.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@
4141
</div>
4242
{{ html|safe }}
4343
{% if !is_available %}
44-
<script defer src="{{ page.assets.burn_js.route()}}"></script>
44+
<script defer src="{{ path_prefix }}{{ page.assets.burn_js.route()}}"></script>
4545
{% endif %}
4646
{% endblock %}

crates/wastebin_server/templates/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
{% endblock %}
1616

1717
{%- block content -%}
18-
<form id="form" action="/new" method="post">
18+
<form id="form" action="{{ path_prefix }}/new" method="post">
1919
<div class="container">
2020
<div class="content">
2121
<textarea id="text" name="text" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" placeholder="<paste text or drop file here>" autofocus required></textarea>

crates/wastebin_server/templates/paste.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,22 @@
1919
{% if is_available %}
2020
{% if can_delete %}
2121
<div class="nav-item">
22-
<a href="/delete/{{ key.id() }}" class="nav-button" title="delete paste" aria-label="delete paste">
22+
<a href="{{ path_prefix }}/delete/{{ key.id() }}" class="nav-button" title="delete paste" aria-label="delete paste">
2323
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
2424
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 7h14m-9 3v8m4-8v8M10 3h4a1 1 0 0 1 1 1v3H9V4a1 1 0 0 1 1-1ZM6 7h12v13a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7Z"/>
2525
</svg>
2626
</a>
2727
</div>
2828
{% endif %}
2929
<div class="nav-item">
30-
<a href="/dl/{{ key }}" class="nav-button" title="download file" aria-label="download file">
30+
<a href="{{ path_prefix }}/dl/{{ key }}" class="nav-button" title="download file" aria-label="download file">
3131
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
3232
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 13V4M7 14H5a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-4a1 1 0 0 0-1-1h-2m-1-5-4 5-4-5m9 8h.01"/>
3333
</svg>
3434
</a>
3535
</div>
3636
<div class="nav-item">
37-
<a href="/raw/{{ key }}" class="nav-button" title="display raw file" aria-label="display raw file">
37+
<a href="{{ path_prefix }}/raw/{{ key }}" class="nav-button" title="display raw file" aria-label="display raw file">
3838
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
3939
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 3v4a1 1 0 0 1-1 1H5m5 4-2 2 2 2m4-4 2 2-2 2m5-12v16a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V7.914a1 1 0 0 1 .293-.707l3.914-3.914A1 1 0 0 1 9.914 3H18a1 1 0 0 1 1 1Z"/>
4040
</svg>
@@ -52,7 +52,7 @@
5252
{% block nav_specific %}
5353
{% if is_available %}
5454
<div class="nav-item">
55-
<a href="/qr/{{ key }}" class="nav-button" title="qr code" aria-label="qr code">
55+
<a href="{{ path_prefix }}/qr/{{ key }}" class="nav-button" title="qr code" aria-label="qr code">
5656
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
5757
<path stroke="currentColor" stroke-linejoin="round" stroke-width="2" d="M4 4h6v6H4V4Zm10 10h6v6h-6v-6Zm0-10h6v6h-6V4Zm-4 10h.01v.01H10V14Zm0 4h.01v.01H10V18Zm-3 2h.01v.01H7V20Zm0-4h.01v.01H7V16Zm-3 2h.01v.01H4V18Zm0-4h.01v.01H4V14Z"/>
5858
<path stroke="currentColor" stroke-linejoin="round" stroke-width="2" d="M7 7h.01v.01H7V7Zm10 10h.01v.01H17V17Z"/>

0 commit comments

Comments
 (0)