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>
Committer:
aktk
Date:
Sat Nov 26 18:06:53 2016 +0000
Revision:
2:33714d7c0f45
Parent:
1:3a1fe94c6e42
Child:
3:59884bc0a238
attempting to notice the request to upgrade it to websocket.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aktk 0:cc483bea4fe3 1 #include "HTTP_SERVER.h"
aktk 1:3a1fe94c6e42 2 #include "string"
aktk 0:cc483bea4fe3 3 #define DEBUG
aktk 1:3a1fe94c6e42 4
aktk 1:3a1fe94c6e42 5 void DEBUG_PRINT_LINE(const char* arg_line)
aktk 1:3a1fe94c6e42 6 {
aktk 1:3a1fe94c6e42 7 #ifdef DEBUG
aktk 1:3a1fe94c6e42 8 printf("%s",arg_line);
aktk 1:3a1fe94c6e42 9 #endif
aktk 1:3a1fe94c6e42 10 }
aktk 1:3a1fe94c6e42 11
aktk 0:cc483bea4fe3 12 HttpServer::HttpServer()
aktk 0:cc483bea4fe3 13 {
aktk 0:cc483bea4fe3 14 keep_alive = (false);
aktk 0:cc483bea4fe3 15 listening_flag = (false);
aktk 0:cc483bea4fe3 16 req_buf[0] = '\0';
aktk 0:cc483bea4fe3 17 }
aktk 0:cc483bea4fe3 18
aktk 0:cc483bea4fe3 19 HttpServer::~HttpServer()
aktk 0:cc483bea4fe3 20 {
aktk 0:cc483bea4fe3 21 }
aktk 0:cc483bea4fe3 22
aktk 0:cc483bea4fe3 23 bool HttpServer::init()
aktk 0:cc483bea4fe3 24 {
aktk 0:cc483bea4fe3 25
aktk 0:cc483bea4fe3 26 // Ethernet Initialization
aktk 0:cc483bea4fe3 27 if(eth.init()) {
aktk 1:3a1fe94c6e42 28 printf("(HTTP_SERVER) Error!@EthernetInterface::init()\r\n");
aktk 0:cc483bea4fe3 29 return false;
aktk 0:cc483bea4fe3 30 }
aktk 0:cc483bea4fe3 31 // Ethernet Connecting setup
aktk 0:cc483bea4fe3 32 if(eth.connect()) {
aktk 1:3a1fe94c6e42 33 printf("(HTTP_SERVER) Error!@EthernetInterface::connect()\r\n");
aktk 0:cc483bea4fe3 34 return false;
aktk 0:cc483bea4fe3 35 } else {
aktk 1:3a1fe94c6e42 36 printf("(HTTP_SERVER) IP Address is %s\r\n", eth.getIPAddress());
aktk 0:cc483bea4fe3 37 }
aktk 0:cc483bea4fe3 38 // TCP Socket setup
aktk 0:cc483bea4fe3 39 // To open Server-side PORT
aktk 0:cc483bea4fe3 40 if(tcpsvr.bind(TCP_PORT)< 0) {
aktk 1:3a1fe94c6e42 41 printf("(HTTP_SERVER) Error!@TCPSocketServer::bind()\r\n");
aktk 0:cc483bea4fe3 42 return false;
aktk 0:cc483bea4fe3 43 } else {
aktk 1:3a1fe94c6e42 44 printf("(HTTP_SERVER) TCP Server has bounden!\r\n");
aktk 0:cc483bea4fe3 45 }
aktk 0:cc483bea4fe3 46 // Server start listening Request from a web browser.
aktk 0:cc483bea4fe3 47 if(tcpsvr.listen(1) < 0) {
aktk 1:3a1fe94c6e42 48 printf("(HTTP_SERVER) tcp server listen failed.\r\n");
aktk 0:cc483bea4fe3 49 return false;
aktk 0:cc483bea4fe3 50 } else {
aktk 0:cc483bea4fe3 51 listening_flag = true;
aktk 1:3a1fe94c6e42 52 printf("(HTTP_SERVER) tcp server is listening...\r\n");
aktk 0:cc483bea4fe3 53 }
aktk 0:cc483bea4fe3 54
aktk 0:cc483bea4fe3 55 return true;
aktk 0:cc483bea4fe3 56 }
aktk 0:cc483bea4fe3 57
aktk 0:cc483bea4fe3 58 bool HttpServer::run()
aktk 0:cc483bea4fe3 59 {
aktk 0:cc483bea4fe3 60 DigitalOut led1(LED1);
aktk 0:cc483bea4fe3 61 DigitalOut led2(LED1);
aktk 0:cc483bea4fe3 62
aktk 0:cc483bea4fe3 63 while (listening_flag) {
aktk 0:cc483bea4fe3 64 led1 = true;
aktk 0:cc483bea4fe3 65 // blocking mode (never timeout)
aktk 0:cc483bea4fe3 66 // waiting client connection
aktk 1:3a1fe94c6e42 67 printf("(HTTP_SERVER) waiting connection\r\n");
aktk 0:cc483bea4fe3 68 if(tcpsvr.accept(tcpcon) < 0) {
aktk 1:3a1fe94c6e42 69 printf("(HTTP_SERVER) failed to accept connection.\r\n");
aktk 0:cc483bea4fe3 70 return -1;
aktk 0:cc483bea4fe3 71 } else {
aktk 1:3a1fe94c6e42 72 printf("(HTTP_SERVER) connection success!\r\nIP: %s\r\n",tcpcon.get_address());
aktk 0:cc483bea4fe3 73 led2 = true;
aktk 0:cc483bea4fe3 74 }
aktk 1:3a1fe94c6e42 75 // When conected
aktk 0:cc483bea4fe3 76 while(tcpcon.is_connected()) {
aktk 1:3a1fe94c6e42 77 DEBUG_PRINT_LINE("(HTTP_SERVER) connected\r\n");
aktk 1:3a1fe94c6e42 78
aktk 0:cc483bea4fe3 79 char buffer[1024] = {0};
aktk 0:cc483bea4fe3 80 char* httpmethod = NULL;
aktk 0:cc483bea4fe3 81 char* filepath = NULL;
aktk 0:cc483bea4fe3 82 char* http_ver = NULL;
aktk 0:cc483bea4fe3 83 char* header_field_name = NULL;
aktk 0:cc483bea4fe3 84 char* header_field_val = NULL;
aktk 1:3a1fe94c6e42 85
aktk 0:cc483bea4fe3 86 //
aktk 0:cc483bea4fe3 87 // Request Analysis
aktk 0:cc483bea4fe3 88 //
aktk 1:3a1fe94c6e42 89 DEBUG_PRINT_LINE("(HTTP_SERVER) DEBUG MODE\r\n");
aktk 0:cc483bea4fe3 90 switch(tcpcon.receive(buffer, 1023)) {
aktk 0:cc483bea4fe3 91 case 0:
aktk 1:3a1fe94c6e42 92 printf("(HTTP_SERVER) recieved buffer is empty.\r\n");
aktk 0:cc483bea4fe3 93 msger.setStatusLine(400, "No Request");
aktk 0:cc483bea4fe3 94 httpmethod = NULL;
aktk 0:cc483bea4fe3 95 filepath = NULL;
aktk 0:cc483bea4fe3 96 http_ver = NULL;
aktk 0:cc483bea4fe3 97 break;
aktk 0:cc483bea4fe3 98 case -1:
aktk 1:3a1fe94c6e42 99 printf("(HTTP_SERVER) failed to read data from client.\r\n");
aktk 0:cc483bea4fe3 100 msger.setStatusLine(500, "Internal Server Error");
aktk 0:cc483bea4fe3 101 httpmethod = NULL;
aktk 0:cc483bea4fe3 102 filepath = NULL;
aktk 0:cc483bea4fe3 103 http_ver = NULL;
aktk 0:cc483bea4fe3 104 break;
aktk 0:cc483bea4fe3 105 default:
aktk 1:3a1fe94c6e42 106 printf("(HTTP_SERVER) Recieved Data: %d\r\n-->\r\n%.*s[End of Request]\r\n",strlen(buffer),strlen(buffer),buffer);
aktk 0:cc483bea4fe3 107 // get HTTP method
aktk 0:cc483bea4fe3 108 httpmethod = strtok(buffer," ");
aktk 0:cc483bea4fe3 109 // get File path
aktk 0:cc483bea4fe3 110 filepath = strtok(NULL, " ");
aktk 0:cc483bea4fe3 111 // get HTTP version
aktk 0:cc483bea4fe3 112 http_ver = strtok(NULL, "\r\n");
aktk 0:cc483bea4fe3 113 #ifdef DEBUG
aktk 1:3a1fe94c6e42 114 printf("(HTTP_SERVER) httpmethod: %s\r\n", httpmethod);
aktk 1:3a1fe94c6e42 115 printf("(HTTP_SERVER) file path: %s\r\n", filepath);
aktk 1:3a1fe94c6e42 116 printf("(HTTP_SERVER) http ver : %s\r\n", http_ver);
aktk 0:cc483bea4fe3 117 #endif
aktk 0:cc483bea4fe3 118 break;
aktk 0:cc483bea4fe3 119 }
aktk 1:3a1fe94c6e42 120 DEBUG_PRINT_LINE("\r\n"
aktk 1:3a1fe94c6e42 121 "(HTTP_SERVER) debug before response\r\n");
aktk 1:3a1fe94c6e42 122
aktk 0:cc483bea4fe3 123 //
aktk 0:cc483bea4fe3 124 // Response
aktk 0:cc483bea4fe3 125 //
aktk 0:cc483bea4fe3 126 if (strcmp(httpmethod,"GET") == 0 ) {
aktk 1:3a1fe94c6e42 127 printf("(HTTP_SERVER) GET request incomming.\r\n");
aktk 0:cc483bea4fe3 128
aktk 0:cc483bea4fe3 129 // file calibration
aktk 1:3a1fe94c6e42 130 DEBUG_PRINT_LINE("(HTTP_SERVER) file opening\r\n");
aktk 0:cc483bea4fe3 131 fhandl.open(filepath,"rb");
aktk 0:cc483bea4fe3 132 if(fhandl.arrival()) {
aktk 0:cc483bea4fe3 133 msger.setStatusLine(200, "OK");
aktk 0:cc483bea4fe3 134 if(msger.setHeaderField("Content-Length", fhandl.getFileSize()))printf("buffer over flow");
aktk 0:cc483bea4fe3 135 if(msger.setHeaderField("Connection", "keep-alive"))printf("buffer over flow");
aktk 0:cc483bea4fe3 136 } else {
aktk 0:cc483bea4fe3 137 if(msger.setStatusLine(404, "NOT FOUND"))printf("buffer over flow");
aktk 0:cc483bea4fe3 138 if(msger.setHeaderField("Connection", "close"))printf("buffer over flow");
aktk 1:3a1fe94c6e42 139 DEBUG_PRINT_LINE("(HTTP_SERVER) NOT FOUND\r\n");
aktk 0:cc483bea4fe3 140 }
aktk 1:3a1fe94c6e42 141 if( strcmp(fhandl.getSuffix(), "htm" ) ||
aktk 1:3a1fe94c6e42 142 strcmp(fhandl.getSuffix(), "HTM" ) ||
aktk 1:3a1fe94c6e42 143 strcmp(fhandl.getSuffix(), "html") ||
aktk 1:3a1fe94c6e42 144 strcmp(fhandl.getSuffix(), "HTML")) {
aktk 0:cc483bea4fe3 145 if(msger.setHeaderField("Content-Type", "text/html"))printf("buffer over flow");
aktk 1:3a1fe94c6e42 146 } else if (strcmp(fhandl.getSuffix(), "ico" ) ) {
aktk 0:cc483bea4fe3 147 if(msger.setHeaderField("Content-Type", "image/png"))printf("buffer over flow");
aktk 0:cc483bea4fe3 148 } else {
aktk 0:cc483bea4fe3 149 msger.setStatusLine(406, "not acceptable");
aktk 0:cc483bea4fe3 150 }
aktk 0:cc483bea4fe3 151
aktk 0:cc483bea4fe3 152 // Connection timeout field
aktk 0:cc483bea4fe3 153 if(msger.setHeaderField("Keep-Alive", "timeouit=15"))printf("buffer over flow");
aktk 1:3a1fe94c6e42 154
aktk 1:3a1fe94c6e42 155 // Define behaviour of server according to Request Header lines
aktk 2:33714d7c0f45 156 // Apply request header field to response header field
aktk 2:33714d7c0f45 157 char* field_Connection = NULL,
aktk 2:33714d7c0f45 158 field_Upgrade = NULL,
aktk 2:33714d7c0f45 159 field_Sec_WebSocket_Key = NULL,
aktk 2:33714d7c0f45 160 field_Sec-WebSocket_Version = NULL,
aktk 2:33714d7c0f45 161 field_Origin = NULL;
aktk 0:cc483bea4fe3 162 do {
aktk 2:33714d7c0f45 163 //Analyze the header feilds
aktk 0:cc483bea4fe3 164 header_field_name = strtok(NULL, ":");
aktk 0:cc483bea4fe3 165 header_field_name++;
aktk 0:cc483bea4fe3 166 header_field_val = strtok(NULL, "\r\n");
aktk 0:cc483bea4fe3 167 header_field_val++;
aktk 2:33714d7c0f45 168
aktk 2:33714d7c0f45 169 if(header_field_name != NULL) {
aktk 2:33714d7c0f45 170 switch(header_field_name) {
aktk 2:33714d7c0f45 171 case "Connection":
aktk 2:33714d7c0f45 172 filed_Connection = header_field_val;
aktk 2:33714d7c0f45 173 break;
aktk 2:33714d7c0f45 174 case "Upgrade":
aktk 2:33714d7c0f45 175 field_Upgrade = header_field_val;
aktk 2:33714d7c0f45 176 break;
aktk 2:33714d7c0f45 177 case "Sec-WebSocket-Key":
aktk 2:33714d7c0f45 178 field_Sec_WebSocket_Key = header_field_val;
aktk 2:33714d7c0f45 179 break;
aktk 2:33714d7c0f45 180 case "Sec-WebSocket-Version":
aktk 2:33714d7c0f45 181 field_Sec_WebSocket_Version = header_field_val;
aktk 2:33714d7c0f45 182 break;
aktk 2:33714d7c0f45 183 case "Origin":
aktk 2:33714d7c0f45 184 field_Origin = header_field_val;
aktk 2:33714d7c0f45 185 break;
aktk 2:33714d7c0f45 186 default:
aktk 2:33714d7c0f45 187 break;
aktk 2:33714d7c0f45 188 }
aktk 2:33714d7c0f45 189 } else {
aktk 2:33714d7c0f45 190 break;
aktk 2:33714d7c0f45 191 }
aktk 0:cc483bea4fe3 192 #ifdef DEBUG
aktk 1:3a1fe94c6e42 193 printf("(HTTP_SERVER) *header_field_name adr: %d %s\r\n", header_field_name - 1, header_field_name);
aktk 1:3a1fe94c6e42 194 printf("(HTTP_SERVER) header_field_val adr: %d %s\r\n", header_field_val - 1, header_field_val);
aktk 0:cc483bea4fe3 195 #endif
aktk 2:33714d7c0f45 196 } while(1);
aktk 2:33714d7c0f45 197
aktk 2:33714d7c0f45 198 // if the request is to switching to the WebSocket Server
aktk 2:33714d7c0f45 199 if( !strcmp(filed_Connection, "Upgrade") &&
aktk 2:33714d7c0f45 200 !strcmp(field_Upgrade, "websocket") &&
aktk 2:33714d7c0f45 201 field_Sec_WebSocket_Key != NULL &&
aktk 2:33714d7c0f45 202 !strcmp(field_Sec_WebSocket_Version, "13") &&
aktk 2:33714d7c0f45 203 field_Origin != NULL) {
aktk 2:33714d7c0f45 204 DEBUG_PRINT_LINE("(HTTP_SERVER) Communication Protocol will be Upgraded to Websocket! \r\n");
aktk 2:33714d7c0f45 205 /*
aktk 2:33714d7c0f45 206 if(ws.isValid()){
aktk 2:33714d7c0f45 207 msger.resetHeader();
aktk 2:33714d7c0f45 208 msger.setStatusLine(101, "Switching Protocols");
aktk 2:33714d7c0f45 209 if(msger.msger.setHeaderField("Connection", "Upgrade")) printf("(HTTP_SERVER)buffer over flow@ResposeMessenger");
aktk 2:33714d7c0f45 210 if(msger.msger.setHeaderField("Upgrade", "websocket")) printf("(HTTP_SERVER)buffer over flow@ResposeMessenger");
aktk 2:33714d7c0f45 211 if(msger.msger.setHeaderField("Sec-WebSocket-Accept", ...)) printf("(HTTP_SERVER)buffer over flow@ResposeMessenger");
aktk 2:33714d7c0f45 212 if(msger.msger.setHeaderField("Access-Control-Allow-Origin", "*")) printf("(HTTP_SERVER)buffer over flow@ResposeMessenger");
aktk 2:33714d7c0f45 213 ...
aktk 0:cc483bea4fe3 214 }
aktk 2:33714d7c0f45 215 */
aktk 2:33714d7c0f45 216 } else {
aktk 2:33714d7c0f45 217 DEBUG_PRINT_LINE("(HTTP_SERVER) Communication Protocol won't be Upgraded.\r\n");
aktk 2:33714d7c0f45 218 msger.setStatusLine(426, "Upgrade Required");
aktk 2:33714d7c0f45 219 if(msger.setHeaderField("Connection", "Close"))printf("buffer over flow");
aktk 2:33714d7c0f45 220 }
aktk 2:33714d7c0f45 221
aktk 1:3a1fe94c6e42 222
aktk 0:cc483bea4fe3 223 #ifdef DEBUG
aktk 0:cc483bea4fe3 224 //printf("status code : %d\r\n", status_code);
aktk 0:cc483bea4fe3 225 //printf("content type: %s\r\n", content_type);
aktk 0:cc483bea4fe3 226 #endif
aktk 0:cc483bea4fe3 227
aktk 0:cc483bea4fe3 228 // send response
aktk 0:cc483bea4fe3 229 msger.sendHTTPResponse(tcpcon, fhandl);
aktk 0:cc483bea4fe3 230
aktk 0:cc483bea4fe3 231 //file close
aktk 0:cc483bea4fe3 232 #ifdef DEBUG
aktk 0:cc483bea4fe3 233 if(
aktk 0:cc483bea4fe3 234 #endif
aktk 0:cc483bea4fe3 235 fhandl.close()
aktk 0:cc483bea4fe3 236 #ifndef DEBUG
aktk 0:cc483bea4fe3 237 ;
aktk 0:cc483bea4fe3 238 #endif
aktk 0:cc483bea4fe3 239 #ifdef DEBUG
aktk 0:cc483bea4fe3 240 == 0)
aktk 1:3a1fe94c6e42 241 printf("(HTTP_SERVER) file has closed\r\n");
aktk 0:cc483bea4fe3 242 else if(EOF)
aktk 1:3a1fe94c6e42 243 printf("(HTTP_SERVER) failed to close the file\r\n");
aktk 0:cc483bea4fe3 244 #endif
aktk 0:cc483bea4fe3 245 msger.resetHeader();
aktk 1:3a1fe94c6e42 246 printf("(HTTP_SERVER) echo back done.\r\n");
aktk 0:cc483bea4fe3 247 }
aktk 1:3a1fe94c6e42 248 printf("(HTTP_SERVER) Response to Request has done\r\n");
aktk 0:cc483bea4fe3 249 }
aktk 1:3a1fe94c6e42 250 printf("(HTTP_SERVER) close connection.\r\ntcp server is listening...\r\n");
aktk 0:cc483bea4fe3 251 tcpcon.close();
aktk 1:3a1fe94c6e42 252 //tcpsvr.close();
aktk 0:cc483bea4fe3 253 led2 = false;
aktk 0:cc483bea4fe3 254 }
aktk 0:cc483bea4fe3 255 led1 = false;
aktk 0:cc483bea4fe3 256 return 0;
aktk 0:cc483bea4fe3 257 }