Skip to content

Commit

Permalink
Add some more response headers
Browse files Browse the repository at this point in the history
Changes:
 * Add Vary header to compressed resources
 * Add Vary header to prometheus metrics
 * Add Cache-Control header to /temperature and /humidity
 * Add Content-Security-Policy to html files
 * Fix Error pages sending a NUL byte at the end
  • Loading branch information
ToMe25 committed Feb 7, 2024
1 parent e830b49 commit 771a05e
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/prometheus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ web::ResponseData prom::handleMetrics(AsyncWebServerRequest *request) {
"text/plain; version=0.0.4; charset=utf-8"),
metrics);
response->addHeader("Cache-Control", "no-cache");
response->addHeader("Vary", "Accept");
return web::ResponseData(response, metrics.length(), 200);
}
#endif
Expand Down
46 changes: 30 additions & 16 deletions src/webhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,20 @@ void web::setup() {
[](AsyncWebServerRequest *request) -> ResponseData {
const std::string temp =
sensors::SENSOR_HANDLER.getTemperatureString();
return ResponseData(
request->beginResponse(200, "text/plain", temp.c_str()),
temp.length(), 200);
AsyncWebServerResponse *response = request->beginResponse(200,
"text/plain", temp.c_str());
response->addHeader("Cache-Control", "no-cache");
return ResponseData(response, temp.length(), 200);
});

registerRequestHandler("/humidity", HTTP_GET,
[](AsyncWebServerRequest *request) -> ResponseData {
const std::string humidity =
sensors::SENSOR_HANDLER.getHumidityString();
return ResponseData(
request->beginResponse(200, "text/plain",
humidity.c_str()), humidity.length(), 200);
AsyncWebServerResponse *response = request->beginResponse(200,
"text/plain", humidity.c_str());
response->addHeader("Cache-Control", "no-cache");
return ResponseData(response, humidity.length(), 200);
});

registerRequestHandler("/data.json", HTTP_GET, getJson);
Expand Down Expand Up @@ -234,12 +236,12 @@ void web::notFoundHandler(AsyncWebServerRequest *request) {
const size_t start = micros();
const std::map<String, String> replacements { { "TITLE",
"Error 404 Not Found" }, { "ERROR",
"The requested file can not be found on this server!" },
{ "DETAILS", "The page <code>" + request->url()
"The requested file can not be found on this server!" }, {
"DETAILS", "The page <code>" + request->url()
+ "</code> couldn't be found." } };
ResponseData response = replacingRequestHandler(replacements, 404,
"text/html", (uint8_t*) ERROR_HTML_START, (uint8_t*) ERROR_HTML_END,
request);
"text/html", (uint8_t*) ERROR_HTML_START,
(uint8_t*) ERROR_HTML_END - 1, request);
if (request->method() == HTTP_HEAD) {
response.response = new AsyncHeadOnlyResponse(response.response,
response.status_code);
Expand Down Expand Up @@ -306,7 +308,7 @@ web::ResponseData web::invalidMethodHandler(

ResponseData response = replacingRequestHandler(replacements, 405,
"text/html", (uint8_t*) ERROR_HTML_START,
(uint8_t*) ERROR_HTML_END, request);
(uint8_t*) ERROR_HTML_END - 1, request);
if (request->method() == HTTP_HEAD) {
response.response = new AsyncHeadOnlyResponse(response.response,
405);
Expand Down Expand Up @@ -356,9 +358,12 @@ web::ResponseData web::optionsHandler(
web::ResponseData web::staticHandler(const uint16_t status_code,
const String &content_type, const uint8_t *start, const uint8_t *end,
AsyncWebServerRequest *request) {
return ResponseData(
request->beginResponse_P(status_code, content_type, start,
end - start), end - start, status_code);
AsyncWebServerResponse *response = request->beginResponse_P(status_code,
content_type, start, end - start);
if (!strcmp(content_type.c_str(), "text/html")) {
response->addHeader("Content-Security-Policy", "default-src 'self'");
}
return ResponseData(response, end - start, status_code);
}

web::ResponseData web::compressedStaticHandler(const uint16_t status_code,
Expand All @@ -367,8 +372,7 @@ web::ResponseData web::compressedStaticHandler(const uint16_t status_code,
AsyncWebServerResponse *response = NULL;
size_t content_length;
if (request->hasHeader("Accept-Encoding")
&& strstr(request->getHeader("Accept-Encoding")->value().c_str(),
"gzip")) {
&& strstr(request->header("Accept-Encoding").c_str(), "gzip")) {
content_length = end - start;
response = request->beginResponse_P(200, content_type, start,
end - start);
Expand All @@ -382,7 +386,14 @@ web::ResponseData web::compressedStaticHandler(const uint16_t status_code,
response = request->beginResponse(content_type, content_length,
std::bind(decompressingResponseFiller, decomp, _1, _2, _3));
}

response->addHeader("Vary", "Accept-Encoding");
response->setCode(status_code);

if (!strcmp(content_type.c_str(), "text/html")) {
response->addHeader("Content-Security-Policy", "default-src 'self'");
}

return ResponseData(response, content_length, status_code);
}

Expand Down Expand Up @@ -433,6 +444,9 @@ web::ResponseData web::replacingRequestHandler(
std::bind(replacingResponseFiller, replacements, offset, start, end,
_1, _2, _3));
response->setCode(status_code);
if (!strcmp(content_type.c_str(), "text/html")) {
response->addHeader("Content-Security-Policy", "default-src 'self'");
}
return ResponseData(response, content_length, status_code);
}

Expand Down
17 changes: 15 additions & 2 deletions src/webhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ size_t decompressingResponseFiller(
* Will automatically be updated by this function.
* @param start A pointer to the first byte of the static page.
* @param end A pointer to the first byte after the static page.
* For C strings this is the terminating NUL byte.
* @param buffer The output buffer to write to.
* @param max_len The max number of bytes to write to the output buffer.
* @param index The number of bytes already created by this method.
Expand Down Expand Up @@ -213,10 +214,13 @@ ResponseData optionsHandler(const WebRequestMethodComposite validMethods,
/**
* A web request handler for a static page.
*
* Automatically adds a "default-src 'self'" content security policy to "text/html" responses.
*
* @param status_code The HTTP response status code to send to the client.
* @param content_type The content type of the static file.
* @param start A pointer to the first byte of the compressed static file.
* @param end A pointer to the first byte after the end of the compressed static file.
* For C strings this is the terminating NUL byte.
* @param request The request to handle.
* @return The response to be sent to the client.
*/
Expand All @@ -226,13 +230,17 @@ ResponseData staticHandler(const uint16_t status_code,

/**
* A web request handler for a compressed static file.
*
* If the client accepts gzip compressed files, the file is sent as is.
* Otherwise it is decompressed on the fly.
*
* Automatically adds a "default-src 'self'" content security policy to "text/html" responses.
*
* @param status_code The HTTP response status code to send to the client.
* @param content_type The content type of the static file.
* @param start A pointer to the first byte of the compressed static file.
* @param end A pointer to the first byte after the end of the compressed static file.
* For C strings this is the terminating NUL byte.
* @param request The request to handle.
* @return The response to be sent to the client.
*/
Expand All @@ -247,12 +255,15 @@ ResponseData compressedStaticHandler(const uint16_t status_code,
* The templates will be replaced with the result of the function registered for them.
* Note that each function will be called once, no matter how often its template appears.
*
* Automatically adds a "default-src 'self'" content security policy to "text/html" responses.
*
* @param replacements A map mapping a template string to be replaced,
* to a function returning its replacement value.
* @param status_code The HTTP response status code to send to the client.
* @param content_type The content type of the file to send.
* @param start A pointer to the first byte of the static file.
* @param end A pointer to the first byte after the static file.
* For C strings this is the terminating NUL byte.
* @param request The request to handle.
* @return The response to be sent to the client.
*/
Expand All @@ -272,6 +283,7 @@ ResponseData replacingRequestHandler(
* @param content_type The content type of the file to send.
* @param start A pointer to the first byte of the static file.
* @param end A pointer to the first byte after the static file.
* For C strings this is the terminating NUL byte.
* @param request The request to handle.
* @return The response to be sent to the client.
*/
Expand Down Expand Up @@ -327,8 +339,9 @@ void registerStaticHandler(const char *uri, const String &content_type,
*
* @param uri The path on which the file can be found.
* @param content_type The content type for the file.
* @param start The pointer for the start of the file.
* @param end The pointer for the end of the file.
* @param start The pointer to the first byte of the file.
* @param end The pointer to the first byte after the end of the file.
* For C strings this is the terminating NUL byte.
*/
void registerCompressedStaticHandler(const char *uri,
const String &content_type, const uint8_t *start, const uint8_t *end);
Expand Down

0 comments on commit 771a05e

Please sign in to comment.