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