mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-25 20:02:37 +03:00
add begin(port) to esp8266webserver, move some strings to flash, some refactoring (#4148)
* add begin(port) to esp8266webserver, move some strings to flash, some refactoring * Moved more strings to flash, unified some strings * move mimetable strings into a standalone file * more string moves to flash, remove duplicates, refactor of template method, minor styling * Reverted moving small string to flash (no heap advantage, reduces bin size)
This commit is contained in:
parent
0339bbb11c
commit
bcbd5961c0
@ -36,7 +36,13 @@
|
||||
#define DEBUG_OUTPUT Serial
|
||||
#endif
|
||||
|
||||
const char * AUTHORIZATION_HEADER = "Authorization";
|
||||
//const char * AUTHORIZATION_HEADER = "Authorization";
|
||||
static const char AUTHORIZATION_HEADER[] PROGMEM = "Authorization";
|
||||
static const char qop_auth[] PROGMEM = "qop=auth";
|
||||
static const char WWW_Authenticate[] PROGMEM = "WWW-Authenticate";
|
||||
static const char colon[] PROGMEM = ":";
|
||||
static const char Content_Length[] PROGMEM = "Content-Length";
|
||||
|
||||
|
||||
ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
|
||||
: _server(addr, port)
|
||||
@ -44,13 +50,13 @@ ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
|
||||
, _currentVersion(0)
|
||||
, _currentStatus(HC_NONE)
|
||||
, _statusChange(0)
|
||||
, _currentHandler(0)
|
||||
, _firstHandler(0)
|
||||
, _lastHandler(0)
|
||||
, _currentHandler(nullptr)
|
||||
, _firstHandler(nullptr)
|
||||
, _lastHandler(nullptr)
|
||||
, _currentArgCount(0)
|
||||
, _currentArgs(0)
|
||||
, _currentArgs(nullptr)
|
||||
, _headerKeysCount(0)
|
||||
, _currentHeaders(0)
|
||||
, _currentHeaders(nullptr)
|
||||
, _contentLength(0)
|
||||
, _chunked(false)
|
||||
{
|
||||
@ -62,13 +68,13 @@ ESP8266WebServer::ESP8266WebServer(int port)
|
||||
, _currentVersion(0)
|
||||
, _currentStatus(HC_NONE)
|
||||
, _statusChange(0)
|
||||
, _currentHandler(0)
|
||||
, _firstHandler(0)
|
||||
, _lastHandler(0)
|
||||
, _currentHandler(nullptr)
|
||||
, _firstHandler(nullptr)
|
||||
, _lastHandler(nullptr)
|
||||
, _currentArgCount(0)
|
||||
, _currentArgs(0)
|
||||
, _currentArgs(nullptr)
|
||||
, _headerKeysCount(0)
|
||||
, _currentHeaders(0)
|
||||
, _currentHeaders(nullptr)
|
||||
, _contentLength(0)
|
||||
, _chunked(false)
|
||||
{
|
||||
@ -88,79 +94,83 @@ ESP8266WebServer::~ESP8266WebServer() {
|
||||
}
|
||||
|
||||
void ESP8266WebServer::begin() {
|
||||
_currentStatus = HC_NONE;
|
||||
close();
|
||||
_server.begin();
|
||||
if(!_headerKeysCount)
|
||||
collectHeaders(0, 0);
|
||||
}
|
||||
|
||||
String ESP8266WebServer::_exractParam(String& authReq,const String& param,const char delimit){
|
||||
void ESP8266WebServer::begin(uint16_t port) {
|
||||
close();
|
||||
_server.begin(port);
|
||||
}
|
||||
|
||||
String ESP8266WebServer::_extractParam(String& authReq,const String& param,const char delimit){
|
||||
int _begin = authReq.indexOf(param);
|
||||
if (_begin==-1) return "";
|
||||
if (_begin==-1)
|
||||
return "";
|
||||
return authReq.substring(_begin+param.length(),authReq.indexOf(delimit,_begin+param.length()));
|
||||
}
|
||||
|
||||
bool ESP8266WebServer::authenticate(const char * username, const char * password){
|
||||
if(hasHeader(AUTHORIZATION_HEADER)){
|
||||
String authReq = header(AUTHORIZATION_HEADER);
|
||||
if(authReq.startsWith("Basic")){
|
||||
if(hasHeader(FPSTR(AUTHORIZATION_HEADER))) {
|
||||
String authReq = header(FPSTR(AUTHORIZATION_HEADER));
|
||||
if(authReq.startsWith(F("Basic"))){
|
||||
authReq = authReq.substring(6);
|
||||
authReq.trim();
|
||||
char toencodeLen = strlen(username)+strlen(password)+1;
|
||||
char *toencode = new char[toencodeLen + 1];
|
||||
if(toencode == NULL){
|
||||
authReq = String();
|
||||
authReq = "";
|
||||
return false;
|
||||
}
|
||||
char *encoded = new char[base64_encode_expected_len(toencodeLen)+1];
|
||||
if(encoded == NULL){
|
||||
authReq = String();
|
||||
authReq = "";
|
||||
delete[] toencode;
|
||||
return false;
|
||||
}
|
||||
sprintf(toencode, "%s:%s", username, password);
|
||||
if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq.equalsConstantTime(encoded)) {
|
||||
authReq = String();
|
||||
authReq = "";
|
||||
delete[] toencode;
|
||||
delete[] encoded;
|
||||
return true;
|
||||
}
|
||||
delete[] toencode;
|
||||
delete[] encoded;
|
||||
}else if(authReq.startsWith("Digest")){
|
||||
} else if(authReq.startsWith(F("Digest"))) {
|
||||
authReq = authReq.substring(7);
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println(authReq);
|
||||
#endif
|
||||
String _username = _exractParam(authReq,"username=\"");
|
||||
if((!_username.length())||_username!=String(username)){
|
||||
authReq = String();
|
||||
String _username = _extractParam(authReq,F("username=\""));
|
||||
if(!_username.length() || _username != String(username)) {
|
||||
authReq = "";
|
||||
return false;
|
||||
}
|
||||
// extracting required parameters for RFC 2069 simpler Digest
|
||||
String _realm = _exractParam(authReq,"realm=\"");
|
||||
String _nonce = _exractParam(authReq,"nonce=\"");
|
||||
String _uri = _exractParam(authReq,"uri=\"");
|
||||
String _response = _exractParam(authReq,"response=\"");
|
||||
String _opaque = _exractParam(authReq,"opaque=\"");
|
||||
String _realm = _extractParam(authReq, F("realm=\""));
|
||||
String _nonce = _extractParam(authReq, F("nonce=\""));
|
||||
String _uri = _extractParam(authReq, F("uri=\""));
|
||||
String _response = _extractParam(authReq, F("response=\""));
|
||||
String _opaque = _extractParam(authReq, F("opaque=\""));
|
||||
|
||||
if((!_realm.length())||(!_nonce.length())||(!_uri.length())||(!_response.length())||(!_opaque.length())){
|
||||
authReq = String();
|
||||
if((!_realm.length()) || (!_nonce.length()) || (!_uri.length()) || (!_response.length()) || (!_opaque.length())) {
|
||||
authReq = "";
|
||||
return false;
|
||||
}
|
||||
if((_opaque!=_sopaque)||(_nonce!=_snonce)||(_realm!=_srealm)){
|
||||
authReq = String();
|
||||
if((_opaque != _sopaque) || (_nonce != _snonce) || (_realm != _srealm)) {
|
||||
authReq = "";
|
||||
return false;
|
||||
}
|
||||
// parameters for the RFC 2617 newer Digest
|
||||
String _nc,_cnonce;
|
||||
if(authReq.indexOf("qop=auth") != -1){
|
||||
_nc = _exractParam(authReq,"nc=",',');
|
||||
_cnonce = _exractParam(authReq,"cnonce=\"");
|
||||
if(authReq.indexOf(FPSTR(qop_auth)) != -1) {
|
||||
_nc = _extractParam(authReq, F("nc="), ',');
|
||||
_cnonce = _extractParam(authReq, F("cnonce=\""));
|
||||
}
|
||||
MD5Builder md5;
|
||||
md5.begin();
|
||||
md5.add(String(username)+":"+_realm+":"+String(password)); // md5 of the user:realm:user
|
||||
md5.add(String(username) + ':' + _realm + ':' + String(password)); // md5 of the user:realm:user
|
||||
md5.calculate();
|
||||
String _H1 = md5.toString();
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
@ -168,15 +178,15 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password
|
||||
#endif
|
||||
md5.begin();
|
||||
if(_currentMethod == HTTP_GET){
|
||||
md5.add("GET:"+_uri);
|
||||
md5.add(String(F("GET:")) + _uri);
|
||||
}else if(_currentMethod == HTTP_POST){
|
||||
md5.add("POST:"+_uri);
|
||||
md5.add(String(F("POST:")) + _uri);
|
||||
}else if(_currentMethod == HTTP_PUT){
|
||||
md5.add("PUT:"+_uri);
|
||||
md5.add(String(F("PUT:")) + _uri);
|
||||
}else if(_currentMethod == HTTP_DELETE){
|
||||
md5.add("DELETE:"+_uri);
|
||||
md5.add(String(F("DELETE:")) + _uri);
|
||||
}else{
|
||||
md5.add("GET:"+_uri);
|
||||
md5.add(String(F("GET:")) + _uri);
|
||||
}
|
||||
md5.calculate();
|
||||
String _H2 = md5.toString();
|
||||
@ -184,49 +194,50 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password
|
||||
DEBUG_OUTPUT.println("Hash of GET:uri=" + _H2);
|
||||
#endif
|
||||
md5.begin();
|
||||
if(authReq.indexOf("qop=auth") != -1){
|
||||
md5.add(_H1+":"+_nonce+":"+_nc+":"+_cnonce+":auth:"+_H2);
|
||||
if(authReq.indexOf(FPSTR(qop_auth)) != -1) {
|
||||
md5.add(_H1 + FPSTR(colon) + _nonce + FPSTR(colon) + _nc + FPSTR(colon) + _cnonce + ':auth:' + _H2);
|
||||
}else{
|
||||
md5.add(_H1+":"+_nonce+":"+_H2);
|
||||
md5.add(_H1 + FPSTR(colon) + _nonce + FPSTR(colon) + _H2);
|
||||
}
|
||||
md5.calculate();
|
||||
String _responsecheck = md5.toString();
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("The Proper response=" +_responsecheck);
|
||||
#endif
|
||||
if(_response==_responsecheck){
|
||||
authReq = String();
|
||||
if(_response == _responsecheck){
|
||||
authReq = "";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
authReq = String();
|
||||
authReq = "";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String ESP8266WebServer::_getRandomHexString(){
|
||||
String ESP8266WebServer::_getRandomHexString() {
|
||||
char buffer[33]; // buffer to hold 32 Hex Digit + /0
|
||||
int i;
|
||||
for(i=0;i<4;i++){
|
||||
sprintf (buffer+(i*8), "%08x", RANDOM_REG32);
|
||||
for(i = 0; i < 4; i++) {
|
||||
sprintf (buffer + (i*8), "%08x", RANDOM_REG32);
|
||||
}
|
||||
return String(buffer);
|
||||
}
|
||||
|
||||
void ESP8266WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg){
|
||||
if(realm==NULL){
|
||||
_srealm = "Login Required";
|
||||
}else{
|
||||
void ESP8266WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg) {
|
||||
if(realm == NULL) {
|
||||
_srealm = String(F("Login Required"));
|
||||
} else {
|
||||
_srealm = String(realm);
|
||||
}
|
||||
if(mode==BASIC_AUTH){
|
||||
sendHeader("WWW-Authenticate", "Basic realm=\"" + _srealm + "\"");
|
||||
}else{
|
||||
if(mode == BASIC_AUTH) {
|
||||
sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Basic realm=\"")) + _srealm + String(F("\"")));
|
||||
} else {
|
||||
_snonce=_getRandomHexString();
|
||||
_sopaque=_getRandomHexString();
|
||||
sendHeader("WWW-Authenticate", "Digest realm=\"" +_srealm + "\", qop=\"auth\", nonce=\""+_snonce+"\", opaque=\""+_sopaque+"\"");
|
||||
sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Digest realm=\"")) +_srealm + String(F("\", qop=\"auth\", nonce=\"")) + _snonce + String(F("\", opaque=\"")) + _sopaque + String(F("\"")));
|
||||
}
|
||||
send(401,"text/html",authFailMsg);
|
||||
using namespace mime;
|
||||
send(401, mimeTable[html].mimeType, authFailMsg);
|
||||
}
|
||||
|
||||
void ESP8266WebServer::on(const String &uri, ESP8266WebServer::THandlerFunction handler) {
|
||||
@ -327,6 +338,9 @@ void ESP8266WebServer::handleClient() {
|
||||
|
||||
void ESP8266WebServer::close() {
|
||||
_server.close();
|
||||
_currentStatus = HC_NONE;
|
||||
if(!_headerKeysCount)
|
||||
collectHeaders(0, 0);
|
||||
}
|
||||
|
||||
void ESP8266WebServer::stop() {
|
||||
@ -335,7 +349,7 @@ void ESP8266WebServer::stop() {
|
||||
|
||||
void ESP8266WebServer::sendHeader(const String& name, const String& value, bool first) {
|
||||
String headerLine = name;
|
||||
headerLine += ": ";
|
||||
headerLine += F(": ");
|
||||
headerLine += value;
|
||||
headerLine += "\r\n";
|
||||
|
||||
@ -347,36 +361,37 @@ void ESP8266WebServer::sendHeader(const String& name, const String& value, bool
|
||||
}
|
||||
}
|
||||
|
||||
void ESP8266WebServer::setContentLength(size_t contentLength) {
|
||||
void ESP8266WebServer::setContentLength(const size_t contentLength) {
|
||||
_contentLength = contentLength;
|
||||
}
|
||||
|
||||
void ESP8266WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) {
|
||||
response = "HTTP/1."+String(_currentVersion)+" ";
|
||||
response = String(F("HTTP/1.")) + String(_currentVersion) + ' ';
|
||||
response += String(code);
|
||||
response += " ";
|
||||
response += ' ';
|
||||
response += _responseCodeToString(code);
|
||||
response += "\r\n";
|
||||
|
||||
using namespace mime;
|
||||
if (!content_type)
|
||||
content_type = "text/html";
|
||||
content_type = mimeTable[html].mimeType;
|
||||
|
||||
sendHeader("Content-Type", content_type, true);
|
||||
sendHeader(String(F("Content-Type")), content_type, true);
|
||||
if (_contentLength == CONTENT_LENGTH_NOT_SET) {
|
||||
sendHeader("Content-Length", String(contentLength));
|
||||
sendHeader(String(FPSTR(Content_Length)), String(contentLength));
|
||||
} else if (_contentLength != CONTENT_LENGTH_UNKNOWN) {
|
||||
sendHeader("Content-Length", String(_contentLength));
|
||||
sendHeader(String(FPSTR(Content_Length)), String(_contentLength));
|
||||
} else if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ //HTTP/1.1 or above client
|
||||
//let's do chunked
|
||||
_chunked = true;
|
||||
sendHeader("Accept-Ranges","none");
|
||||
sendHeader("Transfer-Encoding","chunked");
|
||||
sendHeader(String(F("Accept-Ranges")),String(F("none")));
|
||||
sendHeader(String(F("Transfer-Encoding")),String(F("chunked")));
|
||||
}
|
||||
sendHeader("Connection", "close");
|
||||
sendHeader(String(F("Connection")), String(F("close")));
|
||||
|
||||
response += _responseHeaders;
|
||||
response += "\r\n";
|
||||
_responseHeaders = String();
|
||||
_responseHeaders = "";
|
||||
}
|
||||
|
||||
void ESP8266WebServer::send(int code, const char* content_type, const String& content) {
|
||||
@ -466,24 +481,37 @@ void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) {
|
||||
}
|
||||
|
||||
|
||||
void ESP8266WebServer::_streamFileCore(const size_t fileSize, const String & fileName, const String & contentType)
|
||||
{
|
||||
using namespace mime;
|
||||
setContentLength(fileSize);
|
||||
if (fileName.endsWith(mimeTable[gz].endsWith) &&
|
||||
contentType != mimeTable[gz].mimeType &&
|
||||
contentType != mimeTable[none].mimeType) {
|
||||
sendHeader(F("Content-Encoding"), F("gzip"));
|
||||
}
|
||||
send(200, contentType, "");
|
||||
}
|
||||
|
||||
|
||||
String ESP8266WebServer::arg(String name) {
|
||||
for (int i = 0; i < _currentArgCount; ++i) {
|
||||
if ( _currentArgs[i].key == name )
|
||||
return _currentArgs[i].value;
|
||||
}
|
||||
return String();
|
||||
return "";
|
||||
}
|
||||
|
||||
String ESP8266WebServer::arg(int i) {
|
||||
if (i < _currentArgCount)
|
||||
return _currentArgs[i].value;
|
||||
return String();
|
||||
return "";
|
||||
}
|
||||
|
||||
String ESP8266WebServer::argName(int i) {
|
||||
if (i < _currentArgCount)
|
||||
return _currentArgs[i].key;
|
||||
return String();
|
||||
return "";
|
||||
}
|
||||
|
||||
int ESP8266WebServer::args() {
|
||||
@ -504,7 +532,7 @@ String ESP8266WebServer::header(String name) {
|
||||
if (_currentHeaders[i].key.equalsIgnoreCase(name))
|
||||
return _currentHeaders[i].value;
|
||||
}
|
||||
return String();
|
||||
return "";
|
||||
}
|
||||
|
||||
void ESP8266WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
|
||||
@ -512,7 +540,7 @@ void ESP8266WebServer::collectHeaders(const char* headerKeys[], const size_t hea
|
||||
if (_currentHeaders)
|
||||
delete[]_currentHeaders;
|
||||
_currentHeaders = new RequestArgument[_headerKeysCount];
|
||||
_currentHeaders[0].key = AUTHORIZATION_HEADER;
|
||||
_currentHeaders[0].key = FPSTR(AUTHORIZATION_HEADER);
|
||||
for (int i = 1; i < _headerKeysCount; i++){
|
||||
_currentHeaders[i].key = headerKeys[i-1];
|
||||
}
|
||||
@ -521,13 +549,13 @@ void ESP8266WebServer::collectHeaders(const char* headerKeys[], const size_t hea
|
||||
String ESP8266WebServer::header(int i) {
|
||||
if (i < _headerKeysCount)
|
||||
return _currentHeaders[i].value;
|
||||
return String();
|
||||
return "";
|
||||
}
|
||||
|
||||
String ESP8266WebServer::headerName(int i) {
|
||||
if (i < _headerKeysCount)
|
||||
return _currentHeaders[i].key;
|
||||
return String();
|
||||
return "";
|
||||
}
|
||||
|
||||
int ESP8266WebServer::headers() {
|
||||
@ -574,13 +602,14 @@ void ESP8266WebServer::_handleRequest() {
|
||||
handled = true;
|
||||
}
|
||||
if (!handled) {
|
||||
send(404, "text/plain", String("Not found: ") + _currentUri);
|
||||
using namespace mime;
|
||||
send(404, mimeTable[html].mimeType, String(F("Not found: ")) + _currentUri);
|
||||
handled = true;
|
||||
}
|
||||
if (handled) {
|
||||
_finalizeResponse();
|
||||
}
|
||||
_currentUri = String();
|
||||
_currentUri = "";
|
||||
}
|
||||
|
||||
|
||||
@ -632,6 +661,6 @@ String ESP8266WebServer::_responseCodeToString(int code) {
|
||||
case 503: return F("Service Unavailable");
|
||||
case 504: return F("Gateway Time-out");
|
||||
case 505: return F("HTTP Version not supported");
|
||||
default: return "";
|
||||
default: return F("");
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ public:
|
||||
virtual ~ESP8266WebServer();
|
||||
|
||||
virtual void begin();
|
||||
virtual void begin(uint16_t port);
|
||||
virtual void handleClient();
|
||||
|
||||
virtual void close();
|
||||
@ -120,7 +121,7 @@ public:
|
||||
void send_P(int code, PGM_P content_type, PGM_P content);
|
||||
void send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength);
|
||||
|
||||
void setContentLength(size_t contentLength);
|
||||
void setContentLength(const size_t contentLength);
|
||||
void sendHeader(const String& name, const String& value, bool first = false);
|
||||
void sendContent(const String& content);
|
||||
void sendContent_P(PGM_P content);
|
||||
@ -128,17 +129,12 @@ public:
|
||||
|
||||
static String urlDecode(const String& text);
|
||||
|
||||
template<typename T> size_t streamFile(T &file, const String& contentType){
|
||||
setContentLength(file.size());
|
||||
if (String(file.name()).endsWith(".gz") &&
|
||||
contentType != "application/x-gzip" &&
|
||||
contentType != "application/octet-stream"){
|
||||
sendHeader("Content-Encoding", "gzip");
|
||||
template<typename T>
|
||||
size_t streamFile(T &file, const String& contentType) {
|
||||
_streamFileCore(file.size(), file.name(), contentType);
|
||||
return _currentClient.write(file);
|
||||
}
|
||||
send(200, contentType, "");
|
||||
return _currentClient.write(file);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual size_t _currentClientWrite(const char* b, size_t l) { return _currentClient.write( b, l ); }
|
||||
virtual size_t _currentClientWrite_P(PGM_P b, size_t l) { return _currentClient.write_P( b, l ); }
|
||||
@ -154,10 +150,12 @@ protected:
|
||||
uint8_t _uploadReadByte(WiFiClient& client);
|
||||
void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength);
|
||||
bool _collectHeader(const char* headerName, const char* headerValue);
|
||||
|
||||
|
||||
void _streamFileCore(const size_t fileSize, const String & fileName, const String & contentType);
|
||||
|
||||
String _getRandomHexString();
|
||||
// for extracting Auth parameters
|
||||
String _exractParam(String& authReq,const String& param,const char delimit = '"');
|
||||
String _extractParam(String& authReq,const String& param,const char delimit = '"');
|
||||
|
||||
struct RequestArgument {
|
||||
String key;
|
||||
|
@ -2,32 +2,9 @@
|
||||
#define REQUESTHANDLERSIMPL_H
|
||||
|
||||
#include "RequestHandler.h"
|
||||
#include "mimetable.h"
|
||||
|
||||
// Table of extension->MIME strings stored in PROGMEM, needs to be global due to GCC section typing rules
|
||||
static const struct {const char endsWith[16]; const char mimeType[32];} mimeTable[] ICACHE_RODATA_ATTR = {
|
||||
{ ".html", "text/html" },
|
||||
{ ".htm", "text/html" },
|
||||
{ ".css", "text/css" },
|
||||
{ ".txt", "text/plain" },
|
||||
{ ".js", "application/javascript" },
|
||||
{ ".json", "application/json" },
|
||||
{ ".png", "image/png" },
|
||||
{ ".gif", "image/gif" },
|
||||
{ ".jpg", "image/jpeg" },
|
||||
{ ".ico", "image/x-icon" },
|
||||
{ ".svg", "image/svg+xml" },
|
||||
{ ".ttf", "application/x-font-ttf" },
|
||||
{ ".otf", "application/x-font-opentype" },
|
||||
{ ".woff", "application/font-woff" },
|
||||
{ ".woff2", "application/font-woff2" },
|
||||
{ ".eot", "application/vnd.ms-fontobject" },
|
||||
{ ".sfnt", "application/font-sfnt" },
|
||||
{ ".xml", "text/xml" },
|
||||
{ ".pdf", "application/pdf" },
|
||||
{ ".zip", "application/zip" },
|
||||
{ ".gz", "application/x-gzip" },
|
||||
{ ".appcache", "text/cache-manifest" },
|
||||
{ "", "application/octet-stream" } };
|
||||
using namespace mime;
|
||||
|
||||
class FunctionRequestHandler : public RequestHandler {
|
||||
public:
|
||||
@ -124,10 +101,10 @@ public:
|
||||
|
||||
// look for gz file, only if the original specified path is not a gz. So part only works to send gzip via content encoding when a non compressed is asked for
|
||||
// if you point the the path to gzip you will serve the gzip as content type "application/x-gzip", not text or javascript etc...
|
||||
if (!path.endsWith(".gz") && !_fs.exists(path)) {
|
||||
String pathWithGz = path + ".gz";
|
||||
if (!path.endsWith(mimeTable[gz].endsWith) && !_fs.exists(path)) {
|
||||
String pathWithGz = path + mimeTable[gz].endsWith;
|
||||
if(_fs.exists(pathWithGz))
|
||||
path += ".gz";
|
||||
path += mimeTable[gz].endsWith;
|
||||
}
|
||||
|
||||
File f = _fs.open(path, "r");
|
||||
|
35
libraries/ESP8266WebServer/src/detail/mimetable.cpp
Normal file
35
libraries/ESP8266WebServer/src/detail/mimetable.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "mimetable.h"
|
||||
#include "pgmspace.h"
|
||||
|
||||
namespace mime
|
||||
{
|
||||
|
||||
// Table of extension->MIME strings stored in PROGMEM, needs to be global due to GCC section typing rules
|
||||
const Entry mimeTable[maxType] ICACHE_RODATA_ATTR =
|
||||
{
|
||||
{ ".html", "text/html" },
|
||||
{ ".htm", "text/html" },
|
||||
{ ".css", "text/css" },
|
||||
{ ".txt", "text/plain" },
|
||||
{ ".js", "application/javascript" },
|
||||
{ ".json", "application/json" },
|
||||
{ ".png", "image/png" },
|
||||
{ ".gif", "image/gif" },
|
||||
{ ".jpg", "image/jpeg" },
|
||||
{ ".ico", "image/x-icon" },
|
||||
{ ".svg", "image/svg+xml" },
|
||||
{ ".ttf", "application/x-font-ttf" },
|
||||
{ ".otf", "application/x-font-opentype" },
|
||||
{ ".woff", "application/font-woff" },
|
||||
{ ".woff2", "application/font-woff2" },
|
||||
{ ".eot", "application/vnd.ms-fontobject" },
|
||||
{ ".sfnt", "application/font-sfnt" },
|
||||
{ ".xml", "text/xml" },
|
||||
{ ".pdf", "application/pdf" },
|
||||
{ ".zip", "application/zip" },
|
||||
{ ".gz", "application/x-gzip" },
|
||||
{ ".appcache", "text/cache-manifest" },
|
||||
{ "", "application/octet-stream" }
|
||||
};
|
||||
|
||||
}
|
47
libraries/ESP8266WebServer/src/detail/mimetable.h
Normal file
47
libraries/ESP8266WebServer/src/detail/mimetable.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef __MIMETABLE_H__
|
||||
#define __MIMETABLE_H__
|
||||
|
||||
|
||||
namespace mime
|
||||
{
|
||||
|
||||
enum type
|
||||
{
|
||||
html,
|
||||
htm,
|
||||
css,
|
||||
txt,
|
||||
js,
|
||||
json,
|
||||
png,
|
||||
gif,
|
||||
jpg,
|
||||
ico,
|
||||
svg,
|
||||
ttf,
|
||||
otf,
|
||||
woff,
|
||||
woff2,
|
||||
eot,
|
||||
sfnt,
|
||||
xml,
|
||||
pdf,
|
||||
zip,
|
||||
gz,
|
||||
appcache,
|
||||
none,
|
||||
maxType
|
||||
};
|
||||
|
||||
struct Entry
|
||||
{
|
||||
const char endsWith[16];
|
||||
const char mimeType[32];
|
||||
};
|
||||
|
||||
|
||||
extern const Entry mimeTable[maxType];
|
||||
}
|
||||
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user