LCOV - code coverage report
Current view: top level - libs/http_proto/src/server - cors.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 0.0 % 77 0
Test Date: 2025-12-02 19:05:12 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_proto
       8              : //
       9              : 
      10              : #include <boost/http_proto/server/cors.hpp>
      11              : #include <utility>
      12              : 
      13              : namespace boost {
      14              : namespace http_proto {
      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(Response& res)
      29            0 :         : res_(res)
      30              :     {
      31            0 :     }
      32              : 
      33            0 :     void set(field f, core::string_view s)
      34              :     {
      35            0 :         res_.message.set(f, s);
      36            0 :     }
      37              : 
      38            0 :     void append(field f, core::string_view v)
      39              :     {
      40            0 :         auto it = res_.message.find(f);
      41            0 :         if (it != res_.message.end())
      42              :         {
      43            0 :             std::string s = it->value;
      44            0 :             s += ", ";
      45            0 :             s += v;
      46            0 :             res_.message.set(it, s);
      47            0 :         }
      48              :         else
      49              :         {
      50            0 :             res_.message.set(f, v);
      51              :         }
      52            0 :     }
      53              : 
      54              : private:
      55              :     Response& res_;
      56              :     std::string v_;
      57              : };
      58              : 
      59              : } // (anon)
      60              : 
      61              : // Access-Control-Allow-Origin
      62            0 : static void setOrigin(
      63              :     Vary& v,
      64              :     Request const&,
      65              :     cors_options const& options)
      66              : {
      67            0 :     if( options.origin.empty() ||
      68            0 :         options.origin == "*")
      69              :     {
      70            0 :         v.set(field::access_control_allow_origin, "*");
      71            0 :         return;
      72              :     }
      73              : 
      74            0 :     v.set(
      75              :         field::access_control_allow_origin,
      76            0 :         options.origin);
      77            0 :     v.append(field::vary, to_string(field::origin));
      78              : }
      79              : 
      80              : // Access-Control-Allow-Methods
      81            0 : static void setMethods(
      82              :     Vary& v,
      83              :     cors_options const& options)
      84              : {
      85            0 :     if(! options.methods.empty())
      86              :     {
      87            0 :         v.set(
      88              :             field::access_control_allow_methods,
      89            0 :             options.methods);
      90            0 :         return;
      91              :     }
      92            0 :     v.set(
      93              :         field::access_control_allow_methods,
      94              :         "GET,HEAD,PUT,PATCH,POST,DELETE");
      95              : }
      96              : 
      97              : // Access-Control-Allow-Credentials
      98            0 : static void setCredentials(
      99              :     Vary& v,
     100              :     cors_options const& options)
     101              : {
     102            0 :     if(! options.credentials)
     103            0 :         return;
     104            0 :     v.set(
     105              :         field::access_control_allow_credentials,
     106              :         "true");
     107              : }
     108              : 
     109              : // Access-Control-Allowed-Headers
     110            0 : static void setAllowedHeaders(
     111              :     Vary& v,
     112              :     Request const& req,
     113              :     cors_options const& options)
     114              : {
     115            0 :     if(! options.allowedHeaders.empty())
     116              :     {
     117            0 :         v.set(
     118              :             field::access_control_allow_headers,
     119            0 :             options.allowedHeaders);
     120            0 :         return;
     121              :     }
     122            0 :     auto s = req.message.value_or(
     123              :         field::access_control_request_headers, "");
     124            0 :     if(! s.empty())
     125              :     {
     126            0 :         v.set(
     127              :             field::access_control_allow_headers,
     128              :             s);
     129            0 :         v.append(field::vary, s);
     130              :     }
     131              : }
     132              : 
     133              : // Access-Control-Expose-Headers
     134            0 : static void setExposeHeaders(
     135              :     Vary& v,
     136              :     cors_options const& options)
     137              : {
     138            0 :     if(options.exposedHeaders.empty())
     139            0 :         return;
     140            0 :     v.set(
     141              :         field::access_control_expose_headers,
     142            0 :         options.exposedHeaders);
     143              : }
     144              : 
     145              : // Access-Control-Max-Age
     146            0 : static void setMaxAge(
     147              :     Vary& v,
     148              :     cors_options const& options)
     149              : {
     150            0 :     if(options.max_age.count() == 0)
     151            0 :         return;
     152            0 :     v.set(
     153              :         field::access_control_max_age,
     154            0 :         std::to_string(
     155              :             options.max_age.count()));
     156              : }
     157              : 
     158              : route_result
     159            0 : cors::
     160              : operator()(
     161              :     Request& req,
     162              :     Response& res) const
     163              : {
     164            0 :     Vary v(res);
     165            0 :     if(req.message.method() ==
     166              :         method::options)
     167              :     {
     168              :         // preflight
     169            0 :         setOrigin(v, req, options_);
     170            0 :         setMethods(v, options_);
     171            0 :         setCredentials(v, options_);
     172            0 :         setAllowedHeaders(v, req, options_);
     173            0 :         setMaxAge(v, options_);
     174            0 :         setExposeHeaders(v, options_);
     175              : 
     176            0 :         if(options_.preFligthContinue)
     177            0 :             return route::next;
     178              :         // Safari and others need this for 204 or may hang
     179            0 :         res.message.set_status(options_.result);
     180            0 :         res.message.set_content_length(0);
     181            0 :         res.serializer.start(res.message);
     182            0 :         return route::send;
     183              :     }
     184              :     // actual response
     185            0 :     setOrigin(v, req, options_);
     186            0 :     setCredentials(v, options_);
     187            0 :     setExposeHeaders(v, options_);
     188            0 :     return route::next;
     189            0 : }
     190              : 
     191              : } // http_proto
     192              : } // boost
        

Generated by: LCOV version 2.1