Single instance HTTP Server using new Ethernet Interface with bug fix for URL arguments
Fork of HTTPServer by
HTTPRequestHandler.cpp@12:ba81cc117fb6, 2013-06-05 (annotated)
- Committer:
- leihen
- Date:
- Wed Jun 05 23:39:24 2013 +0000
- Revision:
- 12:ba81cc117fb6
- Parent:
- 11:3943841e1798
- Child:
- 13:aa5338a5e452
Improved throughput of data.
; fixed incorrect Header handling.
; Fixed Support for other FileSystem Handler
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 | 12:ba81cc117fb6 | 4 | #include <ctype.h> |
leihen | 1:6b7472d5e9ee | 5 | |
leihen | 11:3943841e1798 | 6 | #define _DEBUG 0 |
leihen | 6:fe661fa9d18a | 7 | |
leihen | 6:fe661fa9d18a | 8 | #if (_DEBUG && !defined(TARGET_LPC11U24)) |
leihen | 3:d6224049b3bf | 9 | #define INFO(x, ...) std::printf("[HTTPRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__); |
leihen | 3:d6224049b3bf | 10 | #define WARN(x, ...) std::printf("[HTTPRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__); |
leihen | 3:d6224049b3bf | 11 | #define ERR(x, ...) std::printf("[HTTPRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__); |
leihen | 3:d6224049b3bf | 12 | #else |
leihen | 3:d6224049b3bf | 13 | #define INFO(x, ...) |
leihen | 3:d6224049b3bf | 14 | #define WARN(x, ...) |
leihen | 3:d6224049b3bf | 15 | #define ERR(x, ...) |
leihen | 3:d6224049b3bf | 16 | #endif |
leihen | 1:6b7472d5e9ee | 17 | |
leihen | 3:d6224049b3bf | 18 | static char buffer[128]; |
leihen | 3:d6224049b3bf | 19 | |
leihen | 11:3943841e1798 | 20 | |
leihen | 11:3943841e1798 | 21 | const char hdrDNT[] = "DNT: 1\r\n"; |
leihen | 11:3943841e1798 | 22 | const char hdrMaxAge[] = "MaxAge: 0\r\n"; |
leihen | 11:3943841e1798 | 23 | const char hdrConClose[] = "Connection: Keep-Alive\r\n"; |
leihen | 12:ba81cc117fb6 | 24 | //const char hdrTrsfrEnc[] = "Transfer-Encoding: Chunked\r\n"; |
leihen | 11:3943841e1798 | 25 | const char hdrContent[] = "Content-Type: text/html\r\n"; |
leihen | 11:3943841e1798 | 26 | const char hdrServer[] = "Server: mbed embedded\r\n"; |
leihen | 11:3943841e1798 | 27 | const char hdrEndl[] = "\r\n"; |
leihen | 11:3943841e1798 | 28 | |
leihen | 12:ba81cc117fb6 | 29 | |
leihen | 12:ba81cc117fb6 | 30 | static int _stricmp(const char* a, const char* b) |
leihen | 12:ba81cc117fb6 | 31 | { |
leihen | 12:ba81cc117fb6 | 32 | int la = strlen(a); |
leihen | 12:ba81cc117fb6 | 33 | int lb = strlen(b); |
leihen | 12:ba81cc117fb6 | 34 | for (int i = 0 ; i < min(la, lb) ; i++) { |
leihen | 12:ba81cc117fb6 | 35 | if (tolower((int)a[i]) != tolower((int)b[i])) |
leihen | 12:ba81cc117fb6 | 36 | return i; |
leihen | 12:ba81cc117fb6 | 37 | } |
leihen | 12:ba81cc117fb6 | 38 | return 0; |
leihen | 12:ba81cc117fb6 | 39 | } |
leihen | 12:ba81cc117fb6 | 40 | |
leihen | 12:ba81cc117fb6 | 41 | |
leihen | 12:ba81cc117fb6 | 42 | static const struct mapping_t { |
leihen | 12:ba81cc117fb6 | 43 | const char* key; |
leihen | 12:ba81cc117fb6 | 44 | const char* value; |
leihen | 12:ba81cc117fb6 | 45 | } fileTypeMapping[] = { |
leihen | 12:ba81cc117fb6 | 46 | {".gif", "Content-Type: image/gif\r\n" }, |
leihen | 12:ba81cc117fb6 | 47 | {".jpg", "Content-Type: image/jpeg\r\n" }, |
leihen | 12:ba81cc117fb6 | 48 | {".jpeg","Content-Type: image/jpeg\r\n" }, |
leihen | 12:ba81cc117fb6 | 49 | {".ico", "Content-Type: image/x-icon\r\n"}, |
leihen | 12:ba81cc117fb6 | 50 | {".png", "Content-Type: image/png\r\n" }, |
leihen | 12:ba81cc117fb6 | 51 | {".zip", "Content-Type: image/zip\r\n" }, |
leihen | 12:ba81cc117fb6 | 52 | {".gz", "Content-Type: image/gz\r\n" }, |
leihen | 12:ba81cc117fb6 | 53 | {".tar", "Content-Type: image/tar\r\n" }, |
leihen | 12:ba81cc117fb6 | 54 | {".txt", "Content-Type: plain/text\r\n" }, |
leihen | 12:ba81cc117fb6 | 55 | {".pdf", "Content-Type: application/pdf\r\n" }, |
leihen | 12:ba81cc117fb6 | 56 | {".htm", "Content-Type: text/html\r\n" }, |
leihen | 12:ba81cc117fb6 | 57 | {".html","Content-Type: text/html\r\n" }}; |
leihen | 12:ba81cc117fb6 | 58 | |
leihen | 3:d6224049b3bf | 59 | HTTPRequestHandler::HTTPRequestHandler(HTTPConnection::HTTPMessage& Msg, TCPSocketConnection& Tcp) |
leihen | 3:d6224049b3bf | 60 | : msg(Msg), tcp(Tcp) |
leihen | 1:6b7472d5e9ee | 61 | { |
leihen | 3:d6224049b3bf | 62 | msg = Msg; |
leihen | 3:d6224049b3bf | 63 | tcp = Tcp; |
leihen | 12:ba81cc117fb6 | 64 | |
leihen | 1:6b7472d5e9ee | 65 | } |
leihen | 1:6b7472d5e9ee | 66 | |
leihen | 1:6b7472d5e9ee | 67 | HTTPRequestHandler::~HTTPRequestHandler() |
leihen | 1:6b7472d5e9ee | 68 | { |
leihen | 3:d6224049b3bf | 69 | } |
leihen | 3:d6224049b3bf | 70 | |
leihen | 12:ba81cc117fb6 | 71 | void HTTPRequestHandler::getStandardHeaders(HTTPHeaders& header, const char* fext) |
leihen | 12:ba81cc117fb6 | 72 | { |
leihen | 12:ba81cc117fb6 | 73 | header.clear(); |
leihen | 12:ba81cc117fb6 | 74 | header["DNT"] = "1"; |
leihen | 12:ba81cc117fb6 | 75 | header["MaxAge"] = "0"; |
leihen | 12:ba81cc117fb6 | 76 | header["Connection"] = "Keep-Alive"; |
leihen | 12:ba81cc117fb6 | 77 | header["Server"] = "mbed Embedded"; |
leihen | 12:ba81cc117fb6 | 78 | if (fext == NULL) |
leihen | 12:ba81cc117fb6 | 79 | header["Content-Type"] = "text/html"; |
leihen | 12:ba81cc117fb6 | 80 | else { |
leihen | 12:ba81cc117fb6 | 81 | for (int i = 0 ; i < sizeof(fileTypeMapping)/sizeof(struct mapping_t) ;i++) { |
leihen | 12:ba81cc117fb6 | 82 | if (_stricmp(fileTypeMapping[i].key, fext) == 0) { |
leihen | 12:ba81cc117fb6 | 83 | header["Content-Type"] = fileTypeMapping[i].value; |
leihen | 12:ba81cc117fb6 | 84 | break; |
leihen | 12:ba81cc117fb6 | 85 | } |
leihen | 12:ba81cc117fb6 | 86 | } |
leihen | 12:ba81cc117fb6 | 87 | } |
leihen | 12:ba81cc117fb6 | 88 | } |
leihen | 12:ba81cc117fb6 | 89 | |
leihen | 3:d6224049b3bf | 90 | void HTTPRequestHandler::handleRequest() |
leihen | 3:d6224049b3bf | 91 | { |
leihen | 3:d6224049b3bf | 92 | int err = 0; |
leihen | 3:d6224049b3bf | 93 | |
leihen | 3:d6224049b3bf | 94 | switch (msg.request) { |
leihen | 3:d6224049b3bf | 95 | case HTTP_RT_GET: |
leihen | 3:d6224049b3bf | 96 | INFO("Dispatching GET Request."); |
leihen | 3:d6224049b3bf | 97 | err = handleGetRequest(); |
leihen | 3:d6224049b3bf | 98 | break; |
leihen | 3:d6224049b3bf | 99 | |
leihen | 4:d065642c32cc | 100 | case HTTP_RT_POST: |
leihen | 4:d065642c32cc | 101 | INFO("Dispatching POST request."); |
leihen | 4:d065642c32cc | 102 | err = handlePostRequest(); |
leihen | 4:d065642c32cc | 103 | break; |
leihen | 3:d6224049b3bf | 104 | |
leihen | 4:d065642c32cc | 105 | case HTTP_RT_PUT: |
leihen | 4:d065642c32cc | 106 | INFO("Dispatching PUT request."); |
leihen | 4:d065642c32cc | 107 | err = handlePutRequest(); |
leihen | 4:d065642c32cc | 108 | break; |
leihen | 3:d6224049b3bf | 109 | |
leihen | 3:d6224049b3bf | 110 | default: |
leihen | 3:d6224049b3bf | 111 | INFO("Error in handleRequest, unhandled request type."); |
leihen | 9:c2a1462b9b71 | 112 | err = HTTP_NotImplemented; |
leihen | 3:d6224049b3bf | 113 | break; |
leihen | 3:d6224049b3bf | 114 | } |
leihen | 3:d6224049b3bf | 115 | |
leihen | 3:d6224049b3bf | 116 | // if any of these functions returns a negative number, call the error handler |
leihen | 3:d6224049b3bf | 117 | if (err > 0) { |
leihen | 3:d6224049b3bf | 118 | handleError(err); |
leihen | 3:d6224049b3bf | 119 | } |
leihen | 3:d6224049b3bf | 120 | } |
leihen | 3:d6224049b3bf | 121 | |
leihen | 3:d6224049b3bf | 122 | 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"; |
leihen | 3:d6224049b3bf | 123 | |
leihen | 3:d6224049b3bf | 124 | void HTTPRequestHandler::handleError(int errorCode, HTTPHeaders* header) |
leihen | 3:d6224049b3bf | 125 | { |
leihen | 3:d6224049b3bf | 126 | INFO("Handling error !"); |
leihen | 3:d6224049b3bf | 127 | tcp.set_blocking(true, 1500); |
leihen | 11:3943841e1798 | 128 | sprintf(buffer,"HTTP/1.1 %d Error\r\n", errorCode); |
leihen | 3:d6224049b3bf | 129 | tcp.send(buffer, strlen(buffer)); |
leihen | 3:d6224049b3bf | 130 | sprintf(buffer, "Content-Length: %d\r\n", strlen(szErrorPage)); |
leihen | 3:d6224049b3bf | 131 | tcp.send(buffer, strlen(buffer)); |
leihen | 3:d6224049b3bf | 132 | if (header == NULL) { |
leihen | 3:d6224049b3bf | 133 | sprintf(buffer, "Content-Type: text/html\r\nServer: mbed embedded\r\n\n\r"); |
leihen | 3:d6224049b3bf | 134 | tcp.send(buffer, strlen(buffer)); |
leihen | 3:d6224049b3bf | 135 | } |
leihen | 3:d6224049b3bf | 136 | else { |
leihen | 3:d6224049b3bf | 137 | for ( map<const char*, const char*>::iterator cIter = header->begin() ; cIter != header->end() ; cIter ++) { |
leihen | 3:d6224049b3bf | 138 | tcp.send((char*)cIter->first, strlen(cIter->first)); |
leihen | 3:d6224049b3bf | 139 | tcp.send(": ", 2); |
leihen | 3:d6224049b3bf | 140 | tcp.send((char*)cIter->second, strlen(cIter->second)); |
leihen | 3:d6224049b3bf | 141 | tcp.send("\r\n",2); |
leihen | 3:d6224049b3bf | 142 | } |
leihen | 3:d6224049b3bf | 143 | tcp.send("\r\n",2); |
leihen | 3:d6224049b3bf | 144 | } |
leihen | 3:d6224049b3bf | 145 | tcp.send((char*)szErrorPage, strlen(szErrorPage)); |
leihen | 3:d6224049b3bf | 146 | } |
leihen | 3:d6224049b3bf | 147 | |
leihen | 3:d6224049b3bf | 148 | |
leihen | 7:cb7fec1265b5 | 149 | void HTTPRequestHandler::startResponse(int returnCode, long nLen, HTTPHeaders* header) |
leihen | 3:d6224049b3bf | 150 | { |
leihen | 7:cb7fec1265b5 | 151 | INFO("Starting response (%ld bytes in total)!", nLen); |
leihen | 3:d6224049b3bf | 152 | tcp.set_blocking(true, 1500); |
leihen | 11:3943841e1798 | 153 | sprintf(buffer, "HTTP/1.1 %d OK\r\n", returnCode); |
leihen | 11:3943841e1798 | 154 | tcp.send_all(buffer, strlen(buffer)); |
leihen | 11:3943841e1798 | 155 | tcp.send_all((char*)hdrConClose, strlen(hdrConClose)); |
leihen | 7:cb7fec1265b5 | 156 | sprintf(buffer, "Content-Length: %ld\r\n", nLen); // Add 2 chars for the terminating CR+LF |
leihen | 11:3943841e1798 | 157 | tcp.send_all(buffer, strlen(buffer)); |
leihen | 3:d6224049b3bf | 158 | if (header == NULL) { |
leihen | 11:3943841e1798 | 159 | tcp.send_all((char*)hdrDNT, strlen(hdrDNT)); |
leihen | 11:3943841e1798 | 160 | tcp.send_all((char*)hdrMaxAge, strlen(hdrMaxAge)); |
leihen | 11:3943841e1798 | 161 | tcp.send_all((char*)hdrContent, strlen(hdrContent)); |
leihen | 12:ba81cc117fb6 | 162 | // tcp.send_all((char*)hdrTrsfrEnc, strlen(hdrTrsfrEnc)); |
leihen | 11:3943841e1798 | 163 | tcp.send_all((char*)hdrServer, strlen(hdrServer)); |
leihen | 11:3943841e1798 | 164 | tcp.send_all((char*)hdrEndl, strlen(hdrEndl)); |
leihen | 3:d6224049b3bf | 165 | } |
leihen | 3:d6224049b3bf | 166 | else { |
leihen | 3:d6224049b3bf | 167 | for ( map<const char*, const char*>::iterator cIter = header->begin() ; cIter != header->end() ; cIter ++) { |
leihen | 3:d6224049b3bf | 168 | tcp.send((char*)cIter->first, strlen(cIter->first)); |
leihen | 3:d6224049b3bf | 169 | tcp.send(": ", 2); |
leihen | 3:d6224049b3bf | 170 | tcp.send((char*)cIter->second, strlen(cIter->second)); |
leihen | 3:d6224049b3bf | 171 | tcp.send("\r\n\r\n",2); |
leihen | 3:d6224049b3bf | 172 | } |
leihen | 11:3943841e1798 | 173 | tcp.send_all("\r\n", 2); |
leihen | 3:d6224049b3bf | 174 | } |
leihen | 3:d6224049b3bf | 175 | // other content must be sent using the 'processResponse' function |
leihen | 3:d6224049b3bf | 176 | } |
leihen | 3:d6224049b3bf | 177 | |
leihen | 3:d6224049b3bf | 178 | void HTTPRequestHandler::processResponse(int nLen, char* body) |
leihen | 3:d6224049b3bf | 179 | { |
leihen | 7:cb7fec1265b5 | 180 | INFO("Processing Response (%d bytes)!\n",nLen); |
leihen | 11:3943841e1798 | 181 | tcp.send_all(body, nLen); |
leihen | 3:d6224049b3bf | 182 | } |
leihen | 3:d6224049b3bf | 183 | |
leihen | 3:d6224049b3bf | 184 | void HTTPRequestHandler::endResponse() |
leihen | 3:d6224049b3bf | 185 | { |
leihen | 3:d6224049b3bf | 186 | INFO("Ending Response !"); |
leihen | 11:3943841e1798 | 187 | // tcp.send("\r\n\r\n", 4); |
leihen | 3:d6224049b3bf | 188 | } |