# Crow: include/crow/middlewares/cors.h Source File

cors.h
#pragma once
#include "crow/http_request.h"
#include "crow/http_response.h"
#include "crow/routing.h"
namespace crow
{
struct CORSHandler;
/// Used for tuning CORS policies
struct CORSRules
{
friend struct crow::CORSHandler;
/// Set Access-Control-Allow-Origin. Default is "*"
CORSRules& origin(const std::string& origin)
{
origin_ = origin;
return *this;
}
/// Set Access-Control-Allow-Methods. Default is "*"
CORSRules& methods(crow::HTTPMethod method)
{
add_list_item(methods_, crow::method_name(method));
return *this;
}
/// Set Access-Control-Allow-Methods. Default is "*"
template<typename... Methods>
CORSRules& methods(crow::HTTPMethod method, Methods... method_list)
{
add_list_item(methods_, crow::method_name(method));
methods(method_list...);
return *this;
}
/// Set Access-Control-Allow-Headers. Default is "*"
CORSRules& headers(const std::string& header)
{
add_list_item(headers_, header);
return *this;
}
/// Set Access-Control-Allow-Headers. Default is "*"
template<typename... Headers>
CORSRules& headers(const std::string& header, Headers... header_list)
{
add_list_item(headers_, header);
headers(header_list...);
return *this;
}
/// Set Access-Control-Max-Age. Default is none
CORSRules& max_age(int max_age)
{
max_age_ = std::to_string(max_age);
return *this;
}
/// Enable Access-Control-Allow-Credentials
CORSRules& allow_credentials()
{
allow_credentials_ = true;
return *this;
}
/// Ignore CORS and don't send any headers
void ignore()
{
ignore_ = true;
}
/// Handle CORS on specific prefix path
CORSRules& prefix(const std::string& prefix);
/// Handle CORS for specific blueprint
CORSRules& blueprint(const Blueprint& bp);
/// Global CORS policy
CORSRules& global();
private:
CORSRules() = delete;
CORSRules(CORSHandler* handler):
handler_(handler) {}
/// build comma separated list
void add_list_item(std::string& list, const std::string& val)
{
if (list == "*") list = "";
if (list.size() > 0) list += ", ";
list += val;
}
/// Set header `key` to `value` if it is not set
void set_header_no_override(const std::string& key, const std::string& value, crow::response& res)
{
if (value.size() == 0) return;
if (!get_header_value(res.headers, key).empty()) return;
res.add_header(key, value);
}
/// Set response headers
void apply(crow::response& res)
{
if (ignore_) return;
set_header_no_override("Access-Control-Allow-Origin", origin_, res);
set_header_no_override("Access-Control-Allow-Methods", methods_, res);
set_header_no_override("Access-Control-Allow-Headers", headers_, res);
set_header_no_override("Access-Control-Max-Age", max_age_, res);
if (allow_credentials_) set_header_no_override("Access-Control-Allow-Credentials", "true", res);
}
bool ignore_ = false;
// TODO: support multiple origins that are dynamically selected
std::string origin_ = "*";
std::string methods_ = "*";
std::string headers_ = "*";
std::string max_age_;
bool allow_credentials_ = false;
CORSHandler* handler_;
};
/// CORSHandler is a global middleware for setting CORS headers.
///
/// By default, it sets Access-Control-Allow-Origin/Methods/Headers to "*".
/// The default behaviour can be changed with the `global()` cors rule.
/// Additional rules for prexies can be added with `prefix()`.
struct CORSHandler
{
struct context
{};
void before_handle(crow::request& /*req*/, crow::response& /*res*/, context& /*ctx*/)
{}
void after_handle(crow::request& req, crow::response& res, context& /*ctx*/)
{
auto& rule = find_rule(req.url);
rule.apply(res);
}
/// Handle CORS on a specific prefix path
CORSRules& prefix(const std::string& prefix)
{
rules.emplace_back(prefix, CORSRules(this));
return rules.back().second;
}
/// Handle CORS for a specific blueprint
CORSRules& blueprint(const Blueprint& bp)
{
rules.emplace_back(bp.prefix(), CORSRules(this));
return rules.back().second;
}
/// Get the global CORS policy
CORSRules& global()
{
return default_;
}
private:
CORSRules& find_rule(const std::string& path)
{
// TODO: use a trie in case of many rules
for (auto& rule : rules)
{
// Check if path starts with a rules prefix
if (path.rfind(rule.first, 0) == 0)
{
return rule.second;
}
}
return default_;
}
std::vector<std::pair<std::string, CORSRules>> rules;
CORSRules default_ = CORSRules(this);
};
inline CORSRules& CORSRules::prefix(const std::string& prefix)
{
return handler_->prefix(prefix);
}
inline CORSRules& CORSRules::blueprint(const Blueprint& bp)
{
return handler_->blueprint(bp);
}
inline CORSRules& CORSRules::global()
{
return handler_->global();
}
} // namespace crow
crow::Blueprint
A blueprint can be considered a smaller section of a Crow app, specifically where the router is conec...
Definition: routing.h:1104
crow
The main namespace of the library. In this namespace is defined the most important classes and functi...
crow::get_header_value
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
crow::CORSHandler::context
Definition: cors.h:135
crow::CORSHandler
CORSHandler is a global middleware for setting CORS headers.
Definition: cors.h:133
crow::CORSHandler::blueprint
CORSRules & blueprint(const Blueprint &bp)
Handle CORS for a specific blueprint.
Definition: cors.h:154
crow::CORSHandler::prefix
CORSRules & prefix(const std::string &prefix)
Handle CORS on a specific prefix path.
Definition: cors.h:147
crow::CORSHandler::global
CORSRules & global()
Get the global CORS policy.
Definition: cors.h:161
crow::CORSRules
Used for tuning CORS policies.
Definition: cors.h:12
crow::CORSRules::global
CORSRules & global()
Global CORS policy.
Definition: cors.h:195
crow::CORSRules::origin
CORSRules & origin(const std::string &origin)
Set Access-Control-Allow-Origin. Default is "*".
Definition: cors.h:16
crow::CORSRules::methods
CORSRules & methods(crow::HTTPMethod method)
Set Access-Control-Allow-Methods. Default is "*".
Definition: cors.h:23
crow::CORSRules::methods
CORSRules & methods(crow::HTTPMethod method, Methods... method_list)
Set Access-Control-Allow-Methods. Default is "*".
Definition: cors.h:31
crow::CORSRules::prefix
CORSRules & prefix(const std::string &prefix)
Handle CORS on specific prefix path.
Definition: cors.h:185
crow::CORSRules::max_age
CORSRules & max_age(int max_age)
Set Access-Control-Max-Age. Default is none.
Definition: cors.h:55
crow::CORSRules::allow_credentials
CORSRules & allow_credentials()
Enable Access-Control-Allow-Credentials.
Definition: cors.h:62
crow::CORSRules::blueprint
CORSRules & blueprint(const Blueprint &bp)
Handle CORS for specific blueprint.
Definition: cors.h:190
crow::CORSRules::headers
CORSRules & headers(const std::string &header, Headers... header_list)
Set Access-Control-Allow-Headers. Default is "*".
Definition: cors.h:47
crow::CORSRules::headers
CORSRules & headers(const std::string &header)
Set Access-Control-Allow-Headers. Default is "*".
Definition: cors.h:39
crow::CORSRules::ignore
void ignore()
Ignore CORS and don't send any headers.
Definition: cors.h:69
crow::request
An HTTP request.
Definition: http_request.h:36
crow::request::url
std::string url
The endpoint without any parameters.
Definition: http_request.h:39
crow::response
HTTP response.
Definition: http_response.h:34
crow::response::add_header
void add_header(std::string key, std::string value)
Add a new header to the response.
Definition: http_response.h:58
crow::response::headers
ci_map headers
HTTP headers.
Definition: http_response.h:42