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