Adaptation of the HttpServer by user yueee_yt. This version has improved handling of the HTTP headers (**NOTE**: There are limitations with this implementation and it is not fully functional. Use it only as a starting point.)

Dependents:   DMSupport DMSupport DMSupport DMSupport

Fork of DM_HttpServer by EmbeddedArtists AB

Committer:
embeddedartists
Date:
Wed Oct 23 06:58:32 2019 +0000
Revision:
10:c1c8276af541
Parent:
6:7b3320c34654
Child:
11:9dcff8cf906a
Updates related to mbed OS 5

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yueee_yt 4:1b6b021ee21d 1 //#define _DEBUG_ALL
yueee_yt 4:1b6b021ee21d 2
yueee_yt 0:fdf9c2c5200f 3 #ifndef HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 4 #define HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 5
yueee_yt 4:1b6b021ee21d 6 #ifdef _DEBUG_ALL
yueee_yt 4:1b6b021ee21d 7 #define _DEBUG_HTTP_SERVER_H
yueee_yt 4:1b6b021ee21d 8 #endif
yueee_yt 4:1b6b021ee21d 9
yueee_yt 0:fdf9c2c5200f 10 #include <string>
yueee_yt 0:fdf9c2c5200f 11 using std::string;
yueee_yt 0:fdf9c2c5200f 12
yueee_yt 0:fdf9c2c5200f 13 #include <map>
yueee_yt 0:fdf9c2c5200f 14 using std::map;
yueee_yt 0:fdf9c2c5200f 15
yueee_yt 0:fdf9c2c5200f 16 #include "HTTPRequestHandler.h"
yueee_yt 0:fdf9c2c5200f 17 #include "rtos.h"
yueee_yt 0:fdf9c2c5200f 18 #include "mbed.h"
yueee_yt 0:fdf9c2c5200f 19 #include "EthernetInterface.h"
yueee_yt 0:fdf9c2c5200f 20 //#include "HTTPRequestDispatcher.h"
yueee_yt 0:fdf9c2c5200f 21
yueee_yt 0:fdf9c2c5200f 22 //#include "dbg/dbg.h"
yueee_yt 0:fdf9c2c5200f 23
yueee_yt 0:fdf9c2c5200f 24 #define THREAD_MAX 5
yueee_yt 0:fdf9c2c5200f 25 Thread *threads[THREAD_MAX];
yueee_yt 0:fdf9c2c5200f 26 Thread *xthread;
yueee_yt 0:fdf9c2c5200f 27 //#include "HTTPServer2.h"
yueee_yt 0:fdf9c2c5200f 28
yueee_yt 0:fdf9c2c5200f 29 struct handlersComp { //Used to order handlers in the right way
yueee_yt 0:fdf9c2c5200f 30 bool operator() (const string& handler1, const string& handler2) const {
yueee_yt 0:fdf9c2c5200f 31 //The first handler is longer than the second one
yueee_yt 0:fdf9c2c5200f 32 if (handler1.length() > handler2.length())
yueee_yt 0:fdf9c2c5200f 33 return true; //Returns true if handler1 is to appear before handler2
yueee_yt 0:fdf9c2c5200f 34 else if (handler1.length() < handler2.length())
yueee_yt 0:fdf9c2c5200f 35 return false;
yueee_yt 0:fdf9c2c5200f 36 else //To avoid the == case, sort now by address
yueee_yt 0:fdf9c2c5200f 37 return ((&handler1)>(&handler2));
yueee_yt 0:fdf9c2c5200f 38 }
yueee_yt 0:fdf9c2c5200f 39 };
yueee_yt 0:fdf9c2c5200f 40
yueee_yt 0:fdf9c2c5200f 41 map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocketConnection* ), handlersComp > m_lpHandlers;
yueee_yt 0:fdf9c2c5200f 42 template<typename T>
yueee_yt 0:fdf9c2c5200f 43 void HTTPServerAddHandler(const char* path) //Template decl in header
yueee_yt 0:fdf9c2c5200f 44 {
yueee_yt 0:fdf9c2c5200f 45 m_lpHandlers[path] = &T::inst;
yueee_yt 0:fdf9c2c5200f 46 }
yueee_yt 0:fdf9c2c5200f 47
yueee_yt 0:fdf9c2c5200f 48 void ListenThread(void const *args);
yueee_yt 0:fdf9c2c5200f 49 enum HTTP_METH {
yueee_yt 0:fdf9c2c5200f 50 HTTP_GET,
yueee_yt 0:fdf9c2c5200f 51 HTTP_POST,
yueee_yt 0:fdf9c2c5200f 52 HTTP_HEAD
yueee_yt 0:fdf9c2c5200f 53 };
yueee_yt 0:fdf9c2c5200f 54
yueee_yt 0:fdf9c2c5200f 55 bool getRequest(TCPSocketConnection* client,string* path, string* meth)
yueee_yt 0:fdf9c2c5200f 56 {
yueee_yt 0:fdf9c2c5200f 57 char req[128];
yueee_yt 0:fdf9c2c5200f 58 char c_path[128];
yueee_yt 0:fdf9c2c5200f 59 char c_meth[128];
yueee_yt 0:fdf9c2c5200f 60 const int maxLen = 128;
yueee_yt 0:fdf9c2c5200f 61 char* p = req;
yueee_yt 0:fdf9c2c5200f 62 //Read Line
yueee_yt 0:fdf9c2c5200f 63 int ret;
yueee_yt 0:fdf9c2c5200f 64 int len = 0;
yueee_yt 0:fdf9c2c5200f 65 for(int i = 0; i < maxLen - 1; i++) {
yueee_yt 0:fdf9c2c5200f 66 ret = client->receive(p, 1);
yueee_yt 0:fdf9c2c5200f 67 if(!ret) {
yueee_yt 0:fdf9c2c5200f 68 break;
yueee_yt 0:fdf9c2c5200f 69 }
yueee_yt 0:fdf9c2c5200f 70 if( (len > 1) && *(p-1)=='\r' && *p=='\n' ) {
yueee_yt 0:fdf9c2c5200f 71 p--;
yueee_yt 0:fdf9c2c5200f 72 len-=2;
yueee_yt 0:fdf9c2c5200f 73 break;
yueee_yt 0:fdf9c2c5200f 74 } else if( *p=='\n' ) {
yueee_yt 0:fdf9c2c5200f 75 len--;
yueee_yt 0:fdf9c2c5200f 76 break;
yueee_yt 0:fdf9c2c5200f 77 }
yueee_yt 0:fdf9c2c5200f 78 p++;
yueee_yt 0:fdf9c2c5200f 79 len++;
yueee_yt 0:fdf9c2c5200f 80 }
yueee_yt 0:fdf9c2c5200f 81 *p = 0;
yueee_yt 4:1b6b021ee21d 82 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 83 printf("Parsing request : %s\r\n", req);
yueee_yt 4:1b6b021ee21d 84 #endif
yueee_yt 0:fdf9c2c5200f 85 ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path);
yueee_yt 0:fdf9c2c5200f 86 if(ret !=2) return false;
yueee_yt 0:fdf9c2c5200f 87 *meth = string(c_meth);
yueee_yt 0:fdf9c2c5200f 88 *path = string(c_path);
yueee_yt 0:fdf9c2c5200f 89 return true;
yueee_yt 0:fdf9c2c5200f 90 }
yueee_yt 0:fdf9c2c5200f 91
yueee_yt 0:fdf9c2c5200f 92 void dispatchRequest(TCPSocketConnection* client)
yueee_yt 0:fdf9c2c5200f 93 {
yueee_yt 0:fdf9c2c5200f 94 string path;
yueee_yt 0:fdf9c2c5200f 95 string meth;
yueee_yt 0:fdf9c2c5200f 96 HTTP_METH methCode;
yueee_yt 4:1b6b021ee21d 97 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 98 printf("Dispatching req\r\n");
yueee_yt 4:1b6b021ee21d 99 #endif
yueee_yt 0:fdf9c2c5200f 100 if( !getRequest(client,&path, &meth ) ) {
yueee_yt 4:1b6b021ee21d 101 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 102 printf("dispatchRequest Invalid request\r\n");
yueee_yt 4:1b6b021ee21d 103 #endif
yueee_yt 0:fdf9c2c5200f 104 //close();
yueee_yt 0:fdf9c2c5200f 105 return; //Invalid request
yueee_yt 0:fdf9c2c5200f 106 }
yueee_yt 0:fdf9c2c5200f 107 if( !meth.compare("GET") ) {
yueee_yt 4:1b6b021ee21d 108 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 109 printf("dispatchRequest HTTP_GET\r\n");
yueee_yt 4:1b6b021ee21d 110 #endif
yueee_yt 0:fdf9c2c5200f 111 methCode = HTTP_GET;
yueee_yt 0:fdf9c2c5200f 112 } else if( !meth.compare("POST") ) {
yueee_yt 4:1b6b021ee21d 113 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 114 printf("dispatchRequest HTTP_POST\r\n");
yueee_yt 4:1b6b021ee21d 115 #endif
yueee_yt 0:fdf9c2c5200f 116 methCode = HTTP_POST;
yueee_yt 0:fdf9c2c5200f 117 } else if( !meth.compare("HEAD") ) {
yueee_yt 4:1b6b021ee21d 118 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 119 printf("dispatchRequest HTTP_HEAD\r\n");
yueee_yt 4:1b6b021ee21d 120 #endif
yueee_yt 0:fdf9c2c5200f 121 methCode = HTTP_HEAD;
yueee_yt 0:fdf9c2c5200f 122 } else {
yueee_yt 4:1b6b021ee21d 123 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 124 printf("dispatchRequest() Parse error\r\n");
yueee_yt 4:1b6b021ee21d 125 #endif
yueee_yt 0:fdf9c2c5200f 126 //close(); //Parse error
yueee_yt 0:fdf9c2c5200f 127 return;
yueee_yt 0:fdf9c2c5200f 128 }
yueee_yt 4:1b6b021ee21d 129 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 130 printf("Looking for a handler\r\n");
yueee_yt 4:1b6b021ee21d 131 #endif
yueee_yt 0:fdf9c2c5200f 132 map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocketConnection*) >::iterator it;
yueee_yt 0:fdf9c2c5200f 133 int root_len = 0;
yueee_yt 0:fdf9c2c5200f 134 for (it = m_lpHandlers.begin(); it != m_lpHandlers.end(); it++) {
yueee_yt 4:1b6b021ee21d 135 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 136 printf("Checking %s...\r\n", (*it).first.c_str());
yueee_yt 4:1b6b021ee21d 137 #endif
yueee_yt 0:fdf9c2c5200f 138 root_len = (*it).first.length();
yueee_yt 0:fdf9c2c5200f 139 if ( root_len &&
yueee_yt 0:fdf9c2c5200f 140 !path.compare( 0, root_len, (*it).first ) &&
yueee_yt 0:fdf9c2c5200f 141 (path[root_len] == '/' || path[root_len] == '\0')) {
yueee_yt 4:1b6b021ee21d 142 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 143 printf("Found (%s)\r\n", (*it).first.c_str());
yueee_yt 4:1b6b021ee21d 144 #endif
yueee_yt 0:fdf9c2c5200f 145 // Found!
yueee_yt 0:fdf9c2c5200f 146 break; // for
yueee_yt 0:fdf9c2c5200f 147 }
yueee_yt 0:fdf9c2c5200f 148 }
yueee_yt 0:fdf9c2c5200f 149 if((it == m_lpHandlers.end()) && !(m_lpHandlers.empty())) {
yueee_yt 4:1b6b021ee21d 150 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 151 printf("Using default handler\r\n");
yueee_yt 4:1b6b021ee21d 152 #endif
yueee_yt 0:fdf9c2c5200f 153 it = m_lpHandlers.end();
yueee_yt 0:fdf9c2c5200f 154 it--; //Get the last element
yueee_yt 0:fdf9c2c5200f 155 if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler
yueee_yt 0:fdf9c2c5200f 156 it = m_lpHandlers.end();
yueee_yt 0:fdf9c2c5200f 157 root_len = 0;
yueee_yt 0:fdf9c2c5200f 158 }
yueee_yt 0:fdf9c2c5200f 159 if(it == m_lpHandlers.end()) {
yueee_yt 4:1b6b021ee21d 160 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 161 printf("No handler found\r\n");
yueee_yt 4:1b6b021ee21d 162 #endif
yueee_yt 0:fdf9c2c5200f 163 return;
yueee_yt 0:fdf9c2c5200f 164 }
yueee_yt 4:1b6b021ee21d 165 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 166 printf("Handler found.\r\n");
yueee_yt 4:1b6b021ee21d 167 #endif
yueee_yt 0:fdf9c2c5200f 168 HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, client);
yueee_yt 0:fdf9c2c5200f 169 //**** client = NULL; //We don't own it anymore
yueee_yt 0:fdf9c2c5200f 170 switch(methCode) {
yueee_yt 0:fdf9c2c5200f 171 case HTTP_GET:
yueee_yt 0:fdf9c2c5200f 172 pHdlr->doGet();
yueee_yt 0:fdf9c2c5200f 173 break;
yueee_yt 0:fdf9c2c5200f 174 case HTTP_POST:
yueee_yt 0:fdf9c2c5200f 175 pHdlr->doPost();
yueee_yt 0:fdf9c2c5200f 176 break;
yueee_yt 0:fdf9c2c5200f 177 case HTTP_HEAD:
yueee_yt 0:fdf9c2c5200f 178 pHdlr->doHead();
yueee_yt 0:fdf9c2c5200f 179 break;
yueee_yt 0:fdf9c2c5200f 180 }
yueee_yt 0:fdf9c2c5200f 181 delete pHdlr;
yueee_yt 4:1b6b021ee21d 182 // delete client;
yueee_yt 4:1b6b021ee21d 183 // delete m_pTCPSocketConnection;
yueee_yt 4:1b6b021ee21d 184 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 4:1b6b021ee21d 185 printf("(dispatcherRequest)return\r\n");
yueee_yt 4:1b6b021ee21d 186 #endif
yueee_yt 4:1b6b021ee21d 187 return ;
yueee_yt 0:fdf9c2c5200f 188 }
yueee_yt 0:fdf9c2c5200f 189
yueee_yt 0:fdf9c2c5200f 190 void HTTPServerChild (void const *arg)
yueee_yt 0:fdf9c2c5200f 191 {
yueee_yt 4:1b6b021ee21d 192 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 193 printf("HTTPServerChiled Start......\r\n");
yueee_yt 4:1b6b021ee21d 194 #endif
yueee_yt 0:fdf9c2c5200f 195 TCPSocketConnection* client = (TCPSocketConnection*)arg;
yueee_yt 0:fdf9c2c5200f 196
yueee_yt 0:fdf9c2c5200f 197 for (;;) {
yueee_yt 4:1b6b021ee21d 198 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 199 printf("(HTTPServer.h<HTTPServerChild>)Connection from %s\r\n", client->get_address());
yueee_yt 4:1b6b021ee21d 200 #endif
yueee_yt 0:fdf9c2c5200f 201 dispatchRequest(client);
yueee_yt 4:1b6b021ee21d 202 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 203 printf("(HTTPServer.h<HTTPServerChild>)Close %s\r\n", client->get_address());
yueee_yt 4:1b6b021ee21d 204 #endif
yueee_yt 0:fdf9c2c5200f 205 client->close();
yueee_yt 0:fdf9c2c5200f 206 client->reset_address();
yueee_yt 0:fdf9c2c5200f 207 //delete client;
yueee_yt 0:fdf9c2c5200f 208 Thread::signal_wait(1);
yueee_yt 0:fdf9c2c5200f 209 }
yueee_yt 0:fdf9c2c5200f 210 }
yueee_yt 0:fdf9c2c5200f 211
yueee_yt 0:fdf9c2c5200f 212 void HTTPServerCloser (void const *arg)
yueee_yt 0:fdf9c2c5200f 213 {
yueee_yt 0:fdf9c2c5200f 214 TCPSocketConnection *client = (TCPSocketConnection*)arg;
yueee_yt 0:fdf9c2c5200f 215
yueee_yt 0:fdf9c2c5200f 216 for (;;) {
yueee_yt 0:fdf9c2c5200f 217 client->close();
yueee_yt 4:1b6b021ee21d 218 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 219 printf("Close %s\r\n", client->get_address());
yueee_yt 4:1b6b021ee21d 220 #endif
yueee_yt 0:fdf9c2c5200f 221 Thread::signal_wait(1);
yueee_yt 0:fdf9c2c5200f 222 }
yueee_yt 0:fdf9c2c5200f 223 }
yueee_yt 0:fdf9c2c5200f 224
yueee_yt 0:fdf9c2c5200f 225 void HTTPServerStart(int port = 80)
yueee_yt 0:fdf9c2c5200f 226 {
yueee_yt 0:fdf9c2c5200f 227 int i, t = 0;
yueee_yt 0:fdf9c2c5200f 228 TCPSocketConnection clients[THREAD_MAX];
yueee_yt 0:fdf9c2c5200f 229 TCPSocketConnection xclient;
yueee_yt 0:fdf9c2c5200f 230
yueee_yt 0:fdf9c2c5200f 231 for (i = 0; i < THREAD_MAX; i ++) {
yueee_yt 0:fdf9c2c5200f 232 threads[i] = NULL;
yueee_yt 0:fdf9c2c5200f 233 }
yueee_yt 0:fdf9c2c5200f 234 xthread = NULL;
yueee_yt 0:fdf9c2c5200f 235
yueee_yt 0:fdf9c2c5200f 236 TCPSocketServer server;
yueee_yt 0:fdf9c2c5200f 237 server.bind(port);
yueee_yt 0:fdf9c2c5200f 238 server.listen();
yueee_yt 4:1b6b021ee21d 239 // server.set_blocking(false);
yueee_yt 4:1b6b021ee21d 240 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 241 printf("Wait for new connection...\r\n");
yueee_yt 4:1b6b021ee21d 242 #endif
yueee_yt 0:fdf9c2c5200f 243 for (;;) {
yueee_yt 4:1b6b021ee21d 244 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 245 printf("**Start Loop** \r\n");
yueee_yt 4:1b6b021ee21d 246 #endif
yueee_yt 0:fdf9c2c5200f 247 if (t >= 0) {
yueee_yt 0:fdf9c2c5200f 248 if(server.accept(clients[t])==0) {
yueee_yt 0:fdf9c2c5200f 249 // fork child process
yueee_yt 0:fdf9c2c5200f 250 if (threads[t]) {
yueee_yt 0:fdf9c2c5200f 251 threads[t]->signal_set(1);
yueee_yt 0:fdf9c2c5200f 252 } else {
embeddedartists 6:7b3320c34654 253 threads[t] = new Thread(HTTPServerChild, (void*)&clients[t], osPriorityNormal, DEFAULT_STACK_SIZE*2);
yueee_yt 0:fdf9c2c5200f 254 }
yueee_yt 4:1b6b021ee21d 255 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 256 printf("Forked %d\r\n", t);
yueee_yt 4:1b6b021ee21d 257 #endif
yueee_yt 0:fdf9c2c5200f 258 }
yueee_yt 0:fdf9c2c5200f 259 } else {
yueee_yt 0:fdf9c2c5200f 260 if(server.accept(xclient)==0) {
yueee_yt 0:fdf9c2c5200f 261 // closer process
yueee_yt 0:fdf9c2c5200f 262 if (xthread) {
yueee_yt 0:fdf9c2c5200f 263 xthread->signal_set(1);
yueee_yt 0:fdf9c2c5200f 264 } else {
embeddedartists 6:7b3320c34654 265 xthread = new Thread(HTTPServerCloser, (void*)&xclient, osPriorityNormal, DEFAULT_STACK_SIZE*2);
yueee_yt 0:fdf9c2c5200f 266 }
yueee_yt 4:1b6b021ee21d 267 #ifdef _DEBUG_HTTP_SERVER_H
yueee_yt 0:fdf9c2c5200f 268 printf("Connection full\r\n");
yueee_yt 4:1b6b021ee21d 269 #endif
yueee_yt 0:fdf9c2c5200f 270 }
yueee_yt 0:fdf9c2c5200f 271 }
yueee_yt 0:fdf9c2c5200f 272
yueee_yt 0:fdf9c2c5200f 273 t = -1;
yueee_yt 0:fdf9c2c5200f 274 for (i = 0; i < THREAD_MAX; i ++) {
yueee_yt 0:fdf9c2c5200f 275 if (threads[i] == NULL || threads[i]->get_state() == Thread::WaitingAnd) {
yueee_yt 0:fdf9c2c5200f 276 if (t < 0) t = i; // next empty thread
yueee_yt 0:fdf9c2c5200f 277 }
yueee_yt 0:fdf9c2c5200f 278 }
yueee_yt 4:1b6b021ee21d 279 // Thread::wait(100);
yueee_yt 0:fdf9c2c5200f 280 }
yueee_yt 0:fdf9c2c5200f 281 }
embeddedartists 10:c1c8276af541 282 //#include "Handler/RPCHandler.h"
yueee_yt 0:fdf9c2c5200f 283 #include "Handler/FSHandler.h"
yueee_yt 0:fdf9c2c5200f 284 #include "Handler/SimpleHandler.h"
yueee_yt 0:fdf9c2c5200f 285
yueee_yt 0:fdf9c2c5200f 286 #endif