Added KIWIX_RESPONSE_DATA to error response

Now the data used to generate an error response can be made to be
embedded in the response as a JS object KIWIX_RESPONSE_DATA.
This commit is contained in:
Veloman Yunkan 2024-01-09 21:59:53 +04:00
parent 8b8a2eede7
commit b151a2a480
4 changed files with 65 additions and 8 deletions

View File

@ -195,6 +195,9 @@ public:
}; };
} }
std::string asJSON() const;
void dumpJSON(std::ostream& os) const;
private: private:
bool isString() const { return std::holds_alternative<std::string>(data); } bool isString() const { return std::holds_alternative<std::string>(data); }
bool isList() const { return std::holds_alternative<List>(data); } bool isList() const { return std::holds_alternative<List>(data); }
@ -248,15 +251,51 @@ MustacheData ContentResponseBlueprint::Data::toMustache(const std::string& lang)
} }
} }
void ContentResponseBlueprint::Data::dumpJSON(std::ostream& os) const
{
if ( this->isString() ) {
os << '"' << escapeForJSON(this->stringValue()) << '"';
} else if ( this->isList() ) {
const char * sep = " ";
os << "[";
for ( const auto& x : this->listValue() ) {
os << sep;
x.dumpJSON(os);
sep = ", ";
}
os << " ]";
} else if ( this->isObject() ) {
const char * sep = " ";
os << "{";
for ( const auto& kv : this->objectValue() ) {
os << sep << '"' << kv.first << "\" : ";
kv.second.dumpJSON(os);
sep = ", ";
}
os << " }";
} else {
os << (this->boolValue() ? "true" : "false");
}
}
std::string ContentResponseBlueprint::Data::asJSON() const
{
std::ostringstream oss;
this->dumpJSON(oss);
return oss.str();
}
ContentResponseBlueprint::ContentResponseBlueprint(const RequestContext* request, ContentResponseBlueprint::ContentResponseBlueprint(const RequestContext* request,
int httpStatusCode, int httpStatusCode,
const std::string& mimeType, const std::string& mimeType,
const std::string& templateStr) const std::string& templateStr,
bool includeKiwixResponseData)
: m_request(*request) : m_request(*request)
, m_httpStatusCode(httpStatusCode) , m_httpStatusCode(httpStatusCode)
, m_mimeType(mimeType) , m_mimeType(mimeType)
, m_template(templateStr) , m_template(templateStr)
, m_includeKiwixResponseData(includeKiwixResponseData)
, m_data(new Data) , m_data(new Data)
{} {}
@ -265,6 +304,9 @@ ContentResponseBlueprint::~ContentResponseBlueprint() = default;
std::unique_ptr<ContentResponse> ContentResponseBlueprint::generateResponseObject() const std::unique_ptr<ContentResponse> ContentResponseBlueprint::generateResponseObject() const
{ {
kainjow::mustache::data d = m_data->toMustache(m_request.get_user_language()); kainjow::mustache::data d = m_data->toMustache(m_request.get_user_language());
if ( m_includeKiwixResponseData ) {
d.set("KIWIX_RESPONSE_DATA", m_data->asJSON());
}
auto r = ContentResponse::build(m_template, d, m_mimeType); auto r = ContentResponse::build(m_template, d, m_mimeType);
r->set_code(m_httpStatusCode); r->set_code(m_httpStatusCode);
return r; return r;
@ -274,11 +316,13 @@ HTTPErrorResponse::HTTPErrorResponse(const RequestContext& request,
int httpStatusCode, int httpStatusCode,
const std::string& pageTitleMsgId, const std::string& pageTitleMsgId,
const std::string& headingMsgId, const std::string& headingMsgId,
const std::string& cssUrl) const std::string& cssUrl,
bool includeKiwixResponseData)
: ContentResponseBlueprint(&request, : ContentResponseBlueprint(&request,
httpStatusCode, httpStatusCode,
request.get_requested_format() == "html" ? "text/html; charset=utf-8" : "application/xml; charset=utf-8", request.get_requested_format() == "html" ? "text/html; charset=utf-8" : "application/xml; charset=utf-8",
request.get_requested_format() == "html" ? RESOURCE::templates::error_html : RESOURCE::templates::error_xml) request.get_requested_format() == "html" ? RESOURCE::templates::error_html : RESOURCE::templates::error_xml,
includeKiwixResponseData)
{ {
Data::List emptyList; Data::List emptyList;
*this->m_data = Data(Data::Object{ *this->m_data = Data(Data::Object{

View File

@ -121,7 +121,8 @@ public: // functions
ContentResponseBlueprint(const RequestContext* request, ContentResponseBlueprint(const RequestContext* request,
int httpStatusCode, int httpStatusCode,
const std::string& mimeType, const std::string& mimeType,
const std::string& templateStr); const std::string& templateStr,
bool includeKiwixResponseData = false);
~ContentResponseBlueprint(); ~ContentResponseBlueprint();
@ -140,6 +141,7 @@ protected: //data
const int m_httpStatusCode; const int m_httpStatusCode;
const std::string m_mimeType; const std::string m_mimeType;
const std::string m_template; const std::string m_template;
const bool m_includeKiwixResponseData;
std::unique_ptr<Data> m_data; std::unique_ptr<Data> m_data;
}; };
@ -149,7 +151,8 @@ struct HTTPErrorResponse : ContentResponseBlueprint
int httpStatusCode, int httpStatusCode,
const std::string& pageTitleMsgId, const std::string& pageTitleMsgId,
const std::string& headingMsgId, const std::string& headingMsgId,
const std::string& cssUrl = ""); const std::string& cssUrl = "",
bool includeKiwixResponseData = false);
HTTPErrorResponse& operator+(const ParameterizedMessage& errorDetails); HTTPErrorResponse& operator+(const ParameterizedMessage& errorDetails);
HTTPErrorResponse& operator+=(const ParameterizedMessage& errorDetails); HTTPErrorResponse& operator+=(const ParameterizedMessage& errorDetails);

View File

@ -5,7 +5,9 @@
<title>{{PAGE_TITLE}}</title> <title>{{PAGE_TITLE}}</title>
{{#CSS_URL}} {{#CSS_URL}}
<link type="text/css" href="{{{CSS_URL}}}" rel="Stylesheet" /> <link type="text/css" href="{{{CSS_URL}}}" rel="Stylesheet" />
{{/CSS_URL}} {{/CSS_URL}}{{#KIWIX_RESPONSE_DATA}} <script>
const KIWIX_RESPONSE_DATA = {{{KIWIX_RESPONSE_DATA}}};
</script>{{/KIWIX_RESPONSE_DATA}}
</head> </head>
<body> <body>
<h1>{{PAGE_HEADING}}</h1> <h1>{{PAGE_HEADING}}</h1>

View File

@ -29,7 +29,8 @@ TEST(HTTPErrorResponse, shouldBeInEnglishByDefault) {
HTTPErrorResponse errResp(req, MHD_HTTP_NOT_FOUND, HTTPErrorResponse errResp(req, MHD_HTTP_NOT_FOUND,
"404-page-title", "404-page-title",
"404-page-heading", "404-page-heading",
"/css/error.css"); "/css/error.css",
/*includeKiwixResponseData=*/true);
EXPECT_EQ(getResponseContent(errResp), EXPECT_EQ(getResponseContent(errResp),
R"(<!DOCTYPE html> R"(<!DOCTYPE html>
@ -38,6 +39,9 @@ R"(<!DOCTYPE html>
<meta content="text/html;charset=UTF-8" http-equiv="content-type" /> <meta content="text/html;charset=UTF-8" http-equiv="content-type" />
<title>Content not found</title> <title>Content not found</title>
<link type="text/css" href="/css/error.css" rel="Stylesheet" /> <link type="text/css" href="/css/error.css" rel="Stylesheet" />
<script>
const KIWIX_RESPONSE_DATA = { "CSS_URL" : "/css/error.css", "PAGE_HEADING" : { "msgid" : "404-page-heading", "params" : { } }, "PAGE_TITLE" : { "msgid" : "404-page-title", "params" : { } }, "details" : [ ] };
</script>
</head> </head>
<body> <body>
<h1>Not Found</h1> <h1>Not Found</h1>
@ -56,7 +60,8 @@ TEST(HTTPErrorResponse, shouldBeTranslatable) {
HTTPErrorResponse errResp(req, MHD_HTTP_NOT_FOUND, HTTPErrorResponse errResp(req, MHD_HTTP_NOT_FOUND,
"404-page-title", "404-page-title",
"404-page-heading", "404-page-heading",
"/css/error.css"); "/css/error.css",
/*includeKiwixResponseData=*/true);
EXPECT_EQ(getResponseContent(errResp), EXPECT_EQ(getResponseContent(errResp),
R"(<!DOCTYPE html> R"(<!DOCTYPE html>
@ -65,6 +70,9 @@ R"(<!DOCTYPE html>
<meta content="text/html;charset=UTF-8" http-equiv="content-type" /> <meta content="text/html;charset=UTF-8" http-equiv="content-type" />
<title>[I18N TESTING] Not Found - Try Again</title> <title>[I18N TESTING] Not Found - Try Again</title>
<link type="text/css" href="/css/error.css" rel="Stylesheet" /> <link type="text/css" href="/css/error.css" rel="Stylesheet" />
<script>
const KIWIX_RESPONSE_DATA = { "CSS_URL" : "/css/error.css", "PAGE_HEADING" : { "msgid" : "404-page-heading", "params" : { } }, "PAGE_TITLE" : { "msgid" : "404-page-title", "params" : { } }, "details" : [ ] };
</script>
</head> </head>
<body> <body>
<h1>[I18N TESTING] Content not found, but at least the server is alive</h1> <h1>[I18N TESTING] Content not found, but at least the server is alive</h1>