The library with which to make your mbed a HTTP Server which just reads HTML files in the mbed and sends it to the clients.

Dependents:   httpserversample SIMPLE_WSS

Quote:

This library depends on EthernetInterface class, TCPSocketServer class and TCPSocketConnection class. These classes can be imported at EthernetInterface library. Moreover, the EthernetInterface library depends on the mbed-rtos library, so import it here.

Abstract

This is the library to make a mbed a simple HTTP server. With this library, a mbed can understand only GET requests, and can send clients htm or jpg files as a response.

Handleable Requests:

  • GET

Handleable files:

  • html
  • jpg

Note the length of the Filename

A mbed can handle only 8.3 filename (also called as "short filename" or SFN), such as index.htm (in this case, length of the filename is 5.3).

Sample Code

Running the code below, if your mbed is connected to a network, you can see an IP address of the mbed on your console. (When connecting the mbed to a PC with USB, the baud rate should be 9600)

Hello World

#include "mbed.h"
#include "HTTP_SERVER.h"
int main()
{
    HttpServer httpsvr;
    if(httpsvr.init()){
        if(httpsvr.run() == 0)
            printf("end\r\n");
        else
            printf("error end\r\n");
    }
    return 0;
}

As an example, make a index.htm like below (NOT .html; the reason is referred above) in the mbed, and access to <the IP address>/index.htm with a web browser on your PC or any terminals on the network the mbed is connected to, then you would be able to see the page.

index.htm in mbed

<!DOCTYPE html>
<html>
<head>
<title>mbed http server demo</title>
</head>
<body>
	<h1>Mbed Simple HTTP Server</h1> 
	hello world<br />
	<a href="./index.htm" terget="self">Hyper Link Test</a><br />
</body>
</html>

HTTP_SERVER.cpp

Committer:
aktk
Date:
2018-03-16
Revision:
13:b6dd6ed0060b
Parent:
10:4a48594c2f44

File content as of revision 13:b6dd6ed0060b:

#include "HTTP_SERVER.h"
#include "string"
#ifndef DEBUG
//#define DEBUG
#endif

namespace HTTP_SERVER
{
void DEBUG_PRINT_LINE(const char* arg_line)
{
#ifdef DEBUG
    printf("(HTTP_SERVER) ")
    printf(arg_line);
    printf("\r\n");
#endif
}
template<typename T>
void DEBUG_PRINT_LINE(const char* arg_line, T arg_t)
{
#ifdef DEBUG
    printf("(HTTP_SERVER) ");
    printf(arg_line, arg_t);
    printf("\r\n");
#endif
}
template<typename T1, typename T2>
void DEBUG_PRINT_LINE(const char* arg_line, T1 arg_t1, T2 arg_t2)
{
#ifdef DEBUG
    printf("(HTTP_SERVER) ");
    printf(arg_line, arg_t1, arg_t2);
    printf("\r\n");
#endif
}
}
using namespace HTTP_SERVER;

HttpServer::HttpServer()
{
    keep_alive = (false);
    listening_flag = (false);
    req_buf[0] = '\0';
}

HttpServer::~HttpServer()
{
}

bool HttpServer::init()
{

//  Ethernet Initialization
    if(eth.init()) {
        printf("(HTTP_SERVER) Error!@EthernetInterface::init()\r\n");
        return false;
    }
    //  Ethernet Connecting setup
    if(eth.connect()) {
        printf("(HTTP_SERVER) Error!@EthernetInterface::connect()\r\n");
        return false;
    } else {
        printf("(HTTP_SERVER) IP Address is %s\r\n", eth.getIPAddress());
    }
    //  TCP Socket setup
    //  To open Server-side PORT
    if(tcpsvr.bind(TCP_PORT)< 0) {
        printf("(HTTP_SERVER) Error!@TCPSocketServer::bind()\r\n");
        return false;
    } else {
        printf("(HTTP_SERVER) TCP Server has bounden!\r\n");
    }
    //  Server start listening Request from a web browser.
    if(tcpsvr.listen(1) < 0) {
        printf("(HTTP_SERVER) tcp server listen failed.\r\n");
        return false;
    } else {
        listening_flag = true;
        printf("(HTTP_SERVER) tcp server is listening...\r\n");
    }

    return true;
}

bool HttpServer::run()
{
    DigitalOut led1(LED1);
    DigitalOut led2(LED1);

    while (listening_flag) {
        led1 = true;
        //  blocking mode (never timeout)
        //  waiting client connection
        printf("(HTTP_SERVER) waiting connection\r\n");
        if(tcpsvr.accept(tcpcon) < 0) {
            printf("(HTTP_SERVER) failed to accept connection.\r\n");
            return -1;
        } else {
            printf("(HTTP_SERVER) connection success!\r\nIP: %s\r\n",tcpcon.get_address());
            led2 = true;
        }
        //  When conected
        while(tcpcon.is_connected()) {
            printf("(HTTP_SERVER) connected\r\n");

            char buffer[1024]   = {0};
            char* httpmethod    = NULL;
            char* filepath      = NULL;
            char* http_ver      = NULL;
            char* header_field_name = NULL;
            char* header_field_val  = NULL;

            //
            //  Request Analysis
            //
            DEBUG_PRINT_LINE("DEBUG MODE");
            switch(tcpcon.receive(buffer, 1023)) {
                case 0:
                    DEBUG_PRINT_LINE("recieved buffer is empty.");
                    msger.setStatusLine(400, "No Request");
                    if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                    httpmethod    = NULL;
                    filepath      = NULL;
                    http_ver      = NULL;
                    break;
                case -1:
                    DEBUG_PRINT_LINE("failed to read data from client.");
                    msger.setStatusLine(500, "Internal Server Error");
                    if(msger.setHeaderField("Connection", "Close"))DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                    httpmethod    = NULL;
                    filepath      = NULL;
                    http_ver      = NULL;
                    break;
                default:
                    DEBUG_PRINT_LINE("Recieved Data: %d",strlen(buffer));
                    DEBUG_PRINT_LINE("-->\r\n");
                    DEBUG_PRINT_LINE("%.*s[End of Request]",strlen(buffer),buffer);
                    //  get HTTP method, File path, HTTP version
                    httpmethod = strtok(buffer," ");
                    filepath = strtok(NULL, " ");
                    http_ver = strtok(NULL, "\r\n");
                    DEBUG_PRINT_LINE("httpmethod: %s", httpmethod);
                    DEBUG_PRINT_LINE("file path:  %s", filepath);
                    DEBUG_PRINT_LINE("http ver :  %s", http_ver);
                    break;
            }

            //
            //  Response
            //
            if (strcmp(httpmethod,"GET") == 0 ) {
                DEBUG_PRINT_LINE("GET request incomming.");

                //  file calibration
                DEBUG_PRINT_LINE("file opening");
                fhandl.open(filepath,"rb");
                if(fhandl.arrival()) {
                    msger.setStatusLine(200, "OK");
                    if(msger.setHeaderField("Content-Length", fhandl.getFileSize()))    DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                    if(msger.setHeaderField("Connection", "keep-alive"))                DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                } else {
                    if(msger.setStatusLine(404, "NOT FOUND"))                           DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                    if(msger.setHeaderField("Connection", "Close"))                     DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                    DEBUG_PRINT_LINE("NOT FOUND");
                }
                if(         !strcmp(fhandl.getSuffix(), "htm" ) ||
                            !strcmp(fhandl.getSuffix(), "HTM" ) ||
                            !strcmp(fhandl.getSuffix(), "html") ||
                            !strcmp(fhandl.getSuffix(), "HTML")){
                    if(msger.setHeaderField("Content-Type", "text/html"))               DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                } else if(  !strcmp(fhandl.getSuffix(), "js"  )){
                    if(msger.setHeaderField("Content-Type", "text/javascript"))         DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                } else if ( !strcmp(fhandl.getSuffix(), "ico" )){
                    if(msger.setHeaderField("Content-Type", "image/png"))               DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                } else if ( !strcmp(fhandl.getSuffix(), "png" ) ||
                            !strcmp(fhandl.getSuffix(), "PNG" )){
                    if(msger.setHeaderField("Content-Type", "image/png"))               DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                } else if ( !strcmp(fhandl.getSuffix(), "jpg" ) ||
                            !strcmp(fhandl.getSuffix(), "JPG" )){
                    if(msger.setHeaderField("Content-Type", "image/jpg"))               DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");
                } else {
                    msger.setStatusLine(406, "not acceptable");
                }

                //  Connection timeout field
                if(msger.setHeaderField("Keep-Alive", "timeouit=15"))                   DEBUG_PRINT_LINE("buffer over flow @ ResponseMessenger");

                //  send response
                msger.sendHTTPResponse(tcpcon, fhandl);

                //file close
                if( fhandl.close()== 0)
                    DEBUG_PRINT_LINE("file has closed");
                else if(EOF)
                    DEBUG_PRINT_LINE("failed to close the file");
                    
                msger.resetHeader();
                DEBUG_PRINT_LINE("echo back done.");
            }
            if (httpmethod == NULL) {
                msger.sendHTTPResponse(tcpcon);
                msger.resetHeader();
                DEBUG_PRINT_LINE("echo back done.");
            }
            printf("(HTTP_SERVER) Response to Request has done\r\n");
            //
            //
            //
        }
        printf("(HTTP_SERVER) close connection.\r\ntcp server is listening...\r\n");
        tcpcon.close();
        led2 = false;
    }
    tcpsvr.close();
    listening_flag = false;
    led1 = false;
    return 0;
}