tower_http/cors/
mod.rs

1//! Middleware which adds headers for [CORS][mdn].
2//!
3//! # Example
4//!
5//! ```
6//! use http::{Request, Response, Method, header};
7//! use http_body_util::Full;
8//! use bytes::Bytes;
9//! use tower::{ServiceBuilder, ServiceExt, Service};
10//! use tower_http::cors::{Any, CorsLayer};
11//! use std::convert::Infallible;
12//!
13//! async fn handle(request: Request<Full<Bytes>>) -> Result<Response<Full<Bytes>>, Infallible> {
14//!     Ok(Response::new(Full::default()))
15//! }
16//!
17//! # #[tokio::main]
18//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
19//! let cors = CorsLayer::new()
20//!     // allow `GET` and `POST` when accessing the resource
21//!     .allow_methods([Method::GET, Method::POST])
22//!     // allow requests from any origin
23//!     .allow_origin(Any);
24//!
25//! let mut service = ServiceBuilder::new()
26//!     .layer(cors)
27//!     .service_fn(handle);
28//!
29//! let request = Request::builder()
30//!     .header(header::ORIGIN, "https://example.com")
31//!     .body(Full::default())
32//!     .unwrap();
33//!
34//! let response = service
35//!     .ready()
36//!     .await?
37//!     .call(request)
38//!     .await?;
39//!
40//! assert_eq!(
41//!     response.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN).unwrap(),
42//!     "*",
43//! );
44//! # Ok(())
45//! # }
46//! ```
47//!
48//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
49
50#![allow(clippy::enum_variant_names)]
51
52use allow_origin::AllowOriginFuture;
53use bytes::{BufMut, BytesMut};
54use http::{
55    header::{self, HeaderName},
56    HeaderMap, HeaderValue, Method, Request, Response,
57};
58use pin_project_lite::pin_project;
59use std::{
60    array,
61    future::Future,
62    mem,
63    pin::Pin,
64    task::{ready, Context, Poll},
65};
66use tower_layer::Layer;
67use tower_service::Service;
68
69mod allow_credentials;
70mod allow_headers;
71mod allow_methods;
72mod allow_origin;
73mod allow_private_network;
74mod expose_headers;
75mod max_age;
76mod vary;
77
78#[cfg(test)]
79mod tests;
80
81pub use self::{
82    allow_credentials::AllowCredentials, allow_headers::AllowHeaders, allow_methods::AllowMethods,
83    allow_origin::AllowOrigin, allow_private_network::AllowPrivateNetwork,
84    expose_headers::ExposeHeaders, max_age::MaxAge, vary::Vary,
85};
86
87/// Layer that applies the [`Cors`] middleware which adds headers for [CORS][mdn].
88///
89/// See the [module docs](crate::cors) for an example.
90///
91/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
92#[derive(Debug, Clone)]
93#[must_use]
94pub struct CorsLayer {
95    allow_credentials: AllowCredentials,
96    allow_headers: AllowHeaders,
97    allow_methods: AllowMethods,
98    allow_origin: AllowOrigin,
99    allow_private_network: AllowPrivateNetwork,
100    expose_headers: ExposeHeaders,
101    max_age: MaxAge,
102    vary: Vary,
103}
104
105#[allow(clippy::declare_interior_mutable_const)]
106const WILDCARD: HeaderValue = HeaderValue::from_static("*");
107
108impl CorsLayer {
109    /// Create a new `CorsLayer`.
110    ///
111    /// No headers are sent by default. Use the builder methods to customize
112    /// the behavior.
113    ///
114    /// You need to set at least an allowed origin for browsers to make
115    /// successful cross-origin requests to your service.
116    pub fn new() -> Self {
117        Self {
118            allow_credentials: Default::default(),
119            allow_headers: Default::default(),
120            allow_methods: Default::default(),
121            allow_origin: Default::default(),
122            allow_private_network: Default::default(),
123            expose_headers: Default::default(),
124            max_age: Default::default(),
125            vary: Default::default(),
126        }
127    }
128
129    /// A permissive configuration:
130    ///
131    /// - All request headers allowed.
132    /// - All methods allowed.
133    /// - All origins allowed.
134    /// - All headers exposed.
135    pub fn permissive() -> Self {
136        Self::new()
137            .allow_headers(Any)
138            .allow_methods(Any)
139            .allow_origin(Any)
140            .expose_headers(Any)
141    }
142
143    /// A very permissive configuration:
144    ///
145    /// - **Credentials allowed.**
146    /// - The method received in `Access-Control-Request-Method` is sent back
147    ///   as an allowed method.
148    /// - The origin of the preflight request is sent back as an allowed origin.
149    /// - The header names received in `Access-Control-Request-Headers` are sent
150    ///   back as allowed headers.
151    /// - No headers are currently exposed, but this may change in the future.
152    pub fn very_permissive() -> Self {
153        Self::new()
154            .allow_credentials(true)
155            .allow_headers(AllowHeaders::mirror_request())
156            .allow_methods(AllowMethods::mirror_request())
157            .allow_origin(AllowOrigin::mirror_request())
158    }
159
160    /// Set the [`Access-Control-Allow-Credentials`][mdn] header.
161    ///
162    /// ```
163    /// use tower_http::cors::CorsLayer;
164    ///
165    /// let layer = CorsLayer::new().allow_credentials(true);
166    /// ```
167    ///
168    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
169    pub fn allow_credentials<T>(mut self, allow_credentials: T) -> Self
170    where
171        T: Into<AllowCredentials>,
172    {
173        self.allow_credentials = allow_credentials.into();
174        self
175    }
176
177    /// Set the value of the [`Access-Control-Allow-Headers`][mdn] header.
178    ///
179    /// ```
180    /// use tower_http::cors::CorsLayer;
181    /// use http::header::{AUTHORIZATION, ACCEPT};
182    ///
183    /// let layer = CorsLayer::new().allow_headers([AUTHORIZATION, ACCEPT]);
184    /// ```
185    ///
186    /// All headers can be allowed with
187    ///
188    /// ```
189    /// use tower_http::cors::{Any, CorsLayer};
190    ///
191    /// let layer = CorsLayer::new().allow_headers(Any);
192    /// ```
193    ///
194    /// Note that multiple calls to this method will override any previous
195    /// calls.
196    ///
197    /// Also note that `Access-Control-Allow-Headers` is required for requests that have
198    /// `Access-Control-Request-Headers`.
199    ///
200    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
201    pub fn allow_headers<T>(mut self, headers: T) -> Self
202    where
203        T: Into<AllowHeaders>,
204    {
205        self.allow_headers = headers.into();
206        self
207    }
208
209    /// Set the value of the [`Access-Control-Max-Age`][mdn] header.
210    ///
211    /// ```
212    /// use std::time::Duration;
213    /// use tower_http::cors::CorsLayer;
214    ///
215    /// let layer = CorsLayer::new().max_age(Duration::from_secs(60) * 10);
216    /// ```
217    ///
218    /// By default the header will not be set which disables caching and will
219    /// require a preflight call for all requests.
220    ///
221    /// Note that each browser has a maximum internal value that takes
222    /// precedence when the Access-Control-Max-Age is greater. For more details
223    /// see [mdn].
224    ///
225    /// If you need more flexibility, you can use supply a function which can
226    /// dynamically decide the max-age based on the origin and other parts of
227    /// each preflight request:
228    ///
229    /// ```
230    /// # struct MyServerConfig { cors_max_age: Duration }
231    /// use std::time::Duration;
232    ///
233    /// use http::{request::Parts as RequestParts, HeaderValue};
234    /// use tower_http::cors::{CorsLayer, MaxAge};
235    ///
236    /// let layer = CorsLayer::new().max_age(MaxAge::dynamic(
237    ///     |_origin: &HeaderValue, parts: &RequestParts| -> Duration {
238    ///         // Let's say you want to be able to reload your config at
239    ///         // runtime and have another middleware that always inserts
240    ///         // the current config into the request extensions
241    ///         let config = parts.extensions.get::<MyServerConfig>().unwrap();
242    ///         config.cors_max_age
243    ///     },
244    /// ));
245    /// ```
246    ///
247    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
248    pub fn max_age<T>(mut self, max_age: T) -> Self
249    where
250        T: Into<MaxAge>,
251    {
252        self.max_age = max_age.into();
253        self
254    }
255
256    /// Set the value of the [`Access-Control-Allow-Methods`][mdn] header.
257    ///
258    /// ```
259    /// use tower_http::cors::CorsLayer;
260    /// use http::Method;
261    ///
262    /// let layer = CorsLayer::new().allow_methods([Method::GET, Method::POST]);
263    /// ```
264    ///
265    /// All methods can be allowed with
266    ///
267    /// ```
268    /// use tower_http::cors::{Any, CorsLayer};
269    ///
270    /// let layer = CorsLayer::new().allow_methods(Any);
271    /// ```
272    ///
273    /// Note that multiple calls to this method will override any previous
274    /// calls.
275    ///
276    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
277    pub fn allow_methods<T>(mut self, methods: T) -> Self
278    where
279        T: Into<AllowMethods>,
280    {
281        self.allow_methods = methods.into();
282        self
283    }
284
285    /// Set the value of the [`Access-Control-Allow-Origin`][mdn] header.
286    ///
287    /// ```
288    /// use http::HeaderValue;
289    /// use tower_http::cors::CorsLayer;
290    ///
291    /// let layer = CorsLayer::new().allow_origin(
292    ///     "http://example.com".parse::<HeaderValue>().unwrap(),
293    /// );
294    /// ```
295    ///
296    /// Multiple origins can be allowed with
297    ///
298    /// ```
299    /// use tower_http::cors::CorsLayer;
300    ///
301    /// let origins = [
302    ///     "http://example.com".parse().unwrap(),
303    ///     "http://api.example.com".parse().unwrap(),
304    /// ];
305    ///
306    /// let layer = CorsLayer::new().allow_origin(origins);
307    /// ```
308    ///
309    /// All origins can be allowed with
310    ///
311    /// ```
312    /// use tower_http::cors::{Any, CorsLayer};
313    ///
314    /// let layer = CorsLayer::new().allow_origin(Any);
315    /// ```
316    ///
317    /// You can also use a closure
318    ///
319    /// ```
320    /// use tower_http::cors::{CorsLayer, AllowOrigin};
321    /// use http::{request::Parts as RequestParts, HeaderValue};
322    ///
323    /// let layer = CorsLayer::new().allow_origin(AllowOrigin::predicate(
324    ///     |origin: &HeaderValue, _request_parts: &RequestParts| {
325    ///         origin.as_bytes().ends_with(b".rust-lang.org")
326    ///     },
327    /// ));
328    /// ```
329    ///
330    /// You can also use an async closure:
331    ///
332    /// ```
333    /// # #[derive(Clone)]
334    /// # struct Client;
335    /// # fn get_api_client() -> Client {
336    /// #     Client
337    /// # }
338    /// # impl Client {
339    /// #     async fn fetch_allowed_origins(&self) -> Vec<HeaderValue> {
340    /// #         vec![HeaderValue::from_static("http://example.com")]
341    /// #     }
342    /// #     async fn fetch_allowed_origins_for_path(&self, _path: String) -> Vec<HeaderValue> {
343    /// #         vec![HeaderValue::from_static("http://example.com")]
344    /// #     }
345    /// # }
346    /// use tower_http::cors::{CorsLayer, AllowOrigin};
347    /// use http::{request::Parts as RequestParts, HeaderValue};
348    ///
349    /// let client = get_api_client();
350    ///
351    /// let layer = CorsLayer::new().allow_origin(AllowOrigin::async_predicate(
352    ///     |origin: HeaderValue, _request_parts: &RequestParts| async move {
353    ///         // fetch list of origins that are allowed
354    ///         let origins = client.fetch_allowed_origins().await;
355    ///         origins.contains(&origin)
356    ///     },
357    /// ));
358    ///
359    /// let client = get_api_client();
360    ///
361    /// // if using &RequestParts, make sure all the values are owned
362    /// // before passing into the future
363    /// let layer = CorsLayer::new().allow_origin(AllowOrigin::async_predicate(
364    ///     |origin: HeaderValue, parts: &RequestParts| {
365    ///         let path = parts.uri.path().to_owned();
366    ///
367    ///         async move {
368    ///             // fetch list of origins that are allowed for this path
369    ///             let origins = client.fetch_allowed_origins_for_path(path).await;
370    ///             origins.contains(&origin)
371    ///         }
372    ///     },
373    /// ));
374    /// ```
375    ///
376    /// Note that multiple calls to this method will override any previous
377    /// calls.
378    ///
379    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
380    pub fn allow_origin<T>(mut self, origin: T) -> Self
381    where
382        T: Into<AllowOrigin>,
383    {
384        self.allow_origin = origin.into();
385        self
386    }
387
388    /// Set the value of the [`Access-Control-Expose-Headers`][mdn] header.
389    ///
390    /// ```
391    /// use tower_http::cors::CorsLayer;
392    /// use http::header::CONTENT_ENCODING;
393    ///
394    /// let layer = CorsLayer::new().expose_headers([CONTENT_ENCODING]);
395    /// ```
396    ///
397    /// All headers can be allowed with
398    ///
399    /// ```
400    /// use tower_http::cors::{Any, CorsLayer};
401    ///
402    /// let layer = CorsLayer::new().expose_headers(Any);
403    /// ```
404    ///
405    /// Note that multiple calls to this method will override any previous
406    /// calls.
407    ///
408    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
409    pub fn expose_headers<T>(mut self, headers: T) -> Self
410    where
411        T: Into<ExposeHeaders>,
412    {
413        self.expose_headers = headers.into();
414        self
415    }
416
417    /// Set the value of the [`Access-Control-Allow-Private-Network`][wicg] header.
418    ///
419    /// ```
420    /// use tower_http::cors::CorsLayer;
421    ///
422    /// let layer = CorsLayer::new().allow_private_network(true);
423    /// ```
424    ///
425    /// [wicg]: https://wicg.github.io/private-network-access/
426    pub fn allow_private_network<T>(mut self, allow_private_network: T) -> Self
427    where
428        T: Into<AllowPrivateNetwork>,
429    {
430        self.allow_private_network = allow_private_network.into();
431        self
432    }
433
434    /// Set the value(s) of the [`Vary`][mdn] header.
435    ///
436    /// In contrast to the other headers, this one has a non-empty default of
437    /// [`preflight_request_headers()`].
438    ///
439    /// You only need to set this is you want to remove some of these defaults,
440    /// or if you use a closure for one of the other headers and want to add a
441    /// vary header accordingly.
442    ///
443    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary
444    pub fn vary<T>(mut self, headers: T) -> Self
445    where
446        T: Into<Vary>,
447    {
448        self.vary = headers.into();
449        self
450    }
451}
452
453/// Represents a wildcard value (`*`) used with some CORS headers such as
454/// [`CorsLayer::allow_methods`].
455#[derive(Debug, Clone, Copy)]
456#[must_use]
457pub struct Any;
458
459/// Represents a wildcard value (`*`) used with some CORS headers such as
460/// [`CorsLayer::allow_methods`].
461#[deprecated = "Use Any as a unit struct literal instead"]
462pub fn any() -> Any {
463    Any
464}
465
466fn separated_by_commas<I>(mut iter: I) -> Option<HeaderValue>
467where
468    I: Iterator<Item = HeaderValue>,
469{
470    match iter.next() {
471        Some(fst) => {
472            let mut result = BytesMut::from(fst.as_bytes());
473            for val in iter {
474                result.reserve(val.len() + 1);
475                result.put_u8(b',');
476                result.extend_from_slice(val.as_bytes());
477            }
478
479            Some(HeaderValue::from_maybe_shared(result.freeze()).unwrap())
480        }
481        None => None,
482    }
483}
484
485impl Default for CorsLayer {
486    fn default() -> Self {
487        Self::new()
488    }
489}
490
491impl<S> Layer<S> for CorsLayer {
492    type Service = Cors<S>;
493
494    fn layer(&self, inner: S) -> Self::Service {
495        ensure_usable_cors_rules(self);
496
497        Cors {
498            inner,
499            layer: self.clone(),
500        }
501    }
502}
503
504/// Middleware which adds headers for [CORS][mdn].
505///
506/// See the [module docs](crate::cors) for an example.
507///
508/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
509#[derive(Debug, Clone)]
510#[must_use]
511pub struct Cors<S> {
512    inner: S,
513    layer: CorsLayer,
514}
515
516impl<S> Cors<S> {
517    /// Create a new `Cors`.
518    ///
519    /// See [`CorsLayer::new`] for more details.
520    pub fn new(inner: S) -> Self {
521        Self {
522            inner,
523            layer: CorsLayer::new(),
524        }
525    }
526
527    /// A permissive configuration.
528    ///
529    /// See [`CorsLayer::permissive`] for more details.
530    pub fn permissive(inner: S) -> Self {
531        Self {
532            inner,
533            layer: CorsLayer::permissive(),
534        }
535    }
536
537    /// A very permissive configuration.
538    ///
539    /// See [`CorsLayer::very_permissive`] for more details.
540    pub fn very_permissive(inner: S) -> Self {
541        Self {
542            inner,
543            layer: CorsLayer::very_permissive(),
544        }
545    }
546
547    define_inner_service_accessors!();
548
549    /// Returns a new [`Layer`] that wraps services with a [`Cors`] middleware.
550    ///
551    /// [`Layer`]: tower_layer::Layer
552    pub fn layer() -> CorsLayer {
553        CorsLayer::new()
554    }
555
556    /// Set the [`Access-Control-Allow-Credentials`][mdn] header.
557    ///
558    /// See [`CorsLayer::allow_credentials`] for more details.
559    ///
560    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
561    pub fn allow_credentials<T>(self, allow_credentials: T) -> Self
562    where
563        T: Into<AllowCredentials>,
564    {
565        self.map_layer(|layer| layer.allow_credentials(allow_credentials))
566    }
567
568    /// Set the value of the [`Access-Control-Allow-Headers`][mdn] header.
569    ///
570    /// See [`CorsLayer::allow_headers`] for more details.
571    ///
572    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
573    pub fn allow_headers<T>(self, headers: T) -> Self
574    where
575        T: Into<AllowHeaders>,
576    {
577        self.map_layer(|layer| layer.allow_headers(headers))
578    }
579
580    /// Set the value of the [`Access-Control-Max-Age`][mdn] header.
581    ///
582    /// See [`CorsLayer::max_age`] for more details.
583    ///
584    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
585    pub fn max_age<T>(self, max_age: T) -> Self
586    where
587        T: Into<MaxAge>,
588    {
589        self.map_layer(|layer| layer.max_age(max_age))
590    }
591
592    /// Set the value of the [`Access-Control-Allow-Methods`][mdn] header.
593    ///
594    /// See [`CorsLayer::allow_methods`] for more details.
595    ///
596    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
597    pub fn allow_methods<T>(self, methods: T) -> Self
598    where
599        T: Into<AllowMethods>,
600    {
601        self.map_layer(|layer| layer.allow_methods(methods))
602    }
603
604    /// Set the value of the [`Access-Control-Allow-Origin`][mdn] header.
605    ///
606    /// See [`CorsLayer::allow_origin`] for more details.
607    ///
608    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
609    pub fn allow_origin<T>(self, origin: T) -> Self
610    where
611        T: Into<AllowOrigin>,
612    {
613        self.map_layer(|layer| layer.allow_origin(origin))
614    }
615
616    /// Set the value of the [`Access-Control-Expose-Headers`][mdn] header.
617    ///
618    /// See [`CorsLayer::expose_headers`] for more details.
619    ///
620    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
621    pub fn expose_headers<T>(self, headers: T) -> Self
622    where
623        T: Into<ExposeHeaders>,
624    {
625        self.map_layer(|layer| layer.expose_headers(headers))
626    }
627
628    /// Set the value of the [`Access-Control-Allow-Private-Network`][wicg] header.
629    ///
630    /// See [`CorsLayer::allow_private_network`] for more details.
631    ///
632    /// [wicg]: https://wicg.github.io/private-network-access/
633    pub fn allow_private_network<T>(self, allow_private_network: T) -> Self
634    where
635        T: Into<AllowPrivateNetwork>,
636    {
637        self.map_layer(|layer| layer.allow_private_network(allow_private_network))
638    }
639
640    fn map_layer<F>(mut self, f: F) -> Self
641    where
642        F: FnOnce(CorsLayer) -> CorsLayer,
643    {
644        self.layer = f(self.layer);
645        self
646    }
647}
648
649impl<S, ReqBody, ResBody> Service<Request<ReqBody>> for Cors<S>
650where
651    S: Service<Request<ReqBody>, Response = Response<ResBody>>,
652    ResBody: Default,
653{
654    type Response = S::Response;
655    type Error = S::Error;
656    type Future = ResponseFuture<S::Future>;
657
658    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
659        ensure_usable_cors_rules(&self.layer);
660        self.inner.poll_ready(cx)
661    }
662
663    fn call(&mut self, req: Request<ReqBody>) -> Self::Future {
664        let (parts, body) = req.into_parts();
665        let origin = parts.headers.get(&header::ORIGIN);
666
667        let mut headers = HeaderMap::new();
668
669        // These headers are applied to both preflight and subsequent regular CORS requests:
670        // https://fetch.spec.whatwg.org/#http-responses
671
672        headers.extend(self.layer.allow_credentials.to_header(origin, &parts));
673        headers.extend(self.layer.allow_private_network.to_header(origin, &parts));
674        headers.extend(self.layer.vary.to_header());
675
676        let allow_origin_future = self.layer.allow_origin.to_future(origin, &parts);
677
678        // Return results immediately upon preflight request
679        if parts.method == Method::OPTIONS {
680            // These headers are applied only to preflight requests
681            headers.extend(self.layer.allow_methods.to_header(&parts));
682            headers.extend(self.layer.allow_headers.to_header(&parts));
683            headers.extend(self.layer.max_age.to_header(origin, &parts));
684
685            ResponseFuture {
686                inner: Kind::PreflightCall {
687                    allow_origin_future,
688                    headers,
689                },
690            }
691        } else {
692            // This header is applied only to non-preflight requests
693            headers.extend(self.layer.expose_headers.to_header(&parts));
694
695            let req = Request::from_parts(parts, body);
696            ResponseFuture {
697                inner: Kind::CorsCall {
698                    allow_origin_future,
699                    allow_origin_complete: false,
700                    future: self.inner.call(req),
701                    headers,
702                },
703            }
704        }
705    }
706}
707
708pin_project! {
709    /// Response future for [`Cors`].
710    pub struct ResponseFuture<F> {
711        #[pin]
712        inner: Kind<F>,
713    }
714}
715
716pin_project! {
717    #[project = KindProj]
718    enum Kind<F> {
719        CorsCall {
720            #[pin]
721            allow_origin_future: AllowOriginFuture,
722            allow_origin_complete: bool,
723            #[pin]
724            future: F,
725            headers: HeaderMap,
726        },
727        PreflightCall {
728            #[pin]
729            allow_origin_future: AllowOriginFuture,
730            headers: HeaderMap,
731        },
732    }
733}
734
735impl<F, B, E> Future for ResponseFuture<F>
736where
737    F: Future<Output = Result<Response<B>, E>>,
738    B: Default,
739{
740    type Output = Result<Response<B>, E>;
741
742    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
743        match self.project().inner.project() {
744            KindProj::CorsCall {
745                allow_origin_future,
746                allow_origin_complete,
747                future,
748                headers,
749            } => {
750                if !*allow_origin_complete {
751                    headers.extend(ready!(allow_origin_future.poll(cx)));
752                    *allow_origin_complete = true;
753                }
754
755                let mut response: Response<B> = ready!(future.poll(cx))?;
756
757                let response_headers = response.headers_mut();
758
759                // vary header can have multiple values, don't overwrite
760                // previously-set value(s).
761                if let Some(vary) = headers.remove(header::VARY) {
762                    response_headers.append(header::VARY, vary);
763                }
764                // extend will overwrite previous headers of remaining names
765                response_headers.extend(headers.drain());
766
767                Poll::Ready(Ok(response))
768            }
769            KindProj::PreflightCall {
770                allow_origin_future,
771                headers,
772            } => {
773                headers.extend(ready!(allow_origin_future.poll(cx)));
774
775                let mut response = Response::new(B::default());
776                mem::swap(response.headers_mut(), headers);
777
778                Poll::Ready(Ok(response))
779            }
780        }
781    }
782}
783
784fn ensure_usable_cors_rules(layer: &CorsLayer) {
785    if layer.allow_credentials.is_true() {
786        assert!(
787            !layer.allow_headers.is_wildcard(),
788            "Invalid CORS configuration: Cannot combine `Access-Control-Allow-Credentials: true` \
789             with `Access-Control-Allow-Headers: *`"
790        );
791
792        assert!(
793            !layer.allow_methods.is_wildcard(),
794            "Invalid CORS configuration: Cannot combine `Access-Control-Allow-Credentials: true` \
795             with `Access-Control-Allow-Methods: *`"
796        );
797
798        assert!(
799            !layer.allow_origin.is_wildcard(),
800            "Invalid CORS configuration: Cannot combine `Access-Control-Allow-Credentials: true` \
801             with `Access-Control-Allow-Origin: *`"
802        );
803
804        assert!(
805            !layer.expose_headers.is_wildcard(),
806            "Invalid CORS configuration: Cannot combine `Access-Control-Allow-Credentials: true` \
807             with `Access-Control-Expose-Headers: *`"
808        );
809    }
810}
811
812/// Returns an iterator over the three request headers that may be involved in a CORS preflight request.
813///
814/// This is the default set of header names returned in the `vary` header
815pub fn preflight_request_headers() -> impl Iterator<Item = HeaderName> {
816    #[allow(deprecated)] // Can be changed when MSRV >= 1.53
817    array::IntoIter::new([
818        header::ORIGIN,
819        header::ACCESS_CONTROL_REQUEST_METHOD,
820        header::ACCESS_CONTROL_REQUEST_HEADERS,
821    ])
822}