Crow  1.1
A C++ microframework for the web
 
Loading...
Searching...
No Matches
cors.h
1#pragma once
2#include "crow/http_request.h"
3#include "crow/http_response.h"
4#include "crow/routing.h"
5
6namespace crow
7{
8 struct CORSHandler;
9
10 /// Used for tuning CORS policies
11 struct CORSRules
12 {
13 friend struct crow::CORSHandler;
14
15 /// Set Access-Control-Allow-Origin. Default is "*"
16 CORSRules& origin(const std::string& origin)
17 {
18 origin_ = origin;
19 return *this;
20 }
21
22 /// Set Access-Control-Allow-Methods. Default is "*"
23 CORSRules& methods(crow::HTTPMethod method)
24 {
25 add_list_item(methods_, crow::method_name(method));
26 return *this;
27 }
28
29 /// Set Access-Control-Allow-Methods. Default is "*"
30 template<typename... Methods>
31 CORSRules& methods(crow::HTTPMethod method, Methods... method_list)
32 {
33 add_list_item(methods_, crow::method_name(method));
34 methods(method_list...);
35 return *this;
36 }
37
38 /// Set Access-Control-Allow-Headers. Default is "*"
39 CORSRules& headers(const std::string& header)
40 {
41 add_list_item(headers_, header);
42 return *this;
43 }
44
45 /// Set Access-Control-Allow-Headers. Default is "*"
46 template<typename... Headers>
47 CORSRules& headers(const std::string& header, Headers... header_list)
48 {
49 add_list_item(headers_, header);
50 headers(header_list...);
51 return *this;
52 }
53
54 /// Set Access-Control-Expose-Headers. Default is none
55 CORSRules& expose(const std::string& header)
56 {
57 add_list_item(exposed_headers_, header);
58 return *this;
59 }
60
61 /// Set Access-Control-Expose-Headers. Default is none
62 template<typename... Headers>
63 CORSRules& expose(const std::string& header, Headers... header_list)
64 {
65 add_list_item(exposed_headers_, header);
66 expose(header_list...);
67 return *this;
68 }
69
70 /// Set Access-Control-Max-Age. Default is none
72 {
73 max_age_ = std::to_string(max_age);
74 return *this;
75 }
76
77 /// Enable Access-Control-Allow-Credentials
79 {
80 allow_credentials_ = true;
81 return *this;
82 }
83
84 /// Ignore CORS and don't send any headers
85 void ignore()
86 {
87 ignore_ = true;
88 }
89
90 /// Handle CORS on specific prefix path
91 CORSRules& prefix(const std::string& prefix);
92
93 /// Handle CORS for specific blueprint
94 CORSRules& blueprint(const Blueprint& bp);
95
96 /// Global CORS policy
98
99 private:
100 CORSRules() = delete;
101 CORSRules(CORSHandler* handler):
102 handler_(handler) {}
103
104 /// build comma separated list
105 void add_list_item(std::string& list, const std::string& val)
106 {
107 if (list == "*") list = "";
108 if (list.size() > 0) list += ", ";
109 list += val;
110 }
111
112 /// Set header `key` to `value` if it is not set
113 void set_header_no_override(const std::string& key, const std::string& value, crow::response& res)
114 {
115 if (value.size() == 0) return;
116 if (!get_header_value(res.headers, key).empty()) return;
117 res.add_header(key, value);
118 }
119
120 /// Set response headers
121 void apply(const request& req, response& res)
122 {
123 if (ignore_) return;
124
125 set_header_no_override("Access-Control-Allow-Methods", methods_, res);
126 set_header_no_override("Access-Control-Allow-Headers", headers_, res);
127 set_header_no_override("Access-Control-Expose-Headers", exposed_headers_, res);
128 set_header_no_override("Access-Control-Max-Age", max_age_, res);
129 if (allow_credentials_) set_header_no_override("Access-Control-Allow-Credentials", "true", res);
130
131 if (allow_credentials_ && origin_ == "*")
132 set_header_no_override("Access-Control-Allow-Origin", req.get_header_value("Origin"), res);
133 else
134 set_header_no_override("Access-Control-Allow-Origin", origin_, res);
135 }
136
137 bool ignore_ = false;
138 // TODO: support multiple origins that are dynamically selected
139 std::string origin_ = "*";
140 std::string methods_ = "*";
141 std::string headers_ = "*";
142 std::string exposed_headers_;
143 std::string max_age_;
144 bool allow_credentials_ = false;
145
146 CORSHandler* handler_;
147 };
148
149 /// CORSHandler is a global middleware for setting CORS headers.
150
151 ///
152 /// By default, it sets Access-Control-Allow-Origin/Methods/Headers to "*".
153 /// The default behaviour can be changed with the `global()` cors rule.
154 /// Additional rules for prexies can be added with `prefix()`.
156 {
157 struct context
158 {};
159
160 void before_handle(crow::request& /*req*/, crow::response& /*res*/, context& /*ctx*/)
161 {}
162
163 void after_handle(crow::request& req, crow::response& res, context& /*ctx*/)
164 {
165 auto& rule = find_rule(req.url);
166 rule.apply(req, res);
167 }
168
169 /// Handle CORS on a specific prefix path
170 CORSRules& prefix(const std::string& prefix)
171 {
172 rules.emplace_back(prefix, CORSRules(this));
173 return rules.back().second;
174 }
175
176 /// Handle CORS for a specific blueprint
178 {
179 rules.emplace_back(bp.prefix(), CORSRules(this));
180 return rules.back().second;
181 }
182
183 /// Get the global CORS policy
185 {
186 return default_;
187 }
188
189 private:
190 CORSRules& find_rule(const std::string& path)
191 {
192 // TODO: use a trie in case of many rules
193 for (auto& rule : rules)
194 {
195 // Check if path starts with a rules prefix
196 if (path.rfind(rule.first, 0) == 0)
197 {
198 return rule.second;
199 }
200 }
201 return default_;
202 }
203
204 std::vector<std::pair<std::string, CORSRules>> rules;
205 CORSRules default_ = CORSRules(this);
206 };
207
208 inline CORSRules& CORSRules::prefix(const std::string& prefix)
209 {
210 return handler_->prefix(prefix);
211 }
212
214 {
215 return handler_->blueprint(bp);
216 }
217
219 {
220 return handler_->global();
221 }
222
223} // namespace crow
A blueprint can be considered a smaller section of a Crow app, specifically where the router is conce...
Definition routing.h:1091
The main namespace of the library. In this namespace is defined the most important classes and functi...
const std::string & get_header_value(const T &headers, const std::string &key)
Find and return the value associated with the key. (returns an empty string if nothing is found)
Definition http_request.h:24
Definition cors.h:158
CORSHandler is a global middleware for setting CORS headers.
Definition cors.h:156
CORSRules & global()
Get the global CORS policy.
Definition cors.h:184
CORSRules & blueprint(const Blueprint &bp)
Handle CORS for a specific blueprint.
Definition cors.h:177
CORSRules & prefix(const std::string &prefix)
Handle CORS on a specific prefix path.
Definition cors.h:170
Used for tuning CORS policies.
Definition cors.h:12
CORSRules & global()
Global CORS policy.
Definition cors.h:218
CORSRules & origin(const std::string &origin)
Set Access-Control-Allow-Origin. Default is "*".
Definition cors.h:16
CORSRules & methods(crow::HTTPMethod method, Methods... method_list)
Set Access-Control-Allow-Methods. Default is "*".
Definition cors.h:31
CORSRules & headers(const std::string &header)
Set Access-Control-Allow-Headers. Default is "*".
Definition cors.h:39
CORSRules & expose(const std::string &header)
Set Access-Control-Expose-Headers. Default is none.
Definition cors.h:55
CORSRules & headers(const std::string &header, Headers... header_list)
Set Access-Control-Allow-Headers. Default is "*".
Definition cors.h:47
CORSRules & expose(const std::string &header, Headers... header_list)
Set Access-Control-Expose-Headers. Default is none.
Definition cors.h:63
CORSRules & prefix(const std::string &prefix)
Handle CORS on specific prefix path.
Definition cors.h:208
CORSRules & max_age(int max_age)
Set Access-Control-Max-Age. Default is none.
Definition cors.h:71
CORSRules & blueprint(const Blueprint &bp)
Handle CORS for specific blueprint.
Definition cors.h:213
CORSRules & allow_credentials()
Enable Access-Control-Allow-Credentials.
Definition cors.h:78
CORSRules & methods(crow::HTTPMethod method)
Set Access-Control-Allow-Methods. Default is "*".
Definition cors.h:23
void ignore()
Ignore CORS and don't send any headers.
Definition cors.h:85
An HTTP request.
Definition http_request.h:36
std::string url
The endpoint without any parameters.
Definition http_request.h:39
HTTP response.
Definition http_response.h:34
void add_header(std::string key, std::string value)
Add a new header to the response.
Definition http_response.h:58
ci_map headers
HTTP headers.
Definition http_response.h:42