martonmiklos: Add GZIP compression for static files
This commit is contained in:
@@ -38,6 +38,20 @@ EXTRA_INCDIR = include \
|
|||||||
# libraries used in this project, mainly provided by the SDK
|
# libraries used in this project, mainly provided by the SDK
|
||||||
LIBS = c gcc hal phy pp net80211 wpa main lwip
|
LIBS = c gcc hal phy pp net80211 wpa main lwip
|
||||||
|
|
||||||
|
# If GZIP_COMPRESSION is set to "yes" then the static css, js, and html files will be compressed with gzip before added to the espfs image
|
||||||
|
# and will be served with gzip Content-Encoding header.
|
||||||
|
# This could speed up the downloading of these files, but might break compatibility with older web browsers not supporting gzip encoding
|
||||||
|
# because Accept-Encoding is simply ignored. Enable this option if you have large static files to serve (for e.g. JQuery, Twitter bootstrap)
|
||||||
|
# By default only js, css and html files are compressed.
|
||||||
|
# If you have text based static files with different extensions what you want to serve compressed then you will need to add the extension to the following places:
|
||||||
|
# - Add the extension to this Makefile at the webpages.espfs target to the find command
|
||||||
|
# - Add the extension to the gzippedFileTypes array in the user/httpd.c file
|
||||||
|
#
|
||||||
|
# Adding JPG or PNG files (and any other compressed formats) is not recommended, because GZIP compression does not works effectively on compressed files.
|
||||||
|
|
||||||
|
#Static gzipping is disabled by default.
|
||||||
|
#GZIP_COMPRESSION = "yes"
|
||||||
|
|
||||||
# compiler flags using during compilation of source files
|
# compiler flags using during compilation of source files
|
||||||
CFLAGS = -Os -ggdb -std=c99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
|
CFLAGS = -Os -ggdb -std=c99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
|
||||||
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \
|
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \
|
||||||
@@ -101,6 +115,10 @@ Q := @
|
|||||||
vecho := @echo
|
vecho := @echo
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(GZIP_COMPRESSION),"yes")
|
||||||
|
CFLAGS += -DGZIP_COMPRESSION
|
||||||
|
endif
|
||||||
|
|
||||||
vpath %.c $(SRC_DIR)
|
vpath %.c $(SRC_DIR)
|
||||||
|
|
||||||
define compile-objects
|
define compile-objects
|
||||||
@@ -144,8 +162,15 @@ flash: $(FW_FILE_1) $(FW_FILE_2)
|
|||||||
$(Q) $(ESPTOOL) -cp $(ESPPORT) -cb $(ESPBAUD) -ca 0x40000 -cf firmware/0x40000.bin -v
|
$(Q) $(ESPTOOL) -cp $(ESPPORT) -cb $(ESPBAUD) -ca 0x40000 -cf firmware/0x40000.bin -v
|
||||||
|
|
||||||
webpages.espfs: html/ html/wifi/ mkespfsimage/mkespfsimage
|
webpages.espfs: html/ html/wifi/ mkespfsimage/mkespfsimage
|
||||||
cd html; find . | ../mkespfsimage/mkespfsimage > ../webpages.espfs; cd ..
|
ifeq ($(GZIP_COMPRESSION),"yes")
|
||||||
|
$(Q) rm -rf html_compressed;
|
||||||
|
$(Q) cp -r html html_compressed;
|
||||||
|
$(Q) cd html_compressed; find . -type f -regex ".*/.*\.\(html\|css\|js\)" -exec sh -c "gzip -n {}; mv {}.gz {}" \;; cd ..;
|
||||||
|
$(Q) cd html_compressed; find | ../mkespfsimage/mkespfsimage > ../webpages.espfs; cd ..;
|
||||||
|
$(Q) awk "BEGIN {printf \"GZIP compression ratio was: %.2f%%\\n\", (`du -b -s html_compressed/ | sed 's/\([0-9]*\).*/\1/'`/`du -b -s html/ | sed 's/\([0-9]*\).*/\1/'`)*100}"
|
||||||
|
else
|
||||||
|
$(Q) cd html; find | ../mkespfsimage/mkespfsimage > ../webpages.espfs; cd ..
|
||||||
|
endif
|
||||||
mkespfsimage/mkespfsimage: mkespfsimage/
|
mkespfsimage/mkespfsimage: mkespfsimage/
|
||||||
make -C mkespfsimage
|
make -C mkespfsimage
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,19 @@ static const MimeMap mimeTypes[]={
|
|||||||
{NULL, "text/html"}, //default value
|
{NULL, "text/html"}, //default value
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The static files with the following extensions from the HTML folder will be compressed and served with GZIP compression
|
||||||
|
// Add any other file types you want compressed here (and don't forget to modify the Makefile too)
|
||||||
|
#ifdef GZIP_COMPRESSION
|
||||||
|
static const char * gzippedFileTypes[] = {
|
||||||
|
"js",
|
||||||
|
"html",
|
||||||
|
"css",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char gzipNonSupportedMessage[] = "<html><head></head><body>Your browser does not accept gzip-compressed data.</body></html>";
|
||||||
|
#endif
|
||||||
|
|
||||||
//Returns a static char* to a mime type for a given url to a file.
|
//Returns a static char* to a mime type for a given url to a file.
|
||||||
const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
|
const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
|
||||||
int i=0;
|
int i=0;
|
||||||
@@ -88,6 +101,39 @@ const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
|
|||||||
return mimeTypes[i].mimetype;
|
return mimeTypes[i].mimetype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GZIP_COMPRESSION
|
||||||
|
//Sends Content-encoding header if the requested file was GZIP compressed
|
||||||
|
//If the client does not sent the Accept-encoding, send out a static html message.
|
||||||
|
const char* sendGZIPEncodingIfNeeded(HttpdConnData *connData) {
|
||||||
|
int i=0;
|
||||||
|
char acceptEncodingBuffer[64];
|
||||||
|
//Go find the extension
|
||||||
|
char *ext=connData->url+(strlen(connData->url)-1);
|
||||||
|
while (ext!=connData->url && *ext!='.') ext--;
|
||||||
|
if (*ext=='.') ext++;
|
||||||
|
|
||||||
|
//ToDo: os_strcmp is case sensitive; we may want to do case-intensive matching here...
|
||||||
|
while (gzippedFileTypes[i]!=NULL) {
|
||||||
|
if (os_strcmp(ext, gzippedFileTypes[i])==0) {
|
||||||
|
//when serving gzipped files check the browser's "Accept-Encoding" header
|
||||||
|
//if the client does not advertises that he accepts GZIP send a warning message (telnet users for e.g.)
|
||||||
|
httpdGetHeader(connData, "Accept-Encoding", acceptEncodingBuffer, 64);
|
||||||
|
if (os_strstr(acceptEncodingBuffer, "gzip") == NULL) {
|
||||||
|
//No Accept-Encoding: gzip header present
|
||||||
|
return gzipNonSupportedMessage;
|
||||||
|
} else {
|
||||||
|
httpdHeader(connData, "Content-Encoding", "gzip");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//Looks up the connData info for a specific esp connection
|
//Looks up the connData info for a specific esp connection
|
||||||
static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) {
|
static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) {
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#define HTTPD_METHOD_GET 1
|
#define HTTPD_METHOD_GET 1
|
||||||
#define HTTPD_METHOD_POST 2
|
#define HTTPD_METHOD_POST 2
|
||||||
|
|
||||||
|
|
||||||
typedef struct HttpdPriv HttpdPriv;
|
typedef struct HttpdPriv HttpdPriv;
|
||||||
typedef struct HttpdConnData HttpdConnData;
|
typedef struct HttpdConnData HttpdConnData;
|
||||||
typedef struct HttpdPostData HttpdPostData;
|
typedef struct HttpdPostData HttpdPostData;
|
||||||
@@ -58,6 +59,9 @@ int httpdUrlDecode(char *val, int valLen, char *ret, int retLen);
|
|||||||
int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLen);
|
int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLen);
|
||||||
void ICACHE_FLASH_ATTR httpdInit(HttpdBuiltInUrl *fixedUrls, int port);
|
void ICACHE_FLASH_ATTR httpdInit(HttpdBuiltInUrl *fixedUrls, int port);
|
||||||
const char *httpdGetMimetype(char *url);
|
const char *httpdGetMimetype(char *url);
|
||||||
|
#ifdef GZIP_COMPRESSION
|
||||||
|
const char* sendGZIPEncodingIfNeeded(HttpdConnData *connData);
|
||||||
|
#endif
|
||||||
void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code);
|
void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code);
|
||||||
void ICACHE_FLASH_ATTR httpdHeader(HttpdConnData *conn, const char *field, const char *val);
|
void ICACHE_FLASH_ATTR httpdHeader(HttpdConnData *conn, const char *field, const char *val);
|
||||||
void ICACHE_FLASH_ATTR httpdEndHeaders(HttpdConnData *conn);
|
void ICACHE_FLASH_ATTR httpdEndHeaders(HttpdConnData *conn);
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData) {
|
|||||||
EspFsFile *file=connData->cgiData;
|
EspFsFile *file=connData->cgiData;
|
||||||
int len;
|
int len;
|
||||||
char buff[1024];
|
char buff[1024];
|
||||||
|
#ifdef GZIP_COMPRESSION
|
||||||
|
const char *gzipSendResult = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (connData->conn==NULL) {
|
if (connData->conn==NULL) {
|
||||||
//Connection aborted. Clean up.
|
//Connection aborted. Clean up.
|
||||||
@@ -47,6 +50,14 @@ int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData) {
|
|||||||
connData->cgiData=file;
|
connData->cgiData=file;
|
||||||
httpdStartResponse(connData, 200);
|
httpdStartResponse(connData, 200);
|
||||||
httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url));
|
httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url));
|
||||||
|
#ifdef GZIP_COMPRESSION
|
||||||
|
gzipSendResult = sendGZIPEncodingIfNeeded(connData);
|
||||||
|
if (gzipSendResult != NULL) {
|
||||||
|
httpdEndHeaders(connData);
|
||||||
|
httpdSend(connData, gzipSendResult, os_strlen(gzipSendResult));
|
||||||
|
return HTTPD_CGI_DONE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate");
|
httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate");
|
||||||
httpdEndHeaders(connData);
|
httpdEndHeaders(connData);
|
||||||
return HTTPD_CGI_MORE;
|
return HTTPD_CGI_MORE;
|
||||||
|
|||||||
Reference in New Issue
Block a user