diff --git a/src/main.rs b/src/main.rs index cb449b3..2ff446d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ use actix_web::{App, HttpResponse, HttpServer, Responder, web}; use clap::Parser; +const SCHEMA_FILE: &str = "schema.yaml"; + /// Simple swagger UI server - serves OpenAPI file #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] @@ -12,6 +14,10 @@ struct Args { /// Listen address #[clap(short, long, default_value = "0.0.0.0:8000")] listen_address: String, + + /// Access token, optional + #[clap(short, long)] + token: Option, } #[derive(serde::Deserialize)] @@ -19,12 +25,32 @@ struct HandlerPath { filename: Option, } +#[derive(serde::Deserialize)] +struct HandlerQuery { + token: Option, +} + #[derive(Debug, Clone, Eq, PartialEq)] struct Schema(String); -async fn handler(path: web::Path, schema: web::Data) -> impl Responder { +#[derive(Debug, Clone, Eq, PartialEq)] +struct AccessToken(Option); + +async fn handler(path: web::Path, + query: web::Query, + schema: web::Data, + access_token: web::Data) -> impl Responder { let filename: &str = path.filename.as_deref().unwrap_or("index.html"); + if filename.eq("index.html") || filename.eq(SCHEMA_FILE) { + if let Some(tok) = access_token.0.as_ref() { + if !query.token.as_deref().unwrap_or_default().eq(tok) { + return HttpResponse::Unauthorized() + .body("Please indicate as query parameter the 'token'"); + } + } + } + let ext = filename .rsplit_once('.') .map(|r| r.1).unwrap_or_default(); @@ -39,7 +65,7 @@ async fn handler(path: web::Path, schema: web::Data) -> imp _ => "text/plain" }; - let filebytes = if filename.eq("schema.yaml") { + let filebytes = if filename.eq(SCHEMA_FILE) { Some(schema.0.as_bytes().to_vec()) } else { swagger_ui::Assets::get(filename).map(|f| f.to_vec()) @@ -51,7 +77,10 @@ async fn handler(path: web::Path, schema: web::Data) -> imp if filename.eq("index.html") { bytes = String::from_utf8_lossy(&bytes).to_string() - .replace("https://petstore.swagger.io/v2/swagger.json", "/schema.yaml") + .replace( + "https://petstore.swagger.io/v2/swagger.json", + &format!("/{}?token={}", SCHEMA_FILE, access_token.0.as_deref().unwrap_or_default()), + ) .as_bytes().to_vec(); } @@ -73,9 +102,12 @@ async fn main() -> std::io::Result<()> { let schema = Schema(std::fs::read_to_string(args.schema) .expect("Failed to read schema!")); + let access_token = AccessToken(args.token); + HttpServer::new(move || { App::new() .app_data(web::Data::new(schema.clone())) + .app_data(web::Data::new(access_token.clone())) .route("/", web::get().to(handler)) .route("/{filename}", web::get().to(handler))