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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPServer.cpp Source File

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 }