perf(http): add gzip compression and static asset cache headers
- Add CompressionLayer with gzip to the middleware stack - Add Cache-Control: public, max-age=604800 (1 week) to all static asset routes (CSS, JS, favicons)
This commit is contained in:
parent
494e0346bf
commit
4fb2e945a4
3 changed files with 32 additions and 9 deletions
|
|
@ -33,7 +33,7 @@ tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "fmt"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "fmt"] }
|
||||||
tower = "0.4"
|
tower = "0.4"
|
||||||
tower-cookies = "0.10"
|
tower-cookies = "0.10"
|
||||||
tower-http = { version = "0.6", features = ["limit", "set-header", "trace"] }
|
tower-http = { version = "0.6", features = ["compression-gzip", "limit", "set-header", "trace"] }
|
||||||
slug = "0.1.6"
|
slug = "0.1.6"
|
||||||
url = "2"
|
url = "2"
|
||||||
uuid = { version = "1", features = ["v4"] }
|
uuid = { version = "1", features = ["v4"] }
|
||||||
|
|
|
||||||
|
|
@ -43,49 +43,70 @@ async fn scan_redirect() -> Redirect {
|
||||||
|
|
||||||
async fn styles() -> impl IntoResponse {
|
async fn styles() -> impl IntoResponse {
|
||||||
(
|
(
|
||||||
[("content-type", "text/css; charset=utf-8")],
|
[
|
||||||
|
("content-type", "text/css; charset=utf-8"),
|
||||||
|
("cache-control", "public, max-age=604800"),
|
||||||
|
],
|
||||||
include_str!("../../../../static/css/styles.css"),
|
include_str!("../../../../static/css/styles.css"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn webauthn_js() -> impl IntoResponse {
|
async fn webauthn_js() -> impl IntoResponse {
|
||||||
(
|
(
|
||||||
[("content-type", "application/javascript; charset=utf-8")],
|
[
|
||||||
|
("content-type", "application/javascript; charset=utf-8"),
|
||||||
|
("cache-control", "public, max-age=604800"),
|
||||||
|
],
|
||||||
include_str!("../../../../static/js/webauthn.js"),
|
include_str!("../../../../static/js/webauthn.js"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn photo_capture_js() -> impl IntoResponse {
|
async fn photo_capture_js() -> impl IntoResponse {
|
||||||
(
|
(
|
||||||
[("content-type", "application/javascript; charset=utf-8")],
|
[
|
||||||
|
("content-type", "application/javascript; charset=utf-8"),
|
||||||
|
("cache-control", "public, max-age=604800"),
|
||||||
|
],
|
||||||
include_str!("../../../../static/js/components/photo-capture.js"),
|
include_str!("../../../../static/js/components/photo-capture.js"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn searchable_select_js() -> impl IntoResponse {
|
async fn searchable_select_js() -> impl IntoResponse {
|
||||||
(
|
(
|
||||||
[("content-type", "application/javascript; charset=utf-8")],
|
[
|
||||||
|
("content-type", "application/javascript; charset=utf-8"),
|
||||||
|
("cache-control", "public, max-age=604800"),
|
||||||
|
],
|
||||||
include_str!("../../../../static/js/components/searchable-select.js"),
|
include_str!("../../../../static/js/components/searchable-select.js"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn favicon() -> impl IntoResponse {
|
async fn favicon() -> impl IntoResponse {
|
||||||
(
|
(
|
||||||
[("content-type", "image/x-icon")],
|
[
|
||||||
|
("content-type", "image/x-icon"),
|
||||||
|
("cache-control", "public, max-age=604800"),
|
||||||
|
],
|
||||||
include_bytes!("../../../../static/favicon.ico").as_ref(),
|
include_bytes!("../../../../static/favicon.ico").as_ref(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn favicon_light() -> impl IntoResponse {
|
async fn favicon_light() -> impl IntoResponse {
|
||||||
(
|
(
|
||||||
[("content-type", "image/svg+xml")],
|
[
|
||||||
|
("content-type", "image/svg+xml"),
|
||||||
|
("cache-control", "public, max-age=604800"),
|
||||||
|
],
|
||||||
include_str!("../../../../static/favicon-light.svg"),
|
include_str!("../../../../static/favicon-light.svg"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn favicon_dark() -> impl IntoResponse {
|
async fn favicon_dark() -> impl IntoResponse {
|
||||||
(
|
(
|
||||||
[("content-type", "image/svg+xml")],
|
[
|
||||||
|
("content-type", "image/svg+xml"),
|
||||||
|
("cache-control", "public, max-age=604800"),
|
||||||
|
],
|
||||||
include_str!("../../../../static/favicon-dark.svg"),
|
include_str!("../../../../static/favicon-dark.svg"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use axum::http::{HeaderValue, StatusCode};
|
||||||
use axum::response::Html;
|
use axum::response::Html;
|
||||||
use tower::ServiceBuilder;
|
use tower::ServiceBuilder;
|
||||||
use tower_cookies::CookieManagerLayer;
|
use tower_cookies::CookieManagerLayer;
|
||||||
|
use tower_http::compression::CompressionLayer;
|
||||||
use tower_http::limit::RequestBodyLimitLayer;
|
use tower_http::limit::RequestBodyLimitLayer;
|
||||||
use tower_http::set_header::SetResponseHeaderLayer;
|
use tower_http::set_header::SetResponseHeaderLayer;
|
||||||
use tower_http::trace::{DefaultMakeSpan, DefaultOnResponse, TraceLayer};
|
use tower_http::trace::{DefaultMakeSpan, DefaultOnResponse, TraceLayer};
|
||||||
|
|
@ -62,7 +63,8 @@ pub fn app_router(state: AppState) -> axum::Router {
|
||||||
.layer(SetResponseHeaderLayer::overriding(
|
.layer(SetResponseHeaderLayer::overriding(
|
||||||
axum::http::header::STRICT_TRANSPORT_SECURITY,
|
axum::http::header::STRICT_TRANSPORT_SECURITY,
|
||||||
HeaderValue::from_static("max-age=63072000; includeSubDomains"),
|
HeaderValue::from_static("max-age=63072000; includeSubDomains"),
|
||||||
)),
|
))
|
||||||
|
.layer(CompressionLayer::new().gzip(true)),
|
||||||
)
|
)
|
||||||
.with_state(state)
|
.with_state(state)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue