forked from me-no-dev/ESPAsyncWebServer
HTTP 302 and 304 Support
Add support for http redirection (302) and http not modified (304) to reduce the load the server. server.redirect(“url”, “location”, exclude-ip) will respond with 302 to redirect the browser to a different url, this is useful for backward compatibility and to redirect call to CDN when not no AP mode. server.serveStatic has a new optional parameter to get the Last-Modified date for all files serve for this location, when the browser request have the same If-Modified-Since header value, the server respond with 304 code instead of serving the file.
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
.idea/
|
32
README.md
32
README.md
@@ -416,6 +416,38 @@ server.addHandler( new FileFallbackHandler(_fs, "/jquery/jq1.11.1.js" , "/jquery
|
||||
server.addHandler( new FileFallbackHandler(_fs, "/jquery/jqm1.4.5.js" , "/jquery/jqm1.4.5.js" , "http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js", "max-age=86400"));
|
||||
```
|
||||
|
||||
### Serving static files from SPIFFS
|
||||
Serve a specific file or attach a folder in SPIFFS to a root url.
|
||||
An optional Cache-Control header can be added to responses.
|
||||
An optional Last-Modified header can be added, if the request contains If-Modified-Since header with the same value the server will respond with 304 code instead of serving the file.
|
||||
```cpp
|
||||
|
||||
// Serve static file example
|
||||
server.serveStatic("/url/file.htm", SPIFFS, "/dir/file.htm");
|
||||
// Serve static folder example
|
||||
server.serveStatic("/root-url", SPIFFS, "/root-dir");
|
||||
// Specify cache control
|
||||
server.serveStatic("/root-url", SPIFFS, "/root-dir", "max-age=86400");
|
||||
// Specify last modified (should be updated each time files are updated)
|
||||
server.serveStatic("/root-url", SPIFFS, "/root-dir", NULL, "Wed, 08 Jun 2016 22:00:00 GMT");
|
||||
|
||||
```
|
||||
|
||||
### HTTP Redirect (302)
|
||||
Return HTTP 302 response to redirect the client to a different location.
|
||||
An optional IPAddress can specify redirection exclusions, for example, exclude redirection to requests to the AP address.
|
||||
```cpp
|
||||
// Redirect all requests
|
||||
server.redirect("/root/file.ext", "/other-location/other-file.ext");
|
||||
// Redirect requests not for the AP address
|
||||
server.redirect("/root/file.ext", "/other-location/other-file.ext", WiFi.softAPIP());
|
||||
|
||||
// Redirect to jquery CDN except when call is done to AP address
|
||||
server.redirect("/jquery/jq1.12.3.js", "http://code.jquery.com/jquery-1.12.3.min.js", WiFi.softAPIP());
|
||||
// Serve the jquery from SPIFFS
|
||||
server.serveStatic("/jquery", SPIFFS, "/jquery");
|
||||
|
||||
```
|
||||
|
||||
## Bad Responses
|
||||
Some responses are implemented, but you should not use them, because they do not conform to HTTP.
|
||||
|
@@ -297,7 +297,9 @@ class AsyncWebServer {
|
||||
void on(const char* uri, WebRequestMethod method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload);
|
||||
void on(const char* uri, WebRequestMethod method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody);
|
||||
|
||||
void serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header = NULL);
|
||||
void redirect(const char* url, const char* location, const uint32_t exclude_ip = 0);
|
||||
|
||||
void serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header = NULL, const char* modified_header = NULL);
|
||||
|
||||
void onNotFound(ArRequestHandlerFunction fn); //called when handler is not assigned
|
||||
void onFileUpload(ArUploadHandlerFunction fn); //handle file uploads
|
||||
|
@@ -24,6 +24,18 @@
|
||||
|
||||
#include "stddef.h"
|
||||
|
||||
class RedirectWebHandler: public AsyncWebHandler {
|
||||
protected:
|
||||
String _url;
|
||||
String _location;
|
||||
uint32_t _exclude_ip;
|
||||
public:
|
||||
RedirectWebHandler(const char* url, const char* location, uint32_t exclude_ip)
|
||||
: _url(url), _location(location) { _exclude_ip = exclude_ip; }
|
||||
bool canHandle(AsyncWebServerRequest *request);
|
||||
void handleRequest(AsyncWebServerRequest *request);
|
||||
};
|
||||
|
||||
class AsyncStaticWebHandler: public AsyncWebHandler {
|
||||
private:
|
||||
String _getPath(AsyncWebServerRequest *request);
|
||||
@@ -32,10 +44,11 @@ class AsyncStaticWebHandler: public AsyncWebHandler {
|
||||
String _uri;
|
||||
String _path;
|
||||
String _cache_header;
|
||||
String _modified_header;
|
||||
bool _isFile;
|
||||
public:
|
||||
AsyncStaticWebHandler(FS& fs, const char* path, const char* uri, const char* cache_header)
|
||||
: _fs(fs), _uri(uri), _path(path), _cache_header(cache_header){
|
||||
AsyncStaticWebHandler(FS& fs, const char* path, const char* uri, const char* cache_header, const char* modified_header)
|
||||
: _fs(fs), _uri(uri), _path(path), _cache_header(cache_header), _modified_header(modified_header) {
|
||||
|
||||
_isFile = _fs.exists(path) || _fs.exists((String(path)+".gz").c_str());
|
||||
if (_uri != "/" && _uri.endsWith("/")) {
|
||||
|
@@ -21,6 +21,25 @@
|
||||
#include "ESPAsyncWebServer.h"
|
||||
#include "WebHandlerImpl.h"
|
||||
|
||||
|
||||
bool RedirectWebHandler::canHandle(AsyncWebServerRequest *request)
|
||||
{
|
||||
// We can redirect when the request url match and ip doesn't match
|
||||
if (request->url() == _url && _exclude_ip != request->client()->localIP()) {
|
||||
DEBUGF("[RedirectWebHandler::canHandle] TRUE\n");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RedirectWebHandler::handleRequest(AsyncWebServerRequest *request)
|
||||
{
|
||||
AsyncWebServerResponse *response = request->beginResponse(302);
|
||||
response->addHeader("Location", _location);
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request)
|
||||
{
|
||||
if (request->method() != HTTP_GET) {
|
||||
@@ -33,7 +52,10 @@ bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request)
|
||||
if (request->url().startsWith(_uri)) {
|
||||
String path = _getPath(request);
|
||||
if (_fs.exists(path) || _fs.exists(path + ".gz")) {
|
||||
DEBUGF("[AsyncStaticWebHandler::canHandle] TRUE\n");
|
||||
if (_modified_header.length() != 0) {
|
||||
request->addInterestingHeader("If-Modified-Since");
|
||||
}
|
||||
DEBUGF("[AsyncStaticWebHandler::canHandle] TRUE\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -82,14 +104,19 @@ void AsyncStaticWebHandler::handleRequest(AsyncWebServerRequest *request)
|
||||
String path = _getPath(request);
|
||||
|
||||
if (_fs.exists(path) || _fs.exists(path + ".gz")) {
|
||||
AsyncWebServerResponse * response = request->beginResponse(_fs, path);
|
||||
if (_cache_header.length() != 0)
|
||||
response->addHeader("Cache-Control", _cache_header);
|
||||
request->send(response);
|
||||
if (_modified_header.length() != 0 && _modified_header == request->header("If-Modified-Since")) {
|
||||
request->send(304); // Sed not modified
|
||||
} else {
|
||||
AsyncWebServerResponse * response = request->beginResponse(_fs, path);
|
||||
if (_modified_header.length() !=0)
|
||||
response->addHeader("Last-Modified", _modified_header);
|
||||
if (_cache_header.length() != 0)
|
||||
response->addHeader("Cache-Control", _cache_header);
|
||||
request->send(response);
|
||||
}
|
||||
} else {
|
||||
request->send(404);
|
||||
}
|
||||
path = String();
|
||||
|
||||
|
||||
}
|
||||
|
@@ -104,8 +104,12 @@ void AsyncWebServer::on(const char* uri, ArRequestHandlerFunction onRequest){
|
||||
addHandler(handler);
|
||||
}
|
||||
|
||||
void AsyncWebServer::serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header){
|
||||
addHandler(new AsyncStaticWebHandler(fs, path, uri, cache_header));
|
||||
void AsyncWebServer::redirect(const char* url, const char* location, const uint32_t exclude_ip){
|
||||
addHandler(new RedirectWebHandler(url, location, exclude_ip));
|
||||
}
|
||||
|
||||
void AsyncWebServer::serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header, const char* modified_header){
|
||||
addHandler(new AsyncStaticWebHandler(fs, path, uri, cache_header, modified_header));
|
||||
}
|
||||
|
||||
void AsyncWebServer::onNotFound(ArRequestHandlerFunction fn){
|
||||
|
Reference in New Issue
Block a user