Single instance HTTP Server using new Ethernet Interface. Blocking mode only; this improved stability, but the HTTP server must be started from a separate thread.

Dependents:   SmartLight

Fork of HTTPServer by Henry Leinen

Committer:
leihen
Date:
Sat Aug 17 16:17:55 2013 +0000
Revision:
16:cc3f5c53d0d5
Parent:
13:aa5338a5e452
Child:
17:d7186c696729
- Removed old Debug message helper macros and replaced them with new hl_debug.h macros.
; - Renamed debug.h file to hl_debug.h to avoid conflict with EthernetInterface.
; - Fixed incorrectly used debug macro where an ERR was used instead of an INFO

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leihen 1:6b7472d5e9ee 1 /* HTTPRequestHandler.cpp */
leihen 1:6b7472d5e9ee 2 #include "mbed.h"
leihen 1:6b7472d5e9ee 3 #include "HTTPRequestHandler.h"
leihen 13:aa5338a5e452 4 #define DEBUG
leihen 16:cc3f5c53d0d5 5 #include "hl_debug.h"
leihen 12:ba81cc117fb6 6 #include <ctype.h>
leihen 1:6b7472d5e9ee 7
leihen 1:6b7472d5e9ee 8
leihen 3:d6224049b3bf 9 static char buffer[128];
leihen 3:d6224049b3bf 10
leihen 11:3943841e1798 11
leihen 13:aa5338a5e452 12 const char hdrStandard[] = "DNT: 1\r\n"
leihen 13:aa5338a5e452 13 "MaxAge: 0\r\n"
leihen 13:aa5338a5e452 14 "Connection: Keep-Alive\r\n"
leihen 13:aa5338a5e452 15 "Content-Type: text/html\r\n"
leihen 13:aa5338a5e452 16 "Server: mbed embedded\r\n"
leihen 13:aa5338a5e452 17 "Accessible: 1\r\n"
leihen 13:aa5338a5e452 18 "\r\n";
leihen 11:3943841e1798 19
leihen 12:ba81cc117fb6 20
leihen 12:ba81cc117fb6 21 static int _stricmp(const char* a, const char* b)
leihen 12:ba81cc117fb6 22 {
leihen 12:ba81cc117fb6 23 int la = strlen(a);
leihen 12:ba81cc117fb6 24 int lb = strlen(b);
leihen 12:ba81cc117fb6 25 for (int i = 0 ; i < min(la, lb) ; i++) {
leihen 12:ba81cc117fb6 26 if (tolower((int)a[i]) != tolower((int)b[i]))
leihen 12:ba81cc117fb6 27 return i;
leihen 12:ba81cc117fb6 28 }
leihen 12:ba81cc117fb6 29 return 0;
leihen 12:ba81cc117fb6 30 }
leihen 12:ba81cc117fb6 31
leihen 12:ba81cc117fb6 32
leihen 12:ba81cc117fb6 33 static const struct mapping_t {
leihen 12:ba81cc117fb6 34 const char* key;
leihen 12:ba81cc117fb6 35 const char* value;
leihen 12:ba81cc117fb6 36 } fileTypeMapping[] = {
leihen 12:ba81cc117fb6 37 {".gif", "Content-Type: image/gif\r\n" },
leihen 12:ba81cc117fb6 38 {".jpg", "Content-Type: image/jpeg\r\n" },
leihen 12:ba81cc117fb6 39 {".jpeg","Content-Type: image/jpeg\r\n" },
leihen 12:ba81cc117fb6 40 {".ico", "Content-Type: image/x-icon\r\n"},
leihen 12:ba81cc117fb6 41 {".png", "Content-Type: image/png\r\n" },
leihen 12:ba81cc117fb6 42 {".zip", "Content-Type: image/zip\r\n" },
leihen 12:ba81cc117fb6 43 {".gz", "Content-Type: image/gz\r\n" },
leihen 12:ba81cc117fb6 44 {".tar", "Content-Type: image/tar\r\n" },
leihen 12:ba81cc117fb6 45 {".txt", "Content-Type: plain/text\r\n" },
leihen 12:ba81cc117fb6 46 {".pdf", "Content-Type: application/pdf\r\n" },
leihen 12:ba81cc117fb6 47 {".htm", "Content-Type: text/html\r\n" },
leihen 13:aa5338a5e452 48 {".html","Content-Type: text/html\r\n" },
leihen 13:aa5338a5e452 49 {".css", "Content-Type: text/css\r\n" },
leihen 13:aa5338a5e452 50 {".js", "Content-Type: text/javascript\r\n"}};
leihen 12:ba81cc117fb6 51
leihen 3:d6224049b3bf 52 HTTPRequestHandler::HTTPRequestHandler(HTTPConnection::HTTPMessage& Msg, TCPSocketConnection& Tcp)
leihen 3:d6224049b3bf 53 : msg(Msg), tcp(Tcp)
leihen 1:6b7472d5e9ee 54 {
leihen 3:d6224049b3bf 55 msg = Msg;
leihen 3:d6224049b3bf 56 tcp = Tcp;
leihen 12:ba81cc117fb6 57
leihen 1:6b7472d5e9ee 58 }
leihen 1:6b7472d5e9ee 59
leihen 1:6b7472d5e9ee 60 HTTPRequestHandler::~HTTPRequestHandler()
leihen 1:6b7472d5e9ee 61 {
leihen 3:d6224049b3bf 62 }
leihen 3:d6224049b3bf 63
leihen 12:ba81cc117fb6 64 void HTTPRequestHandler::getStandardHeaders(HTTPHeaders& header, const char* fext)
leihen 12:ba81cc117fb6 65 {
leihen 12:ba81cc117fb6 66 header.clear();
leihen 12:ba81cc117fb6 67 header["DNT"] = "1";
leihen 12:ba81cc117fb6 68 header["MaxAge"] = "0";
leihen 12:ba81cc117fb6 69 header["Connection"] = "Keep-Alive";
leihen 12:ba81cc117fb6 70 header["Server"] = "mbed Embedded";
leihen 12:ba81cc117fb6 71 if (fext == NULL)
leihen 12:ba81cc117fb6 72 header["Content-Type"] = "text/html";
leihen 12:ba81cc117fb6 73 else {
leihen 12:ba81cc117fb6 74 for (int i = 0 ; i < sizeof(fileTypeMapping)/sizeof(struct mapping_t) ;i++) {
leihen 12:ba81cc117fb6 75 if (_stricmp(fileTypeMapping[i].key, fext) == 0) {
leihen 12:ba81cc117fb6 76 header["Content-Type"] = fileTypeMapping[i].value;
leihen 12:ba81cc117fb6 77 break;
leihen 12:ba81cc117fb6 78 }
leihen 12:ba81cc117fb6 79 }
leihen 12:ba81cc117fb6 80 }
leihen 12:ba81cc117fb6 81 }
leihen 12:ba81cc117fb6 82
leihen 3:d6224049b3bf 83 void HTTPRequestHandler::handleRequest()
leihen 3:d6224049b3bf 84 {
leihen 3:d6224049b3bf 85 int err = 0;
leihen 3:d6224049b3bf 86
leihen 3:d6224049b3bf 87 switch (msg.request) {
leihen 3:d6224049b3bf 88 case HTTP_RT_GET:
leihen 3:d6224049b3bf 89 INFO("Dispatching GET Request.");
leihen 3:d6224049b3bf 90 err = handleGetRequest();
leihen 3:d6224049b3bf 91 break;
leihen 3:d6224049b3bf 92
leihen 4:d065642c32cc 93 case HTTP_RT_POST:
leihen 4:d065642c32cc 94 INFO("Dispatching POST request.");
leihen 4:d065642c32cc 95 err = handlePostRequest();
leihen 4:d065642c32cc 96 break;
leihen 3:d6224049b3bf 97
leihen 4:d065642c32cc 98 case HTTP_RT_PUT:
leihen 4:d065642c32cc 99 INFO("Dispatching PUT request.");
leihen 4:d065642c32cc 100 err = handlePutRequest();
leihen 4:d065642c32cc 101 break;
leihen 3:d6224049b3bf 102
leihen 3:d6224049b3bf 103 default:
leihen 3:d6224049b3bf 104 INFO("Error in handleRequest, unhandled request type.");
leihen 9:c2a1462b9b71 105 err = HTTP_NotImplemented;
leihen 3:d6224049b3bf 106 break;
leihen 3:d6224049b3bf 107 }
leihen 3:d6224049b3bf 108
leihen 3:d6224049b3bf 109 // if any of these functions returns a negative number, call the error handler
leihen 3:d6224049b3bf 110 if (err > 0) {
leihen 3:d6224049b3bf 111 handleError(err);
leihen 3:d6224049b3bf 112 }
leihen 3:d6224049b3bf 113 }
leihen 3:d6224049b3bf 114
leihen 13:aa5338a5e452 115 static const char* szErrorPage = "<HTML><HEAD><META content=\"text/html\" http-equiv=Content-Type></HEAD><BODY><h1>Error</h1><P>HTTPServer Error<P></BODY></HTML>\r\n\r\n";
leihen 3:d6224049b3bf 116
leihen 3:d6224049b3bf 117 void HTTPRequestHandler::handleError(int errorCode, HTTPHeaders* header)
leihen 3:d6224049b3bf 118 {
leihen 3:d6224049b3bf 119 INFO("Handling error !");
leihen 13:aa5338a5e452 120 tcp.set_blocking(false, 1500);
leihen 11:3943841e1798 121 sprintf(buffer,"HTTP/1.1 %d Error\r\n", errorCode);
leihen 3:d6224049b3bf 122 tcp.send(buffer, strlen(buffer));
leihen 3:d6224049b3bf 123 sprintf(buffer, "Content-Length: %d\r\n", strlen(szErrorPage));
leihen 3:d6224049b3bf 124 tcp.send(buffer, strlen(buffer));
leihen 3:d6224049b3bf 125 if (header == NULL) {
leihen 3:d6224049b3bf 126 sprintf(buffer, "Content-Type: text/html\r\nServer: mbed embedded\r\n\n\r");
leihen 3:d6224049b3bf 127 tcp.send(buffer, strlen(buffer));
leihen 3:d6224049b3bf 128 }
leihen 3:d6224049b3bf 129 else {
leihen 3:d6224049b3bf 130 for ( map<const char*, const char*>::iterator cIter = header->begin() ; cIter != header->end() ; cIter ++) {
leihen 3:d6224049b3bf 131 tcp.send((char*)cIter->first, strlen(cIter->first));
leihen 3:d6224049b3bf 132 tcp.send(": ", 2);
leihen 3:d6224049b3bf 133 tcp.send((char*)cIter->second, strlen(cIter->second));
leihen 3:d6224049b3bf 134 tcp.send("\r\n",2);
leihen 3:d6224049b3bf 135 }
leihen 3:d6224049b3bf 136 tcp.send("\r\n",2);
leihen 3:d6224049b3bf 137 }
leihen 3:d6224049b3bf 138 tcp.send((char*)szErrorPage, strlen(szErrorPage));
leihen 3:d6224049b3bf 139 }
leihen 3:d6224049b3bf 140
leihen 3:d6224049b3bf 141
leihen 7:cb7fec1265b5 142 void HTTPRequestHandler::startResponse(int returnCode, long nLen, HTTPHeaders* header)
leihen 3:d6224049b3bf 143 {
leihen 7:cb7fec1265b5 144 INFO("Starting response (%ld bytes in total)!", nLen);
leihen 13:aa5338a5e452 145 tcp.set_blocking(false, 1500);
leihen 11:3943841e1798 146 sprintf(buffer, "HTTP/1.1 %d OK\r\n", returnCode);
leihen 13:aa5338a5e452 147 tcp.send(buffer, strlen(buffer));
leihen 7:cb7fec1265b5 148 sprintf(buffer, "Content-Length: %ld\r\n", nLen); // Add 2 chars for the terminating CR+LF
leihen 13:aa5338a5e452 149 tcp.send(buffer, strlen(buffer));
leihen 13:aa5338a5e452 150 INFO("Sending standard headers !");
leihen 3:d6224049b3bf 151 if (header == NULL) {
leihen 13:aa5338a5e452 152 tcp.send_all((char*)hdrStandard, strlen(hdrStandard));
leihen 3:d6224049b3bf 153 }
leihen 3:d6224049b3bf 154 else {
leihen 3:d6224049b3bf 155 for ( map<const char*, const char*>::iterator cIter = header->begin() ; cIter != header->end() ; cIter ++) {
leihen 13:aa5338a5e452 156 tcp.send_all((char*)cIter->first, strlen(cIter->first));
leihen 13:aa5338a5e452 157 tcp.send_all(": ", 2);
leihen 13:aa5338a5e452 158 tcp.send_all((char*)cIter->second, strlen(cIter->second));
leihen 13:aa5338a5e452 159 tcp.send_all("\r\n\r\n",2);
leihen 3:d6224049b3bf 160 }
leihen 11:3943841e1798 161 tcp.send_all("\r\n", 2);
leihen 3:d6224049b3bf 162 }
leihen 13:aa5338a5e452 163 INFO("Proceeding !");
leihen 3:d6224049b3bf 164 // other content must be sent using the 'processResponse' function
leihen 3:d6224049b3bf 165 }
leihen 3:d6224049b3bf 166
leihen 3:d6224049b3bf 167 void HTTPRequestHandler::processResponse(int nLen, char* body)
leihen 3:d6224049b3bf 168 {
leihen 7:cb7fec1265b5 169 INFO("Processing Response (%d bytes)!\n",nLen);
leihen 11:3943841e1798 170 tcp.send_all(body, nLen);
leihen 3:d6224049b3bf 171 }
leihen 3:d6224049b3bf 172
leihen 3:d6224049b3bf 173 void HTTPRequestHandler::endResponse()
leihen 3:d6224049b3bf 174 {
leihen 3:d6224049b3bf 175 INFO("Ending Response !");
leihen 3:d6224049b3bf 176 }