mirror of
https://github.com/CrowCpp/Crow.git
synced 2024-06-07 21:10:44 +00:00
6444748269
modified merge script to include middlewares, all are included by default include excludes everything else (items separated by ',') exclude only excludes selected items (items separated by ',')
132 lines
4.1 KiB
C++
132 lines
4.1 KiB
C++
#pragma once
|
|
#include <boost/algorithm/string/trim.hpp>
|
|
#include "crow/http_request.h"
|
|
#include "crow/http_response.h"
|
|
|
|
namespace crow
|
|
{
|
|
// Any middleware requires following 3 members:
|
|
|
|
// struct context;
|
|
// storing data for the middleware; can be read from another middleware or handlers
|
|
|
|
// before_handle
|
|
// called before handling the request.
|
|
// if res.end() is called, the operation is halted.
|
|
// (still call after_handle of this middleware)
|
|
// 2 signatures:
|
|
// void before_handle(request& req, response& res, context& ctx)
|
|
// if you only need to access this middlewares context.
|
|
// template <typename AllContext>
|
|
// void before_handle(request& req, response& res, context& ctx, AllContext& all_ctx)
|
|
// you can access another middlewares' context by calling `all_ctx.template get<MW>()'
|
|
// ctx == all_ctx.template get<CurrentMiddleware>()
|
|
|
|
// after_handle
|
|
// called after handling the request.
|
|
// void after_handle(request& req, response& res, context& ctx)
|
|
// template <typename AllContext>
|
|
// void after_handle(request& req, response& res, context& ctx, AllContext& all_ctx)
|
|
|
|
struct CookieParser
|
|
{
|
|
struct context
|
|
{
|
|
std::unordered_map<std::string, std::string> jar;
|
|
std::unordered_map<std::string, std::string> cookies_to_add;
|
|
|
|
std::string get_cookie(const std::string& key) const
|
|
{
|
|
auto cookie = jar.find(key);
|
|
if (cookie != jar.end())
|
|
return cookie->second;
|
|
return {};
|
|
}
|
|
|
|
void set_cookie(const std::string& key, const std::string& value)
|
|
{
|
|
cookies_to_add.emplace(key, value);
|
|
}
|
|
};
|
|
|
|
void before_handle(request& req, response& res, context& ctx)
|
|
{
|
|
int count = req.headers.count("Cookie");
|
|
if (!count)
|
|
return;
|
|
if (count > 1)
|
|
{
|
|
res.code = 400;
|
|
res.end();
|
|
return;
|
|
}
|
|
std::string cookies = req.get_header_value("Cookie");
|
|
size_t pos = 0;
|
|
while(pos < cookies.size())
|
|
{
|
|
size_t pos_equal = cookies.find('=', pos);
|
|
if (pos_equal == cookies.npos)
|
|
break;
|
|
std::string name = cookies.substr(pos, pos_equal-pos);
|
|
boost::trim(name);
|
|
pos = pos_equal+1;
|
|
while(pos < cookies.size() && cookies[pos] == ' ') pos++;
|
|
if (pos == cookies.size())
|
|
break;
|
|
|
|
size_t pos_semicolon = cookies.find(';', pos);
|
|
std::string value = cookies.substr(pos, pos_semicolon-pos);
|
|
|
|
boost::trim(value);
|
|
if (value[0] == '"' && value[value.size()-1] == '"')
|
|
{
|
|
value = value.substr(1, value.size()-2);
|
|
}
|
|
|
|
ctx.jar.emplace(std::move(name), std::move(value));
|
|
|
|
pos = pos_semicolon;
|
|
if (pos == cookies.npos)
|
|
break;
|
|
pos++;
|
|
while(pos < cookies.size() && cookies[pos] == ' ') pos++;
|
|
}
|
|
}
|
|
|
|
void after_handle(request& /*req*/, response& res, context& ctx)
|
|
{
|
|
for(auto& cookie:ctx.cookies_to_add)
|
|
{
|
|
if (cookie.second.empty())
|
|
res.add_header("Set-Cookie", cookie.first + "=\"\"");
|
|
else
|
|
res.add_header("Set-Cookie", cookie.first + "=" + cookie.second);
|
|
}
|
|
}
|
|
};
|
|
|
|
/*
|
|
App<CookieParser, AnotherJarMW> app;
|
|
A B C
|
|
A::context
|
|
int aa;
|
|
|
|
ctx1 : public A::context
|
|
ctx2 : public ctx1, public B::context
|
|
ctx3 : public ctx2, public C::context
|
|
|
|
C depends on A
|
|
|
|
C::handle
|
|
context.aaa
|
|
|
|
App::context : private CookieParser::contetx, ...
|
|
{
|
|
jar
|
|
|
|
}
|
|
|
|
SimpleApp
|
|
*/
|
|
}
|