Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit bcbd596

Browse files
authoredFeb 7, 2018
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)
1 parent 0339bbb commit bcbd596

File tree

5 files changed

+212
-126
lines changed

5 files changed

+212
-126
lines changed
 

‎libraries/ESP8266WebServer/src/ESP8266WebServer.cpp

Lines changed: 114 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,27 @@
3636
#define DEBUG_OUTPUT Serial
3737
#endif
3838

39-
const char * AUTHORIZATION_HEADER = "Authorization";
39+
//const char * AUTHORIZATION_HEADER = "Authorization";
40+
static const char AUTHORIZATION_HEADER[] PROGMEM = "Authorization";
41+
static const char qop_auth[] PROGMEM = "qop=auth";
42+
static const char WWW_Authenticate[] PROGMEM = "WWW-Authenticate";
43+
static const char colon[] PROGMEM = ":";
44+
static const char Content_Length[] PROGMEM = "Content-Length";
45+
4046

4147
ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port)
4248
: _server(addr, port)
4349
, _currentMethod(HTTP_ANY)
4450
, _currentVersion(0)
4551
, _currentStatus(HC_NONE)
4652
, _statusChange(0)
47-
, _currentHandler(0)
48-
, _firstHandler(0)
49-
, _lastHandler(0)
53+
, _currentHandler(nullptr)
54+
, _firstHandler(nullptr)
55+
, _lastHandler(nullptr)
5056
, _currentArgCount(0)
51-
, _currentArgs(0)
57+
, _currentArgs(nullptr)
5258
, _headerKeysCount(0)
53-
, _currentHeaders(0)
59+
, _currentHeaders(nullptr)
5460
, _contentLength(0)
5561
, _chunked(false)
5662
{
@@ -62,13 +68,13 @@ ESP8266WebServer::ESP8266WebServer(int port)
6268
, _currentVersion(0)
6369
, _currentStatus(HC_NONE)
6470
, _statusChange(0)
65-
, _currentHandler(0)
66-
, _firstHandler(0)
67-
, _lastHandler(0)
71+
, _currentHandler(nullptr)
72+
, _firstHandler(nullptr)
73+
, _lastHandler(nullptr)
6874
, _currentArgCount(0)
69-
, _currentArgs(0)
75+
, _currentArgs(nullptr)
7076
, _headerKeysCount(0)
71-
, _currentHeaders(0)
77+
, _currentHeaders(nullptr)
7278
, _contentLength(0)
7379
, _chunked(false)
7480
{
@@ -88,145 +94,150 @@ ESP8266WebServer::~ESP8266WebServer() {
8894
}
8995

9096
void ESP8266WebServer::begin() {
91-
_currentStatus = HC_NONE;
97+
close();
9298
_server.begin();
93-
if(!_headerKeysCount)
94-
collectHeaders(0, 0);
9599
}
96100

97-
String ESP8266WebServer::_exractParam(String& authReq,const String& param,const char delimit){
101+
void ESP8266WebServer::begin(uint16_t port) {
102+
close();
103+
_server.begin(port);
104+
}
105+
106+
String ESP8266WebServer::_extractParam(String& authReq,const String& param,const char delimit){
98107
int _begin = authReq.indexOf(param);
99-
if (_begin==-1) return "";
108+
if (_begin==-1)
109+
return "";
100110
return authReq.substring(_begin+param.length(),authReq.indexOf(delimit,_begin+param.length()));
101111
}
102112

103113
bool ESP8266WebServer::authenticate(const char * username, const char * password){
104-
if(hasHeader(AUTHORIZATION_HEADER)){
105-
String authReq = header(AUTHORIZATION_HEADER);
106-
if(authReq.startsWith("Basic")){
114+
if(hasHeader(FPSTR(AUTHORIZATION_HEADER))) {
115+
String authReq = header(FPSTR(AUTHORIZATION_HEADER));
116+
if(authReq.startsWith(F("Basic"))){
107117
authReq = authReq.substring(6);
108118
authReq.trim();
109119
char toencodeLen = strlen(username)+strlen(password)+1;
110120
char *toencode = new char[toencodeLen + 1];
111121
if(toencode == NULL){
112-
authReq = String();
122+
authReq = "";
113123
return false;
114124
}
115125
char *encoded = new char[base64_encode_expected_len(toencodeLen)+1];
116126
if(encoded == NULL){
117-
authReq = String();
127+
authReq = "";
118128
delete[] toencode;
119129
return false;
120130
}
121131
sprintf(toencode, "%s:%s", username, password);
122132
if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq.equalsConstantTime(encoded)) {
123-
authReq = String();
133+
authReq = "";
124134
delete[] toencode;
125135
delete[] encoded;
126136
return true;
127137
}
128138
delete[] toencode;
129139
delete[] encoded;
130-
}else if(authReq.startsWith("Digest")){
140+
} else if(authReq.startsWith(F("Digest"))) {
131141
authReq = authReq.substring(7);
132142
#ifdef DEBUG_ESP_HTTP_SERVER
133143
DEBUG_OUTPUT.println(authReq);
134144
#endif
135-
String _username = _exractParam(authReq,"username=\"");
136-
if((!_username.length())||_username!=String(username)){
137-
authReq = String();
145+
String _username = _extractParam(authReq,F("username=\""));
146+
if(!_username.length() || _username != String(username)) {
147+
authReq = "";
138148
return false;
139149
}
140150
// extracting required parameters for RFC 2069 simpler Digest
141-
String _realm = _exractParam(authReq,"realm=\"");
142-
String _nonce = _exractParam(authReq,"nonce=\"");
143-
String _uri = _exractParam(authReq,"uri=\"");
144-
String _response = _exractParam(authReq,"response=\"");
145-
String _opaque = _exractParam(authReq,"opaque=\"");
146-
147-
if((!_realm.length())||(!_nonce.length())||(!_uri.length())||(!_response.length())||(!_opaque.length())){
148-
authReq = String();
151+
String _realm = _extractParam(authReq, F("realm=\""));
152+
String _nonce = _extractParam(authReq, F("nonce=\""));
153+
String _uri = _extractParam(authReq, F("uri=\""));
154+
String _response = _extractParam(authReq, F("response=\""));
155+
String _opaque = _extractParam(authReq, F("opaque=\""));
156+
157+
if((!_realm.length()) || (!_nonce.length()) || (!_uri.length()) || (!_response.length()) || (!_opaque.length())) {
158+
authReq = "";
149159
return false;
150160
}
151-
if((_opaque!=_sopaque)||(_nonce!=_snonce)||(_realm!=_srealm)){
152-
authReq = String();
161+
if((_opaque != _sopaque) || (_nonce != _snonce) || (_realm != _srealm)) {
162+
authReq = "";
153163
return false;
154164
}
155165
// parameters for the RFC 2617 newer Digest
156166
String _nc,_cnonce;
157-
if(authReq.indexOf("qop=auth") != -1){
158-
_nc = _exractParam(authReq,"nc=",',');
159-
_cnonce = _exractParam(authReq,"cnonce=\"");
167+
if(authReq.indexOf(FPSTR(qop_auth)) != -1) {
168+
_nc = _extractParam(authReq, F("nc="), ',');
169+
_cnonce = _extractParam(authReq, F("cnonce=\""));
160170
}
161171
MD5Builder md5;
162172
md5.begin();
163-
md5.add(String(username)+":"+_realm+":"+String(password)); // md5 of the user:realm:user
173+
md5.add(String(username) + ':' + _realm + ':' + String(password)); // md5 of the user:realm:user
164174
md5.calculate();
165175
String _H1 = md5.toString();
166176
#ifdef DEBUG_ESP_HTTP_SERVER
167177
DEBUG_OUTPUT.println("Hash of user:realm:pass=" + _H1);
168178
#endif
169179
md5.begin();
170180
if(_currentMethod == HTTP_GET){
171-
md5.add("GET:"+_uri);
181+
md5.add(String(F("GET:")) + _uri);
172182
}else if(_currentMethod == HTTP_POST){
173-
md5.add("POST:"+_uri);
183+
md5.add(String(F("POST:")) + _uri);
174184
}else if(_currentMethod == HTTP_PUT){
175-
md5.add("PUT:"+_uri);
185+
md5.add(String(F("PUT:")) + _uri);
176186
}else if(_currentMethod == HTTP_DELETE){
177-
md5.add("DELETE:"+_uri);
187+
md5.add(String(F("DELETE:")) + _uri);
178188
}else{
179-
md5.add("GET:"+_uri);
189+
md5.add(String(F("GET:")) + _uri);
180190
}
181191
md5.calculate();
182192
String _H2 = md5.toString();
183193
#ifdef DEBUG_ESP_HTTP_SERVER
184194
DEBUG_OUTPUT.println("Hash of GET:uri=" + _H2);
185195
#endif
186196
md5.begin();
187-
if(authReq.indexOf("qop=auth") != -1){
188-
md5.add(_H1+":"+_nonce+":"+_nc+":"+_cnonce+":auth:"+_H2);
197+
if(authReq.indexOf(FPSTR(qop_auth)) != -1) {
198+
md5.add(_H1 + FPSTR(colon) + _nonce + FPSTR(colon) + _nc + FPSTR(colon) + _cnonce + ':auth:' + _H2);
189199
}else{
190-
md5.add(_H1+":"+_nonce+":"+_H2);
200+
md5.add(_H1 + FPSTR(colon) + _nonce + FPSTR(colon) + _H2);
191201
}
192202
md5.calculate();
193203
String _responsecheck = md5.toString();
194204
#ifdef DEBUG_ESP_HTTP_SERVER
195205
DEBUG_OUTPUT.println("The Proper response=" +_responsecheck);
196206
#endif
197-
if(_response==_responsecheck){
198-
authReq = String();
207+
if(_response == _responsecheck){
208+
authReq = "";
199209
return true;
200210
}
201211
}
202-
authReq = String();
212+
authReq = "";
203213
}
204214
return false;
205215
}
206216

207-
String ESP8266WebServer::_getRandomHexString(){
217+
String ESP8266WebServer::_getRandomHexString() {
208218
char buffer[33]; // buffer to hold 32 Hex Digit + /0
209219
int i;
210-
for(i=0;i<4;i++){
211-
sprintf (buffer+(i*8), "%08x", RANDOM_REG32);
220+
for(i = 0; i < 4; i++) {
221+
sprintf (buffer + (i*8), "%08x", RANDOM_REG32);
212222
}
213223
return String(buffer);
214224
}
215225

216-
void ESP8266WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg){
217-
if(realm==NULL){
218-
_srealm = "Login Required";
219-
}else{
226+
void ESP8266WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg) {
227+
if(realm == NULL) {
228+
_srealm = String(F("Login Required"));
229+
} else {
220230
_srealm = String(realm);
221231
}
222-
if(mode==BASIC_AUTH){
223-
sendHeader("WWW-Authenticate", "Basic realm=\"" + _srealm + "\"");
224-
}else{
232+
if(mode == BASIC_AUTH) {
233+
sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Basic realm=\"")) + _srealm + String(F("\"")));
234+
} else {
225235
_snonce=_getRandomHexString();
226236
_sopaque=_getRandomHexString();
227-
sendHeader("WWW-Authenticate", "Digest realm=\"" +_srealm + "\", qop=\"auth\", nonce=\""+_snonce+"\", opaque=\""+_sopaque+"\"");
237+
sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Digest realm=\"")) +_srealm + String(F("\", qop=\"auth\", nonce=\"")) + _snonce + String(F("\", opaque=\"")) + _sopaque + String(F("\"")));
228238
}
229-
send(401,"text/html",authFailMsg);
239+
using namespace mime;
240+
send(401, mimeTable[html].mimeType, authFailMsg);
230241
}
231242

232243
void ESP8266WebServer::on(const String &uri, ESP8266WebServer::THandlerFunction handler) {
@@ -327,6 +338,9 @@ void ESP8266WebServer::handleClient() {
327338

328339
void ESP8266WebServer::close() {
329340
_server.close();
341+
_currentStatus = HC_NONE;
342+
if(!_headerKeysCount)
343+
collectHeaders(0, 0);
330344
}
331345

332346
void ESP8266WebServer::stop() {
@@ -335,7 +349,7 @@ void ESP8266WebServer::stop() {
335349

336350
void ESP8266WebServer::sendHeader(const String& name, const String& value, bool first) {
337351
String headerLine = name;
338-
headerLine += ": ";
352+
headerLine += F(": ");
339353
headerLine += value;
340354
headerLine += "\r\n";
341355

@@ -347,36 +361,37 @@ void ESP8266WebServer::sendHeader(const String& name, const String& value, bool
347361
}
348362
}
349363

350-
void ESP8266WebServer::setContentLength(size_t contentLength) {
364+
void ESP8266WebServer::setContentLength(const size_t contentLength) {
351365
_contentLength = contentLength;
352366
}
353367

354368
void ESP8266WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) {
355-
response = "HTTP/1."+String(_currentVersion)+" ";
369+
response = String(F("HTTP/1.")) + String(_currentVersion) + ' ';
356370
response += String(code);
357-
response += " ";
371+
response += ' ';
358372
response += _responseCodeToString(code);
359373
response += "\r\n";
360374

375+
using namespace mime;
361376
if (!content_type)
362-
content_type = "text/html";
377+
content_type = mimeTable[html].mimeType;
363378

364-
sendHeader("Content-Type", content_type, true);
379+
sendHeader(String(F("Content-Type")), content_type, true);
365380
if (_contentLength == CONTENT_LENGTH_NOT_SET) {
366-
sendHeader("Content-Length", String(contentLength));
381+
sendHeader(String(FPSTR(Content_Length)), String(contentLength));
367382
} else if (_contentLength != CONTENT_LENGTH_UNKNOWN) {
368-
sendHeader("Content-Length", String(_contentLength));
383+
sendHeader(String(FPSTR(Content_Length)), String(_contentLength));
369384
} else if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ //HTTP/1.1 or above client
370385
//let's do chunked
371386
_chunked = true;
372-
sendHeader("Accept-Ranges","none");
373-
sendHeader("Transfer-Encoding","chunked");
387+
sendHeader(String(F("Accept-Ranges")),String(F("none")));
388+
sendHeader(String(F("Transfer-Encoding")),String(F("chunked")));
374389
}
375-
sendHeader("Connection", "close");
390+
sendHeader(String(F("Connection")), String(F("close")));
376391

377392
response += _responseHeaders;
378393
response += "\r\n";
379-
_responseHeaders = String();
394+
_responseHeaders = "";
380395
}
381396

382397
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) {
466481
}
467482

468483

484+
void ESP8266WebServer::_streamFileCore(const size_t fileSize, const String & fileName, const String & contentType)
485+
{
486+
using namespace mime;
487+
setContentLength(fileSize);
488+
if (fileName.endsWith(mimeTable[gz].endsWith) &&
489+
contentType != mimeTable[gz].mimeType &&
490+
contentType != mimeTable[none].mimeType) {
491+
sendHeader(F("Content-Encoding"), F("gzip"));
492+
}
493+
send(200, contentType, "");
494+
}
495+
496+
469497
String ESP8266WebServer::arg(String name) {
470498
for (int i = 0; i < _currentArgCount; ++i) {
471499
if ( _currentArgs[i].key == name )
472500
return _currentArgs[i].value;
473501
}
474-
return String();
502+
return "";
475503
}
476504

477505
String ESP8266WebServer::arg(int i) {
478506
if (i < _currentArgCount)
479507
return _currentArgs[i].value;
480-
return String();
508+
return "";
481509
}
482510

483511
String ESP8266WebServer::argName(int i) {
484512
if (i < _currentArgCount)
485513
return _currentArgs[i].key;
486-
return String();
514+
return "";
487515
}
488516

489517
int ESP8266WebServer::args() {
@@ -504,15 +532,15 @@ String ESP8266WebServer::header(String name) {
504532
if (_currentHeaders[i].key.equalsIgnoreCase(name))
505533
return _currentHeaders[i].value;
506534
}
507-
return String();
535+
return "";
508536
}
509537

510538
void ESP8266WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
511539
_headerKeysCount = headerKeysCount + 1;
512540
if (_currentHeaders)
513541
delete[]_currentHeaders;
514542
_currentHeaders = new RequestArgument[_headerKeysCount];
515-
_currentHeaders[0].key = AUTHORIZATION_HEADER;
543+
_currentHeaders[0].key = FPSTR(AUTHORIZATION_HEADER);
516544
for (int i = 1; i < _headerKeysCount; i++){
517545
_currentHeaders[i].key = headerKeys[i-1];
518546
}
@@ -521,13 +549,13 @@ void ESP8266WebServer::collectHeaders(const char* headerKeys[], const size_t hea
521549
String ESP8266WebServer::header(int i) {
522550
if (i < _headerKeysCount)
523551
return _currentHeaders[i].value;
524-
return String();
552+
return "";
525553
}
526554

527555
String ESP8266WebServer::headerName(int i) {
528556
if (i < _headerKeysCount)
529557
return _currentHeaders[i].key;
530-
return String();
558+
return "";
531559
}
532560

533561
int ESP8266WebServer::headers() {
@@ -574,13 +602,14 @@ void ESP8266WebServer::_handleRequest() {
574602
handled = true;
575603
}
576604
if (!handled) {
577-
send(404, "text/plain", String("Not found: ") + _currentUri);
605+
using namespace mime;
606+
send(404, mimeTable[html].mimeType, String(F("Not found: ")) + _currentUri);
578607
handled = true;
579608
}
580609
if (handled) {
581610
_finalizeResponse();
582611
}
583-
_currentUri = String();
612+
_currentUri = "";
584613
}
585614

586615

@@ -632,6 +661,6 @@ String ESP8266WebServer::_responseCodeToString(int code) {
632661
case 503: return F("Service Unavailable");
633662
case 504: return F("Gateway Time-out");
634663
case 505: return F("HTTP Version not supported");
635-
default: return "";
664+
default: return F("");
636665
}
637666
}

‎libraries/ESP8266WebServer/src/ESP8266WebServer.h

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class ESP8266WebServer
7474
virtual ~ESP8266WebServer();
7575

7676
virtual void begin();
77+
virtual void begin(uint16_t port);
7778
virtual void handleClient();
7879

7980
virtual void close();
@@ -120,25 +121,20 @@ class ESP8266WebServer
120121
void send_P(int code, PGM_P content_type, PGM_P content);
121122
void send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength);
122123

123-
void setContentLength(size_t contentLength);
124+
void setContentLength(const size_t contentLength);
124125
void sendHeader(const String& name, const String& value, bool first = false);
125126
void sendContent(const String& content);
126127
void sendContent_P(PGM_P content);
127128
void sendContent_P(PGM_P content, size_t size);
128129

129130
static String urlDecode(const String& text);
130131

131-
template<typename T> size_t streamFile(T &file, const String& contentType){
132-
setContentLength(file.size());
133-
if (String(file.name()).endsWith(".gz") &&
134-
contentType != "application/x-gzip" &&
135-
contentType != "application/octet-stream"){
136-
sendHeader("Content-Encoding", "gzip");
132+
template<typename T>
133+
size_t streamFile(T &file, const String& contentType) {
134+
_streamFileCore(file.size(), file.name(), contentType);
135+
return _currentClient.write(file);
137136
}
138-
send(200, contentType, "");
139-
return _currentClient.write(file);
140-
}
141-
137+
142138
protected:
143139
virtual size_t _currentClientWrite(const char* b, size_t l) { return _currentClient.write( b, l ); }
144140
virtual size_t _currentClientWrite_P(PGM_P b, size_t l) { return _currentClient.write_P( b, l ); }
@@ -154,10 +150,12 @@ template<typename T> size_t streamFile(T &file, const String& contentType){
154150
uint8_t _uploadReadByte(WiFiClient& client);
155151
void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength);
156152
bool _collectHeader(const char* headerName, const char* headerValue);
157-
153+
154+
void _streamFileCore(const size_t fileSize, const String & fileName, const String & contentType);
155+
158156
String _getRandomHexString();
159157
// for extracting Auth parameters
160-
String _exractParam(String& authReq,const String& param,const char delimit = '"');
158+
String _extractParam(String& authReq,const String& param,const char delimit = '"');
161159

162160
struct RequestArgument {
163161
String key;

‎libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,9 @@
22
#define REQUESTHANDLERSIMPL_H
33

44
#include "RequestHandler.h"
5+
#include "mimetable.h"
56

6-
// Table of extension->MIME strings stored in PROGMEM, needs to be global due to GCC section typing rules
7-
static const struct {const char endsWith[16]; const char mimeType[32];} mimeTable[] ICACHE_RODATA_ATTR = {
8-
{ ".html", "text/html" },
9-
{ ".htm", "text/html" },
10-
{ ".css", "text/css" },
11-
{ ".txt", "text/plain" },
12-
{ ".js", "application/javascript" },
13-
{ ".json", "application/json" },
14-
{ ".png", "image/png" },
15-
{ ".gif", "image/gif" },
16-
{ ".jpg", "image/jpeg" },
17-
{ ".ico", "image/x-icon" },
18-
{ ".svg", "image/svg+xml" },
19-
{ ".ttf", "application/x-font-ttf" },
20-
{ ".otf", "application/x-font-opentype" },
21-
{ ".woff", "application/font-woff" },
22-
{ ".woff2", "application/font-woff2" },
23-
{ ".eot", "application/vnd.ms-fontobject" },
24-
{ ".sfnt", "application/font-sfnt" },
25-
{ ".xml", "text/xml" },
26-
{ ".pdf", "application/pdf" },
27-
{ ".zip", "application/zip" },
28-
{ ".gz", "application/x-gzip" },
29-
{ ".appcache", "text/cache-manifest" },
30-
{ "", "application/octet-stream" } };
7+
using namespace mime;
318

329
class FunctionRequestHandler : public RequestHandler {
3310
public:
@@ -124,10 +101,10 @@ class StaticRequestHandler : public RequestHandler {
124101

125102
// 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
126103
// if you point the the path to gzip you will serve the gzip as content type "application/x-gzip", not text or javascript etc...
127-
if (!path.endsWith(".gz") && !_fs.exists(path)) {
128-
String pathWithGz = path + ".gz";
104+
if (!path.endsWith(mimeTable[gz].endsWith) && !_fs.exists(path)) {
105+
String pathWithGz = path + mimeTable[gz].endsWith;
129106
if(_fs.exists(pathWithGz))
130-
path += ".gz";
107+
path += mimeTable[gz].endsWith;
131108
}
132109

133110
File f = _fs.open(path, "r");
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "mimetable.h"
2+
#include "pgmspace.h"
3+
4+
namespace mime
5+
{
6+
7+
// Table of extension->MIME strings stored in PROGMEM, needs to be global due to GCC section typing rules
8+
const Entry mimeTable[maxType] ICACHE_RODATA_ATTR =
9+
{
10+
{ ".html", "text/html" },
11+
{ ".htm", "text/html" },
12+
{ ".css", "text/css" },
13+
{ ".txt", "text/plain" },
14+
{ ".js", "application/javascript" },
15+
{ ".json", "application/json" },
16+
{ ".png", "image/png" },
17+
{ ".gif", "image/gif" },
18+
{ ".jpg", "image/jpeg" },
19+
{ ".ico", "image/x-icon" },
20+
{ ".svg", "image/svg+xml" },
21+
{ ".ttf", "application/x-font-ttf" },
22+
{ ".otf", "application/x-font-opentype" },
23+
{ ".woff", "application/font-woff" },
24+
{ ".woff2", "application/font-woff2" },
25+
{ ".eot", "application/vnd.ms-fontobject" },
26+
{ ".sfnt", "application/font-sfnt" },
27+
{ ".xml", "text/xml" },
28+
{ ".pdf", "application/pdf" },
29+
{ ".zip", "application/zip" },
30+
{ ".gz", "application/x-gzip" },
31+
{ ".appcache", "text/cache-manifest" },
32+
{ "", "application/octet-stream" }
33+
};
34+
35+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#ifndef __MIMETABLE_H__
2+
#define __MIMETABLE_H__
3+
4+
5+
namespace mime
6+
{
7+
8+
enum type
9+
{
10+
html,
11+
htm,
12+
css,
13+
txt,
14+
js,
15+
json,
16+
png,
17+
gif,
18+
jpg,
19+
ico,
20+
svg,
21+
ttf,
22+
otf,
23+
woff,
24+
woff2,
25+
eot,
26+
sfnt,
27+
xml,
28+
pdf,
29+
zip,
30+
gz,
31+
appcache,
32+
none,
33+
maxType
34+
};
35+
36+
struct Entry
37+
{
38+
const char endsWith[16];
39+
const char mimeType[32];
40+
};
41+
42+
43+
extern const Entry mimeTable[maxType];
44+
}
45+
46+
47+
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.