Close #77: Allow modification of hardcoded headers

This commit is contained in:
Mathieu CArbou
2024-08-31 21:39:27 +00:00
committed by Mathieu Carbou
parent 504231c96f
commit f0402e5a6e
4 changed files with 61 additions and 14 deletions

View File

@@ -61,6 +61,27 @@ void setup() {
request->send(LittleFS, "/index.html");
});
/*
curl -I -X HEAD http://192.168.4.1/download
HTTP/1.1 200 OK
Content-Length: 1024
Content-Type: application/octet-stream
Connection: close
Accept-Ranges: bytes
*/
// Ref: https://github.com/mathieucarbou/ESPAsyncWebServer/pull/80
server.on("/download", HTTP_HEAD | HTTP_GET, [](AsyncWebServerRequest* request) {
if (request->method() == HTTP_HEAD) {
AsyncWebServerResponse* response = request->beginResponse(200, "application/octet-stream");
response->setContentLength(1024); // myFile.getSize()
response->addHeader("Accept-Ranges", "bytes");
// ...
request->send(response);
} else {
// ...
}
});
// Send a GET request to <IP>/get?message=<message>
server.on("/get", HTTP_GET, [](AsyncWebServerRequest* request) {
String message;

View File

@@ -581,8 +581,9 @@ class AsyncWebServerResponse {
virtual void setContentLength(size_t len);
void setContentType(const String& type) { setContentType(type.c_str()); }
virtual void setContentType(const char* type);
virtual void addHeader(const char* name, const char* value);
void addHeader(const String& name, const String& value) { addHeader(name.c_str(), value.c_str()); }
virtual bool addHeader(const char* name, const char* value, bool replaceExisting = true);
bool addHeader(const String& name, const String& value, bool replaceExisting = true) { return addHeader(name.c_str(), value.c_str(), replaceExisting); }
virtual bool removeHeader(const char* name);
virtual String _assembleHead(uint8_t version);
virtual bool _started() const;
virtual bool _finished() const;

View File

@@ -239,18 +239,43 @@ void AsyncWebServerResponse::setContentType(const char* type) {
_contentType = type;
}
void AsyncWebServerResponse::addHeader(const char* name, const char* value) {
bool AsyncWebServerResponse::removeHeader(const char* name) {
for (auto i = _headers.begin(); i != _headers.end(); ++i) {
if (i->name().equalsIgnoreCase(name)) {
_headers.erase(i);
return true;
}
}
return false;
}
bool AsyncWebServerResponse::addHeader(const char* name, const char* value, bool replaceExisting) {
for (auto i = _headers.begin(); i != _headers.end(); ++i) {
if (i->name().equalsIgnoreCase(name)) {
// header already set
if (replaceExisting) {
// remove, break and add the new one
_headers.erase(i);
break;
} else {
// do not update
return false;
}
}
}
// header was not found found, or existing one was removed
_headers.emplace_back(name, value);
return true;
}
String AsyncWebServerResponse::_assembleHead(uint8_t version) {
if (version) {
addHeader(T_Accept_Ranges, T_none);
addHeader(T_Accept_Ranges, T_none, false);
if (_chunked)
addHeader(Transfer_Encoding, T_chunked);
addHeader(T_Transfer_Encoding, T_chunked, false);
}
String out;
int bufSize = 300;
constexpr size_t bufSize = 300;
char buf[bufSize];
#ifndef ESP8266
@@ -307,7 +332,7 @@ AsyncBasicResponse::AsyncBasicResponse(int code, const char* contentType, const
if (!_contentType.length())
_contentType = T_text_plain;
}
addHeader(T_Connection, T_close);
addHeader(T_Connection, T_close, false);
}
void AsyncBasicResponse::_respond(AsyncWebServerRequest* request) {
@@ -385,7 +410,7 @@ AsyncAbstractResponse::AsyncAbstractResponse(AwsTemplateProcessor callback) : _c
}
void AsyncAbstractResponse::_respond(AsyncWebServerRequest* request) {
addHeader(T_Connection, T_close);
addHeader(T_Connection, T_close, false);
_head = _assembleHead(request->version());
_state = RESPONSE_HEADERS;
_ack(request, 0, 0);
@@ -663,7 +688,7 @@ AsyncFileResponse::AsyncFileResponse(FS& fs, const String& path, const char* con
if (!download && !fs.exists(_path) && fs.exists(_path + T__gz)) {
_path = _path + T__gz;
addHeader(T_Content_Encoding, T_gzip);
addHeader(T_Content_Encoding, T_gzip, false);
_callback = nullptr; // Unable to process zipped templates
_sendContentLength = true;
_chunked = false;
@@ -688,7 +713,7 @@ AsyncFileResponse::AsyncFileResponse(FS& fs, const String& path, const char* con
// set filename and force rendering
snprintf_P(buf, sizeof(buf), PSTR("inline"));
}
addHeader(T_Content_Disposition, buf);
addHeader(T_Content_Disposition, buf, false);
}
AsyncFileResponse::AsyncFileResponse(File content, const String& path, const char* contentType, bool download, AwsTemplateProcessor callback) : AsyncAbstractResponse(callback) {
@@ -696,7 +721,7 @@ AsyncFileResponse::AsyncFileResponse(File content, const String& path, const cha
_path = path;
if (!download && String(content.name()).endsWith(T__gz) && !path.endsWith(T__gz)) {
addHeader(T_Content_Encoding, T_gzip);
addHeader(T_Content_Encoding, T_gzip, false);
_callback = nullptr; // Unable to process gzipped templates
_sendContentLength = true;
_chunked = false;
@@ -719,7 +744,7 @@ AsyncFileResponse::AsyncFileResponse(File content, const String& path, const cha
} else {
snprintf_P(buf, sizeof(buf), PSTR("inline"));
}
addHeader(T_Content_Disposition, buf);
addHeader(T_Content_Disposition, buf, false);
}
size_t AsyncFileResponse::_fillBuffer(uint8_t* data, size_t len) {

View File

@@ -41,7 +41,7 @@ static constexpr const char* T_none = "none";
static constexpr const char* T_UPGRADE = "Upgrade";
static constexpr const char* T_WS = "websocket";
static constexpr const char* T_WWW_AUTH = "WWW-Authenticate";
static constexpr const char* Transfer_Encoding = "Transfer-Encoding";
static constexpr const char* T_Transfer_Encoding = "Transfer-Encoding";
// HTTP Methods
static constexpr const char* T_ANY = "ANY";
@@ -210,7 +210,7 @@ static const char T_none[] PROGMEM = "none";
static const char T_UPGRADE[] PROGMEM = "Upgrade";
static const char T_WS[] PROGMEM = "websocket";
static const char T_WWW_AUTH[] PROGMEM = "WWW-Authenticate";
static const char Transfer_Encoding[] PROGMEM = "Transfer-Encoding";
static const char T_Transfer_Encoding[] PROGMEM = "Transfer-Encoding";
// HTTP Methods
static const char T_ANY[] PROGMEM = "ANY";