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.
Fork of HTTPServer by
HTTPRequestHandler.cpp@16:cc3f5c53d0d5, 2013-08-17 (annotated)
- 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?
User | Revision | Line number | New 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 | } |