LCOV - code coverage report
Current view: top level - libs/http/src/server - cors.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 0.0 % 59 0
Test Date: 2026-01-20 00:11:34 Functions: 0.0 % 11 0

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
       3              : //
       4              : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5              : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6              : //
       7              : // Official repository: https://github.com/cppalliance/http
       8              : //
       9              : 
      10              : #include <boost/http/server/cors.hpp>
      11              : #include <utility>
      12              : 
      13              : namespace boost {
      14              : namespace http {
      15              : 
      16            0 : cors::
      17              : cors(
      18            0 :     cors_options options) noexcept
      19            0 :     : options_(std::move(options))
      20              : {
      21              :     // VFALCO TODO Validate the strings in options against RFC
      22            0 : }
      23              : 
      24              : namespace {
      25              : 
      26              : struct Vary
      27              : {
      28            0 :     Vary(route_params& rp)
      29            0 :         : rp_(rp)
      30              :     {
      31            0 :     }
      32              : 
      33            0 :     void set(field f, core::string_view s)
      34              :     {
      35            0 :         rp_.res.set(f, s);
      36            0 :     }
      37              : 
      38            0 :     void append(field f, core::string_view v)
      39              :     {
      40            0 :         auto it = rp_.res.find(f);
      41            0 :         if(it != rp_.res.end())
      42              :         {
      43            0 :             std::string s = it->value;
      44            0 :             s += ", ";
      45            0 :             s += v;
      46            0 :             rp_.res.set(it, s);
      47            0 :         }
      48              :         else
      49              :         {
      50            0 :             rp_.res.set(f, v);
      51              :         }
      52            0 :     }
      53              : 
      54              : private:
      55              :     route_params& rp_;
      56              : };
      57              : 
      58              : } // (anon)
      59              : 
      60              : // Access-Control-Allow-Origin
      61            0 : static void setOrigin(
      62              :     Vary& v,
      63              :     route_params const&,
      64              :     cors_options const& options)
      65              : {
      66            0 :     if( options.origin.empty() ||
      67            0 :         options.origin == "*")
      68              :     {
      69            0 :         v.set(field::access_control_allow_origin, "*");
      70            0 :         return;
      71              :     }
      72              : 
      73            0 :     v.set(
      74              :         field::access_control_allow_origin,
      75            0 :         options.origin);
      76            0 :     v.append(field::vary, to_string(field::origin));
      77              : }
      78              : 
      79              : // Access-Control-Allow-Methods
      80            0 : static void setMethods(
      81              :     Vary& v,
      82              :     cors_options const& options)
      83              : {
      84            0 :     if(! options.methods.empty())
      85              :     {
      86            0 :         v.set(
      87              :             field::access_control_allow_methods,
      88            0 :             options.methods);
      89            0 :         return;
      90              :     }
      91            0 :     v.set(
      92              :         field::access_control_allow_methods,
      93              :         "GET,HEAD,PUT,PATCH,POST,DELETE");
      94              : }
      95              : 
      96              : // Access-Control-Allow-Credentials
      97            0 : static void setCredentials(
      98              :     Vary& v,
      99              :     cors_options const& options)
     100              : {
     101            0 :     if(! options.credentials)
     102            0 :         return;
     103            0 :     v.set(
     104              :         field::access_control_allow_credentials,
     105              :         "true");
     106              : }
     107              : 
     108              : // Access-Control-Allowed-Headers
     109            0 : static void setAllowedHeaders(
     110              :     Vary& v,
     111              :     route_params const& rp,
     112              :     cors_options const& options)
     113              : {
     114            0 :     if(! options.allowedHeaders.empty())
     115              :     {
     116            0 :         v.set(
     117              :             field::access_control_allow_headers,
     118            0 :             options.allowedHeaders);
     119            0 :         return;
     120              :     }
     121            0 :     auto s = rp.req.value_or(
     122              :         field::access_control_request_headers, "");
     123            0 :     if(! s.empty())
     124              :     {
     125            0 :         v.set(field::access_control_allow_headers, s);
     126            0 :         v.append(field::vary, s);
     127              :     }
     128              : }
     129              : 
     130              : // Access-Control-Expose-Headers
     131            0 : static void setExposeHeaders(
     132              :     Vary& v,
     133              :     cors_options const& options)
     134              : {
     135            0 :     if(options.exposedHeaders.empty())
     136            0 :         return;
     137            0 :     v.set(
     138              :         field::access_control_expose_headers,
     139            0 :         options.exposedHeaders);
     140              : }
     141              : 
     142              : // Access-Control-Max-Age
     143            0 : static void setMaxAge(
     144              :     Vary& v,
     145              :     cors_options const& options)
     146              : {
     147            0 :     if(options.max_age.count() == 0)
     148            0 :         return;
     149            0 :     v.set(
     150              :         field::access_control_max_age,
     151            0 :         std::to_string(
     152              :             options.max_age.count()));
     153              : }
     154              : 
     155              : route_task
     156            0 : cors::
     157              : operator()(
     158              :     route_params& rp) const
     159              : {
     160              :     Vary v(rp);
     161              :     if(rp.req.method() == method::options)
     162              :     {
     163              :         // preflight
     164              :         setOrigin(v, rp, options_);
     165              :         setMethods(v, options_);
     166              :         setCredentials(v, options_);
     167              :         setAllowedHeaders(v, rp, options_);
     168              :         setMaxAge(v, options_);
     169              :         setExposeHeaders(v, options_);
     170              : 
     171              :         if(options_.preFlightContinue)
     172              :             co_return route::next;
     173              : 
     174              :         // Safari and others need this for 204 or may hang
     175              :         rp.res.set_status(options_.result);
     176              :         co_return co_await rp.send("");
     177              :     }
     178              : 
     179              :     // actual response
     180              :     setOrigin(v, rp, options_);
     181              :     setCredentials(v, options_);
     182              :     setExposeHeaders(v, options_);
     183              :     co_return route::next;
     184            0 : }
     185              : 
     186              : } // http
     187              : } // boost
        

Generated by: LCOV version 2.3