utoipa_actix_web/
service_config.rs

1//! Implement `utoipa` extended [`ServiceConfig`] for [`actix_web::web::ServiceConfig`].
2
3use std::cell::Cell;
4
5use actix_service::{IntoServiceFactory, ServiceFactory};
6use actix_web::dev::{HttpServiceFactory, ServiceRequest, ServiceResponse};
7use actix_web::{Error, Route};
8
9use crate::OpenApiFactory;
10
11/// Wrapper type for [`actix_web::web::ServiceConfig`], [`utoipa::openapi::path::Paths`] and
12/// vec of [`utoipa::openapi::schema::Schema`] references.
13pub struct ServiceConfig<'s>(
14    pub(super) &'s mut actix_web::web::ServiceConfig,
15    pub(super) Cell<utoipa::openapi::path::Paths>,
16    pub(super)  Cell<
17        Vec<(
18            String,
19            utoipa::openapi::RefOr<utoipa::openapi::schema::Schema>,
20        )>,
21    >,
22);
23
24impl<'s> ServiceConfig<'s> {
25    /// Construct a new [`ServiceConfig`] from given [`actix_web::web::ServiceConfig`].
26    pub fn new(conf: &'s mut actix_web::web::ServiceConfig) -> ServiceConfig<'s> {
27        ServiceConfig(
28            conf,
29            Cell::new(utoipa::openapi::path::Paths::new()),
30            Cell::new(Vec::new()),
31        )
32    }
33
34    /// Passthrough implementation for [`actix_web::web::ServiceConfig::app_data`].
35    pub fn app_data<U: 'static>(&mut self, ext: U) -> &mut Self {
36        self.0.app_data(ext);
37        self
38    }
39
40    /// Passthrough implementation for [`actix_web::web::ServiceConfig::default_service`].
41    pub fn default_service<F, U>(&mut self, f: F) -> &mut Self
42    where
43        F: IntoServiceFactory<U, ServiceRequest>,
44        U: ServiceFactory<ServiceRequest, Config = (), Response = ServiceResponse, Error = Error>
45            + 'static,
46        U::InitError: std::fmt::Debug,
47    {
48        self.0.default_service(f);
49        self
50    }
51
52    /// Passthrough implementation for [`actix_web::web::ServiceConfig::configure`].
53    pub fn configure<F>(&mut self, f: F) -> &mut Self
54    where
55        F: FnOnce(&mut ServiceConfig),
56    {
57        f(self);
58        self
59    }
60
61    /// Passthrough implementation for [`actix_web::web::ServiceConfig::route`].
62    pub fn route(&mut self, path: &str, route: Route) -> &mut Self {
63        self.0.route(path, route);
64        self
65    }
66
67    /// Counterpart for [`UtoipaApp::service`][utoipa_app_service].
68    ///
69    /// [utoipa_app_service]: ../struct.UtoipaApp.html#method.service
70    pub fn service<F>(&mut self, factory: F) -> &mut Self
71    where
72        F: HttpServiceFactory + OpenApiFactory + 'static,
73    {
74        let mut paths = self.1.take();
75        let other_paths = factory.paths();
76        paths.merge(other_paths);
77
78        let mut schemas = self.2.take();
79        factory.schemas(&mut schemas);
80        self.2.set(schemas);
81
82        self.0.service(factory);
83        self.1.set(paths);
84
85        self
86    }
87
88    /// Passthrough implementation for [`actix_web::web::ServiceConfig::external_resource`].
89    pub fn external_resource<N, U>(&mut self, name: N, url: U) -> &mut Self
90    where
91        N: AsRef<str>,
92        U: AsRef<str>,
93    {
94        self.0.external_resource(name, url);
95        self
96    }
97
98    /// Synonymous for [`UtoipaApp::map`][utoipa_app_map]
99    ///
100    /// [utoipa_app_map]: ../struct.UtoipaApp.html#method.map
101    pub fn map<
102        F: FnOnce(&mut actix_web::web::ServiceConfig) -> &mut actix_web::web::ServiceConfig,
103    >(
104        &mut self,
105        op: F,
106    ) -> &mut Self {
107        op(self.0);
108
109        self
110    }
111}