14
« on: July 01, 2015, 12:18:49 PM »
Hello,
i am currently working on a project which has very limited storage in the SPI-flash but still needs a "fancy" website with a lot of javascript.
As javascript libraries are often over hundred kilobytes in size they waste space needed for other things.
I remembered reading about gzip compression for webservers but always thought the server would need to compress the files before sending them to the client.
After stumbling across another article it became clear to me that this is not the case and the only thing needed is an entry in the HTTP-header to inform the client that the data is compressed.
With this in mind I modified the HTTP-stack to fill in the needed information:
#if defined SUPPORT_GZIP_SERVING
static unsigned short fnAddContentTypeGZIP(CHAR *ptrBuffer, const CHAR *ptrType)
{
CHAR *ptrContent = ptrBuffer;
ptrContent = uStrcpy(ptrContent, "Content-Type: ");
ptrContent = uStrcpy(ptrContent, ptrType);
ptrContent = uStrcpy(ptrContent, "\r\n");
ptrContent = uStrcpy(ptrContent, "Content-Encoding: gzip\r\n\r\n");
return ((ptrContent - (CHAR *)ptrBuffer) - 2);
}
#endif
static unsigned short fnAddMimeContent(unsigned char *ptrBuffer, unsigned char ucMimeType)
{
switch (ucMimeType) {
#if defined MIME_TXT
case MIME_TXT:
return (fnAddContentType((CHAR *)ptrBuffer, "text/plain"));
#endif
#if defined MIME_CSS
case MIME_CSS:
return (fnAddContentType((CHAR *)ptrBuffer, "text/css"));
#endif
#if defined MIME_JAVA_SCRIPT
case MIME_JAVA_SCRIPT:
return (fnAddContentType((CHAR *)ptrBuffer, "application/javascript"));
#endif
#if defined MIME_PNG
case MIME_PNG:
return (fnAddContentType((CHAR *)ptrBuffer, "image/png"));
#endif
#if defined MIME_JPG
case MIME_JPG:
return (fnAddContentType((CHAR *)ptrBuffer, "image/jpg"));
#endif
#if defined MIME_BMP
case MIME_BMP:
return (fnAddContentType((CHAR *)ptrBuffer, "image/bmp"));
#endif
#if defined MIME_GIF
case MIME_GIF:
return (fnAddContentType((CHAR *)ptrBuffer, "image/gif"));
#endif
#if defined SUPPORT_GZIP_SERVING
case MIME_JAVA_GZIP:
return (fnAddContentTypeGZIP((CHAR *)ptrBuffer, "application/javascript"));
break;
case MIME_CSS_GZIP:
return (fnAddContentTypeGZIP((CHAR *)ptrBuffer, "text/css"));
break;
case MIME_HTML_GZIP:
return (fnAddContentTypeGZIP((CHAR *)ptrBuffer, "text/html"));
break;
#endif
default:
return 0;
}
}
#endif
The function fnAddContentTypeGZIP adds the mime-type and an additional string "Content-Encoding: gzip" to the HTTP-header.
The new defines e.g. MIME_JAVA_GZIP have to be defined at the end of config.h for this to work. I added custom file extensions like jgz for compressed java and cgz for compressed css:
#if defined OPSYS_CONFIG // this is only set in the hardware module
#if defined ETH_INTERFACE // if we support Ethernet we define some constants for its (TCP/IP) use
const unsigned char cucNullMACIP[MAC_LENGTH] = { 0, 0, 0, 0, 0, 0 };
const unsigned char cucBroadcast[MAC_LENGTH] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; // used also for broadcast IP
#endif
#if defined SUPPORT_MIME_IDENTIFIER
const CHAR *cMimeTable[] = { // keep the ordering in the table to match the MIME type defines below!!
(const CHAR *)"HTM", // HTML file - will be interpreted by web server
(const CHAR *)"JPG", // JPG image
(const CHAR *)"GIF", // GIF image
(const CHAR *)"CSS", // CSS Cascading Style Sheets
(const CHAR *)"JS", // Java script
(const CHAR *)"BIN", // binary data file
(const CHAR *)"TXT", // text data file
(const CHAR *)"ICO", // icon
(const CHAR *)"BMP", // BMP image
#ifdef SUPPORT_GZIP_SERVING
(const CHAR *)"JGZ", // gzipped javascript
(const CHAR *)"CGZ", // gzipped css
(const CHAR *)"HGZ", // gzipped html
#endif
(const CHAR *)"???", // all other types will be displayed as unknown
};
#endif
#endif
// File type identifiers
//
#define MIME_HTML 0 // this and any lower types will be parsed by the web server
#define MIME_JPG 1
#define MIME_GIF 2
#define MIME_CSS 3
#define MIME_JAVA_SCRIPT 4
#define MIME_BINARY 5
#define MIME_TXT 6
#define MIME_ICON 7
#define MIME_BMP 8
#ifdef SUPPORT_GZIP_SERVING
#define MIME_JAVA_GZIP 9
#define MIME_CSS_GZIP 10
#define MIME_HTML_GZIP 11
#define UNKNOWN_MIME 12 // this entry is needed to terminate the list
#else
#define UNKNOWN_MIME 9 // this entry is needed to terminate the list
#endif
The new mime types get set when you write a file with one of the extensions to your storage.
I was able to get the filesize down to a fifth of the original so this really speeds up things. (179k -> 31k)
The only caveat I could find is that the original insert mechanisms with the pound-sign will not work when using a compressed HTML-file but as I am not using them anymore it doesn't really matter to me.
Maybe this will help others too when dealing with limited storage.
Kind Regards
Paul