216 lines
7.7 KiB
C++
216 lines
7.7 KiB
C++
#include "./render.h"
|
|
|
|
#include <c++utilities/conversion/stringbuilder.h>
|
|
|
|
#include <boost/beast/core.hpp>
|
|
#include <boost/beast/version.hpp>
|
|
|
|
using namespace std;
|
|
using namespace boost::beast;
|
|
using namespace CppUtilities;
|
|
|
|
namespace LibRepoMgr {
|
|
namespace WebAPI {
|
|
namespace Render {
|
|
|
|
string escapeHtml(std::string_view unescapedStr)
|
|
{
|
|
// allocate string for result
|
|
string::size_type requiredSize = unescapedStr.size();
|
|
for (const auto &c : unescapedStr) {
|
|
switch (c) {
|
|
case '&':
|
|
requiredSize += 4;
|
|
break;
|
|
case '\"':
|
|
case '\'':
|
|
requiredSize += 5;
|
|
break;
|
|
case '<':
|
|
case '>':
|
|
requiredSize += 3;
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
string escapedStr;
|
|
escapedStr.reserve(requiredSize);
|
|
|
|
// make escaped string
|
|
for (const auto &c : unescapedStr) {
|
|
switch (c) {
|
|
case '&':
|
|
escapedStr += "&";
|
|
break;
|
|
case '\"':
|
|
escapedStr += """;
|
|
break;
|
|
case '\'':
|
|
escapedStr += "'";
|
|
break;
|
|
case '<':
|
|
escapedStr += "<";
|
|
break;
|
|
case '>':
|
|
escapedStr += ">";
|
|
break;
|
|
default:
|
|
escapedStr += c;
|
|
}
|
|
}
|
|
return escapedStr;
|
|
}
|
|
|
|
std::shared_ptr<Response> makeOptions(const Request &request, std::string_view origin, std::string_view methods, std::string_view headers)
|
|
{
|
|
const auto res = make_shared<Response>(http::status::ok, request.version());
|
|
res->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
res->set(http::field::access_control_allow_origin, boost::beast::string_view(origin.data(), origin.size()));
|
|
res->set(http::field::access_control_allow_methods, boost::beast::string_view(methods.data(), methods.size()));
|
|
res->set(http::field::access_control_allow_headers, boost::beast::string_view(headers.data(), headers.size()));
|
|
res->keep_alive(request.keep_alive());
|
|
res->prepare_payload();
|
|
return res;
|
|
}
|
|
|
|
std::shared_ptr<Response> makeBadRequest(const Request &request, std::string_view why)
|
|
{
|
|
const auto res = make_shared<Response>(http::status::bad_request, request.version());
|
|
res->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
res->set(http::field::content_type, "text/plain");
|
|
res->set(http::field::access_control_allow_origin, "*");
|
|
res->keep_alive(request.keep_alive());
|
|
res->body() = why;
|
|
res->prepare_payload();
|
|
return res;
|
|
}
|
|
|
|
std::shared_ptr<Response> makeBadRequest(const Request &request, RAPIDJSON_NAMESPACE::StringBuffer &&why)
|
|
{
|
|
const auto res = make_shared<Response>(http::status::bad_request, request.version());
|
|
res->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
res->set(http::field::content_type, "application/json");
|
|
res->set(http::field::access_control_allow_origin, "*");
|
|
res->keep_alive(request.keep_alive());
|
|
res->body().assign(why.GetString(), why.GetSize());
|
|
res->prepare_payload();
|
|
return res;
|
|
}
|
|
|
|
std::shared_ptr<Response> makeNotFound(const Request &request, std::string_view target)
|
|
{
|
|
const auto res = make_shared<Response>(http::status::not_found, request.version());
|
|
res->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
res->set(http::field::content_type, "text/plain");
|
|
res->set(http::field::access_control_allow_origin, "*");
|
|
res->keep_alive(request.keep_alive());
|
|
res->body() = "The resource '" % target + "' was not found.";
|
|
res->prepare_payload();
|
|
return res;
|
|
}
|
|
|
|
std::shared_ptr<Response> makeAuthRequired(const Request &request)
|
|
{
|
|
const auto res = make_shared<Response>(http::status::unauthorized, request.version());
|
|
res->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
res->set(http::field::content_type, "text/plain");
|
|
res->set(http::field::www_authenticate, "Basic realm=\"auth required\"");
|
|
res->set(http::field::access_control_allow_origin, "*");
|
|
res->keep_alive(request.keep_alive());
|
|
res->body() = "Authenticate to access the resource.";
|
|
res->prepare_payload();
|
|
return res;
|
|
}
|
|
|
|
std::shared_ptr<Response> makeForbidden(const Request &request)
|
|
{
|
|
const auto res = make_shared<Response>(http::status::forbidden, request.version());
|
|
res->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
res->set(http::field::content_type, "text/plain");
|
|
res->set(http::field::access_control_allow_origin, "*");
|
|
res->keep_alive(request.keep_alive());
|
|
res->body() = "Access denied.";
|
|
res->prepare_payload();
|
|
return res;
|
|
}
|
|
|
|
std::shared_ptr<Response> makeServerError(const Request &request, std::string_view what)
|
|
{
|
|
const auto res = make_shared<Response>(http::status::internal_server_error, request.version());
|
|
res->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
res->set(http::field::content_type, "text/plain");
|
|
res->set(http::field::access_control_allow_origin, "*");
|
|
res->keep_alive(request.keep_alive());
|
|
res->body() = argsToString("An error occurred: '", what, "'");
|
|
res->prepare_payload();
|
|
return res;
|
|
}
|
|
|
|
std::shared_ptr<Response> makeData(const Request &request, const string &buffer, const char *mimeType)
|
|
{
|
|
const auto res = make_shared<Response>(http::status::ok, request.version());
|
|
res->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
res->set(http::field::content_type, mimeType);
|
|
res->set(http::field::access_control_allow_origin, "*");
|
|
res->keep_alive(request.keep_alive());
|
|
res->body() = buffer;
|
|
res->prepare_payload();
|
|
return res;
|
|
}
|
|
|
|
std::shared_ptr<Response> makeData(const Request &request, string &&buffer, const char *mimeType)
|
|
{
|
|
const auto res = make_shared<Response>(http::status::ok, request.version());
|
|
res->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
res->set(http::field::content_type, mimeType);
|
|
res->set(http::field::access_control_allow_origin, "*");
|
|
res->keep_alive(request.keep_alive());
|
|
res->body() = buffer;
|
|
res->prepare_payload();
|
|
return res;
|
|
}
|
|
|
|
std::shared_ptr<Response> makeData(const Request &request, rapidjson::StringBuffer &&buffer, const char *mimeType)
|
|
{
|
|
const auto res = make_shared<Response>(http::status::ok, request.version());
|
|
res->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
res->set(http::field::content_type, mimeType);
|
|
res->set(http::field::access_control_allow_origin, "*");
|
|
res->keep_alive(request.keep_alive());
|
|
res->body().assign(buffer.GetString(), buffer.GetSize());
|
|
res->prepare_payload();
|
|
return res;
|
|
}
|
|
|
|
std::shared_ptr<FileResponse> makeFile(const Request &request, const char *filePath, const char *mimeType, boost::beast::error_code &ec)
|
|
{
|
|
const auto fileResponse = std::make_shared<FileResponse>();
|
|
fileResponse->set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
fileResponse->set(http::field::content_type, mimeType);
|
|
fileResponse->set(http::field::access_control_allow_origin, "*");
|
|
fileResponse->keep_alive(request.keep_alive());
|
|
fileResponse->body().open(filePath, file_mode::scan, ec);
|
|
return fileResponse;
|
|
}
|
|
|
|
inline ChunkResponse::ChunkResponse()
|
|
: response(boost::beast::http::status::ok, 11)
|
|
, serializer(response)
|
|
{
|
|
response.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING);
|
|
response.set(boost::beast::http::field::access_control_allow_origin, "*");
|
|
response.chunked(true);
|
|
}
|
|
|
|
std::shared_ptr<ChunkResponse> makeChunkResponse(const Request &request, const char *mimeType)
|
|
{
|
|
const auto chunkResponse = std::make_shared<ChunkResponse>();
|
|
chunkResponse->response.set(boost::beast::http::field::content_type, mimeType);
|
|
chunkResponse->response.keep_alive(request.keep_alive());
|
|
return chunkResponse;
|
|
}
|
|
|
|
} // namespace Render
|
|
} // namespace WebAPI
|
|
} // namespace LibRepoMgr
|