v0.24.5
This commit is contained in:
commit
5e23e9af02
240 files changed
+99957
No files matched your search
@@ -0,0 +1,89 @@
|
||||
//! Authenticated OpenAPI/Swagger UI, exclusively on the admin listener.
|
||||
//! Only these allowlisted vendor assets can be read; no filesystem or wildcard route.
|
||||
use axum::{
|
||||
response::{Html, IntoResponse, Response},
|
||||
Json,
|
||||
};
|
||||
use http::StatusCode;
|
||||
use serde_json::Value;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
pub(super) async fn index() -> Html<&'static str> {
|
||||
Html(include_str!("web/docs.html"))
|
||||
}
|
||||
pub(super) async fn script() -> impl IntoResponse {
|
||||
(
|
||||
[("content-type", "text/javascript; charset=utf-8")],
|
||||
include_str!("web/docs.js"),
|
||||
)
|
||||
}
|
||||
pub(super) async fn style() -> impl IntoResponse {
|
||||
(
|
||||
[("content-type", "text/css; charset=utf-8")],
|
||||
include_str!("web/docs.css"),
|
||||
)
|
||||
}
|
||||
pub(super) async fn schema() -> Json<Value> {
|
||||
static DOCUMENT: OnceLock<Value> = OnceLock::new();
|
||||
Json(
|
||||
DOCUMENT
|
||||
.get_or_init(|| {
|
||||
let mut value: Value = serde_json::from_str(include_str!("openapi.json"))
|
||||
.expect("validated embedded OpenAPI");
|
||||
value["info"]["version"] = Value::String(env!("CARGO_PKG_VERSION").into());
|
||||
value
|
||||
})
|
||||
.clone(),
|
||||
)
|
||||
}
|
||||
pub(super) fn asset(name: &'static str) -> Response {
|
||||
// Bytes are embedded for debug AND release, and always served through the
|
||||
// authenticated router. Never read a file or fetch a CDN on an HTTP request.
|
||||
let (content_type, bytes): (&'static str, &'static [u8]) = match name {
|
||||
"swagger-ui-bundle.js" => (
|
||||
"text/javascript; charset=utf-8",
|
||||
include_bytes!(concat!(env!("OUT_DIR"), "/swagger-ui/swagger-ui-bundle.js")),
|
||||
),
|
||||
"swagger-ui.css" => (
|
||||
"text/css; charset=utf-8",
|
||||
include_bytes!(concat!(env!("OUT_DIR"), "/swagger-ui/swagger-ui.css")),
|
||||
),
|
||||
"licenses.txt" => (
|
||||
"text/plain; charset=utf-8",
|
||||
include_bytes!(concat!(env!("OUT_DIR"), "/swagger-ui/licenses.txt")),
|
||||
),
|
||||
_ => return StatusCode::NOT_FOUND.into_response(),
|
||||
};
|
||||
([("content-type", content_type)], bytes).into_response()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn fixed_vendor_names_return_embedded_assets_with_expected_types() {
|
||||
for (name, expected_type) in [
|
||||
("swagger-ui-bundle.js", "text/javascript; charset=utf-8"),
|
||||
("swagger-ui.css", "text/css; charset=utf-8"),
|
||||
("licenses.txt", "text/plain; charset=utf-8"),
|
||||
] {
|
||||
let response = asset(name);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(response.headers()["content-type"], expected_type);
|
||||
let bytes = axum::body::to_bytes(response.into_body(), 16 * 1024 * 1024)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(!bytes.is_empty(), "{name}");
|
||||
}
|
||||
for name in [
|
||||
"../Cargo.toml",
|
||||
"index.html",
|
||||
"openapi.json",
|
||||
"source.json",
|
||||
"unknown.js",
|
||||
] {
|
||||
assert_eq!(asset(name).status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user