GCC Code Coverage Report


Directory: ./
File: libs/http_proto/src/server/cors.cpp
Date: 2025-12-02 19:05:14
Exec Total Coverage
Lines: 0 77 0.0%
Functions: 0 11 0.0%
Branches: 0 53 0.0%

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