Single instance HTTP Server using WiFly Interface.

Dependents:   WiFlyHTTPServerSample MultiThreadingHTTPServer

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPRequestHandler.cpp Source File

HTTPRequestHandler.cpp

00001 /* HTTPRequestHandler.cpp */
00002 #include "mbed.h"
00003 #include "HTTPRequestHandler.h"
00004 #include <ctype.h>
00005 #include "Wifly.h"
00006 
00007 //#define DEBUG
00008 #include "debug.h"
00009 
00010 static char buffer[128];
00011 
00012 //const char hdrConClose[] = "Connection: Keep-Alive\r\n";
00013 
00014 const char hdrStandard[] = "DNT: 1\r\n"
00015                             "MaxAge: 0\r\n"
00016                             "Connection: Keep-Alive\r\n"
00017                             "Content-Type: text/html\r\n"
00018                             "Server: mbed embedded\r\n"
00019                             "Accessible: 1\r\n"
00020                             "\r\n";
00021 
00022 
00023 static int _stricmp(const char* a, const char* b)
00024 {
00025     int la = strlen(a);
00026     int lb = strlen(b);
00027     for (int i = 0 ; i < min(la, lb) ; i++) {
00028         if (tolower((int)a[i]) != tolower((int)b[i]))
00029             return i;
00030     }
00031     return 0;
00032 }
00033 
00034 
00035 static const struct mapping_t {
00036     const char* key;
00037     const char* value;
00038 } fileTypeMapping[]  = {
00039         {".gif", "Content-Type: image/gif\r\n"   },
00040     {".jpg", "Content-Type: image/jpeg\r\n"  },
00041     {".jpeg","Content-Type: image/jpeg\r\n"  },
00042     {".ico", "Content-Type: image/x-icon\r\n"},
00043     {".png", "Content-Type: image/png\r\n"   },
00044     {".zip", "Content-Type: image/zip\r\n"   },
00045     {".gz",  "Content-Type: image/gz\r\n"    },
00046     {".tar", "Content-Type: image/tar\r\n"   },
00047     {".txt", "Content-Type: plain/text\r\n"  },
00048     {".pdf", "Content-Type: application/pdf\r\n" },
00049     {".htm", "Content-Type: text/html\r\n"   },
00050     {".html","Content-Type: text/html\r\n"   },
00051     {".js", "Content-Type: text/javascript\r\n"}};
00052     
00053 HTTPRequestHandler::HTTPRequestHandler(HTTPConnection::HTTPMessage& Msg)
00054     : msg(Msg)
00055 {
00056     msg = Msg;
00057 
00058 }
00059 
00060 HTTPRequestHandler::~HTTPRequestHandler()
00061 {
00062 }
00063 
00064 void HTTPRequestHandler::getStandardHeaders(HTTPHeaders& header, const char* fext)
00065 {
00066     header.clear();
00067     header["DNT"] = "1";
00068     header["MaxAge"] = "0";
00069     header["Connection"] = "Keep-Alive";
00070     header["Server"] = "mbed Embedded";
00071     header["Accessible"] = "1";
00072     if (fext == NULL)
00073         header["Content-Type"] = "text/html";
00074     else {
00075         for (int i = 0 ; i < sizeof(fileTypeMapping)/sizeof(struct mapping_t) ;i++) {
00076             if (_stricmp(fileTypeMapping[i].key, fext) == 0) {
00077                 header["Content-Type"] = fileTypeMapping[i].value;
00078                 break;
00079             }
00080         }
00081     }
00082 }
00083 
00084 void HTTPRequestHandler::handleRequest()
00085 {
00086     int err = 0;
00087     
00088     switch (msg.request) {
00089         case HTTP_RT_GET:
00090             INFO("Dispatching GET Request.");
00091             err = handleGetRequest();
00092             break;
00093             
00094         case HTTP_RT_POST:
00095             INFO("Dispatching POST request.");
00096             err = handlePostRequest();
00097             break;
00098             
00099         case HTTP_RT_PUT:
00100             INFO("Dispatching PUT request.");
00101             err = handlePutRequest();
00102             break;
00103             
00104         default:
00105             INFO("Error in handleRequest, unhandled request type.");
00106             err = HTTP_NotImplemented;
00107             break;
00108     }
00109     
00110     //  if any of these functions returns a negative number, call the error handler
00111     if (err > 0) {
00112         handleError(err);
00113     }        
00114 }
00115 
00116 static const char* szErrorPage = "<HTML><HEAD><META content=\"text/html\" http-equiv=Content-Type></HEAD><BODY><h1>Error %d</h1><P>HTTPServer Error<P></BODY></HTML>\r\n\r\n";
00117 
00118 void HTTPRequestHandler::handleError(int errorCode, HTTPHeaders* header)
00119 {
00120     INFO("Handling error !");
00121     sprintf(buffer,"HTTP/1.1 %d Error\r\n", errorCode);
00122     Wifly::getInstance()->sendData(buffer, strlen(buffer));
00123     sprintf(buffer, "Content-Length: %d\r\n", strlen(szErrorPage));
00124     Wifly::getInstance()->sendData(buffer, strlen(buffer));
00125     if (header == NULL) {
00126         sprintf(buffer, "Content-Type: text/html\r\nServer: mbed embedded\r\n\n\r");
00127         Wifly::getInstance()->sendData(buffer, strlen(buffer));
00128     }
00129     else {
00130         for ( map<const char*, const char*>::iterator cIter = header->begin() ; cIter != header->end() ; cIter ++) {
00131             Wifly::getInstance()->sendData((char*)cIter->first, strlen(cIter->first));
00132             Wifly::getInstance()->sendData(": ", 2);
00133             Wifly::getInstance()->sendData((char*)cIter->second, strlen(cIter->second));
00134             Wifly::getInstance()->sendData("\r\n",2);
00135         }
00136         Wifly::getInstance()->sendData("\r\n",2);
00137     }
00138     Wifly::getInstance()->sendData((char*)szErrorPage, strlen(szErrorPage));
00139 }
00140 
00141 
00142 void HTTPRequestHandler::startResponse(int returnCode, long nLen, HTTPHeaders* header)
00143 {
00144     INFO("Starting response (%ld bytes in total)!", nLen);
00145     sprintf(buffer, "HTTP/1.1 %d OK\r\n", returnCode);
00146     Wifly::getInstance()->sendData(buffer, strlen(buffer));
00147     sprintf(buffer, "Content-Length: %ld\r\n", nLen);    //  Add 2 chars for the terminating CR+LF
00148     Wifly::getInstance()->sendData(buffer, strlen(buffer));
00149     if (header == NULL) {
00150             Wifly::getInstance()->sendData((char*)hdrStandard, strlen(hdrStandard));
00151     }
00152     else {
00153         for ( map<const char*, const char*>::iterator cIter = header->begin() ; cIter != header->end() ; cIter ++) {
00154             Wifly::getInstance()->sendData((char*)cIter->first, strlen(cIter->first));
00155             Wifly::getInstance()->sendData(": ", 2);
00156             Wifly::getInstance()->sendData((char*)cIter->second, strlen(cIter->second));
00157             Wifly::getInstance()->sendData("\r\n\r\n",2);
00158         }
00159         Wifly::getInstance()->sendData("\r\n", 2);
00160     }
00161     //  other content must be sent using the 'processResponse' function
00162 }
00163 
00164 void HTTPRequestHandler::processResponse(int nLen, char* body)
00165 {
00166     INFO("Processing Response (%d bytes)!\n",nLen);
00167     Wifly::getInstance()->sendData(body, nLen);
00168 }
00169 
00170 void HTTPRequestHandler::endResponse()
00171 {
00172 //    INFO("Ending Response !");
00173 //    Wifly::getInstance()->sendData("\r\n\r\n", 4);
00174 //    Wifly::getInstance()->cmdMode();
00175 //    Wifly::getInstance()->sendData("close\r", 6);
00176 //    Thread::wait(250);
00177 //    Wifly::getInstance()->exit();
00178 }