use crate::config::AppConfig;
use crate::handlers::utils::get_static_path;
use actix_web::{web, HttpRequest, HttpResponse, Result};
use serde_json::{json, Value};
pub async fn openapi_handler(
req: HttpRequest,
config: web::Data<AppConfig>,
) -> Result<HttpResponse> {
let static_path = get_static_path();
let openapi_path = static_path.join("openapi.json");
let base_openapi = match std::fs::read_to_string(&openapi_path) {
Ok(content) => content,
Err(_) => {
return Ok(HttpResponse::NotFound().json(json!({
"info": {
"title": "HTTPCan",
"version": option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"),
"description": "A simple, high‑performance HTTP request & response service built with Rust and Actix Web. Fully compatible with [httpbin.org](https://httpbin.org), with modern streaming and AI‑friendly enhancements."
},
"error": "OpenAPI specification not found",
"message": "Please download openapi.json from https://httpcan.org. Then create a static directory in the directory where the httpcan binary file is located, and place the downloaded openapi.json into that directory."
})));
}
};
let mut openapi: Value = match serde_json::from_str(&base_openapi) {
Ok(spec) => spec,
Err(_) => {
return Ok(HttpResponse::InternalServerError().json(json!({
"error": "Failed to parse OpenAPI specification"
})));
}
};
if config.add_current_server {
let connection_info = req.connection_info();
let scheme = connection_info.scheme();
let host = connection_info.host();
let current_server_url = format!("{}://{}", scheme, host);
let mut servers_array = Vec::new();
servers_array.push(json!({
"url": current_server_url,
"description": "Current server"
}));
if let Some(existing_servers) = openapi.get("servers").and_then(|s| s.as_array()) {
for server in existing_servers {
if let Some(url) = server.get("url").and_then(|u| u.as_str()) {
if url != current_server_url {
servers_array.push(server.clone());
}
}
}
}
if let Some(obj) = openapi.as_object_mut() {
obj.insert("servers".to_string(), json!(servers_array));
}
}
Ok(HttpResponse::Ok()
.content_type("application/json")
.json(openapi))
}