utoipa_swagger_ui/
actix.rs1#![cfg(feature = "actix-web")]
2
3use actix_web::{
4 dev::HttpServiceFactory, guard::Get, web, web::Data, HttpResponse, Resource,
5 Responder as ActixResponder,
6};
7
8use crate::{ApiDoc, Config, SwaggerUi};
9
10impl HttpServiceFactory for SwaggerUi {
11 fn register(self, config: &mut actix_web::dev::AppService) {
12 let mut urls = self
13 .urls
14 .into_iter()
15 .map(|(url, openapi)| {
16 register_api_doc_url_resource(url.url.as_ref(), ApiDoc::Utoipa(openapi), config);
17 url
18 })
19 .collect::<Vec<_>>();
20 let external_api_docs = self.external_urls.into_iter().map(|(url, api_doc)| {
21 register_api_doc_url_resource(url.url.as_ref(), ApiDoc::Value(api_doc), config);
22 url
23 });
24 urls.extend(external_api_docs);
25
26 let swagger_resource = Resource::new(self.path.as_ref())
27 .guard(Get())
28 .app_data(Data::new(if let Some(config) = self.config {
29 if config.url.is_some() || !config.urls.is_empty() {
30 config
31 } else {
32 config.configure_defaults(urls)
33 }
34 } else {
35 Config::new(urls)
36 }))
37 .to(serve_swagger_ui);
38
39 HttpServiceFactory::register(swagger_resource, config);
40 }
41}
42
43fn register_api_doc_url_resource(url: &str, api: ApiDoc, config: &mut actix_web::dev::AppService) {
44 async fn get_api_doc(api_doc: web::Data<ApiDoc>) -> impl ActixResponder {
45 HttpResponse::Ok().json(api_doc.as_ref())
46 }
47
48 let url_resource = Resource::new(url)
49 .guard(Get())
50 .app_data(Data::new(api))
51 .to(get_api_doc);
52 HttpServiceFactory::register(url_resource, config);
53}
54
55async fn serve_swagger_ui(path: web::Path<String>, data: web::Data<Config<'_>>) -> HttpResponse {
56 match super::serve(&path.into_inner(), data.into_inner()) {
57 Ok(swagger_file) => swagger_file
58 .map(|file| {
59 HttpResponse::Ok()
60 .content_type(file.content_type)
61 .body(file.bytes.to_vec())
62 })
63 .unwrap_or_else(|| HttpResponse::NotFound().finish()),
64 Err(error) => HttpResponse::InternalServerError().body(error.to_string()),
65 }
66}