HTTP Server library for Mbed OS-5. A fork of Henry Leinen's [[https://os.mbed.com/users/leihen/code/HTTPServer/]] library.
Dependents: STM32F407VET6_HTTPServer
HTTPServer.cpp
00001 #include "mbed.h" 00002 #include "HTTPServer.h" 00003 #define DEBUG 00004 #include "hl_debug.h" 00005 00006 00007 00008 /* Constructor */ 00009 /* initialize all members and set the standard error handler. */ 00010 HTTPServer::HTTPServer() 00011 : m_pEthernet(NULL) 00012 { 00013 m_pErrorHandler = StdErrorHandler; 00014 } 00015 00016 HTTPServer::~HTTPServer() 00017 { 00018 if (m_pEthernet == NULL) { 00019 INFO("Deleting EthernetInterface Object.\n"); 00020 delete m_pEthernet; 00021 } 00022 } 00023 00024 static const char* szStdErrorPage = "<HTML><HEAD><META content=\"text/html\" http-equiv=Content-Type></HEAD><BODY><h1>Error 404</h1><P>This resource is not available<P></BODY></HTML>\r\n\r\n"; 00025 00026 void HTTPServer::StdErrorHandler(HTTPConnection::HTTPMessage& msg, TCPSocket* tcp) 00027 { 00028 char echoHeader[256]; 00029 tcp->set_blocking(false); 00030 sprintf(echoHeader,"HTTP/1.0 404 Fail\r\nConnection: close\r\nContent-Length: %d\r\nContent-Type: text/html\r\nServer: mbed embedded\r\n\n\r",strlen(szStdErrorPage)); 00031 tcp->send(echoHeader, strlen(echoHeader)); 00032 tcp->send((char*)szStdErrorPage, strlen(szStdErrorPage)); 00033 } 00034 00035 00036 bool HTTPServer::start(int port, EthernetInterface* pEthernet) 00037 { 00038 // If no ethernet interface is provided, instantiate own on the heap. This has to be deleted later in the destructor. 00039 // If a valid pointer to an thernet interface is proveded, we can simply use it. 00040 if (pEthernet == NULL) { 00041 ERR("Socket is not opened!!\r\n"); 00042 00043 } else { 00044 // In the case that the ethernet interface is provided, it is assumed that a connection has already been created. 00045 INFO("Using connection IP %s", pEthernet->get_ip_address()); 00046 } 00047 00048 nsapi_error_t r; 00049 const char* ip = pEthernet->get_ip_address(); 00050 00051 /* Open the server on ethernet stack */ 00052 INFO("Opening server on the Ethernet stack ..."); 00053 r = m_Svr.open(pEthernet); 00054 if (r != 0) { 00055 INFO("Error! Opening server returned: %d\n", r); 00056 error("Opening server"); 00057 return false; 00058 } 00059 00060 INFO("Binding to port %d...", port); 00061 if (m_Svr.bind(ip, port) < 0) { 00062 ERR("Failed to bind to port !\n"); 00063 error("Binding"); 00064 return false; 00065 } 00066 00067 if (m_Svr.listen(1) < 0) { 00068 ERR("Failed to listen !\n"); 00069 error("Listening"); 00070 return false; 00071 } 00072 00073 INFO("Listening ..."); 00074 // set into non blocking operation after timeout 00075 m_Svr.set_timeout(1500); 00076 00077 return true; 00078 } 00079 00080 00081 int HTTPServer::poll(bool blocking) 00082 { 00083 // This thread basically checks if there is a new incoming connection. 00084 // If so , a new HTTPConnection is created and the connection thread is started. 00085 nsapi_error_t error; 00086 SocketAddress clntAddress; 00087 TCPSocket* clnt = m_Svr.accept(&error); 00088 00089 if (clnt == NULL) { 00090 return -1; 00091 } 00092 00093 if (error != 0) { 00094 clnt->close(); 00095 return error; 00096 } 00097 00098 // a new connection was received 00099 clnt->getpeername(&clntAddress); 00100 INFO("Client (IP=%s) is connected !\n", clntAddress.get_ip_address()); 00101 HTTPConnection con(clnt); 00102 int c = con.poll(); 00103 if (c == 0) { 00104 // Handle the request 00105 INFO("Handling request !"); 00106 HandleRequest(con.m_Msg, clnt); 00107 } 00108 if (c == -1) { 00109 // break; 00110 } 00111 00112 INFO("Leaving polling thread"); 00113 return 0; 00114 } 00115 00116 void HTTPServer::HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocket* tcp) 00117 { 00118 std::string localPath; 00119 std::map<std::string, HTTPRequestHandler*(*)(const char*, const char*, HTTPConnection::HTTPMessage&, TCPSocket*), handlersComp>::const_iterator it; 00120 00121 // Iterate through registered handlers and check if the handler's path is a subset of the requested uri. 00122 for (it = m_lpHandlers.begin() ; it != m_lpHandlers.end() ; it++) { 00123 // check if this entries' path is fully contained at the beginning of the requested path 00124 std::string curpth = it->first; 00125 00126 if (msg.uri.find(curpth) == 0) { 00127 // firts matching handler found, we just take it and we'll be happy 00128 localPath = msg.uri.substr(curpth.length()); 00129 break; 00130 } 00131 } 00132 00133 if (it == m_lpHandlers.end()) { 00134 // There is no such handler, so return invalid 00135 00136 m_pErrorHandler(msg, tcp); 00137 INFO("Webrequest left unhandled."); 00138 } else { 00139 // Valid handler was found 00140 INFO("Routing webrequest !"); 00141 // Instantiate the handler object (handling will be done from withing the object's constructor 00142 HTTPRequestHandler *phdl = (*it->second)(it->first.c_str(), localPath.c_str(), msg, tcp); 00143 // now we can delete the object, because handling is completed. 00144 if (phdl != NULL) 00145 delete phdl; 00146 } 00147 }
Generated on Wed Jul 13 2022 12:04:08 by
