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:
Fri Mar 16 21:55:50 2018 +0000
Revision:
13:b6dd6ed0060b
Parent:
11:0ee7d100db24
merged

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aktk 0:cc483bea4fe3 1 #include "ResponseMessenger.h"
aktk 0:cc483bea4fe3 2
aktk 0:cc483bea4fe3 3 const char ResponseMessenger::http_ver[9] = "HTTP/1.1";
aktk 0:cc483bea4fe3 4 ResponseMessenger::ResponseMessenger()
aktk 0:cc483bea4fe3 5 {
aktk 0:cc483bea4fe3 6 // Status-Line
aktk 0:cc483bea4fe3 7 status_code = 0;
aktk 0:cc483bea4fe3 8 reason_phrase[0] = '\0';
aktk 0:cc483bea4fe3 9 header_field_buffer[0]='\0';
aktk 0:cc483bea4fe3 10 // Response Header
aktk 0:cc483bea4fe3 11 }
aktk 0:cc483bea4fe3 12 ResponseMessenger::~ResponseMessenger()
aktk 0:cc483bea4fe3 13 {
aktk 0:cc483bea4fe3 14 }
aktk 0:cc483bea4fe3 15 int ResponseMessenger::resetHeader()
aktk 0:cc483bea4fe3 16 {
aktk 0:cc483bea4fe3 17 // Status-Line
aktk 0:cc483bea4fe3 18 status_code = 0;
aktk 0:cc483bea4fe3 19 reason_phrase[0] = '\0';
aktk 2:33714d7c0f45 20 // Response Header
aktk 0:cc483bea4fe3 21 header_field_buffer[0]='\0';
aktk 0:cc483bea4fe3 22 return 0;
aktk 0:cc483bea4fe3 23 }
aktk 0:cc483bea4fe3 24 int ResponseMessenger::setStatusLine(
aktk 0:cc483bea4fe3 25 int arg_status_code,
aktk 0:cc483bea4fe3 26 const char* arg_reason_phrase
aktk 0:cc483bea4fe3 27 )
aktk 0:cc483bea4fe3 28 {
aktk 0:cc483bea4fe3 29 status_code = arg_status_code;
aktk 0:cc483bea4fe3 30 strcpy(reason_phrase, arg_reason_phrase);
aktk 0:cc483bea4fe3 31
aktk 0:cc483bea4fe3 32 // To be safe on the sage side
aktk 0:cc483bea4fe3 33 reason_phrase[REASON_PHRASE_SIZE - 1] = '\0';
aktk 0:cc483bea4fe3 34 // Send 0 if arg str size is too big, else -1.
aktk 0:cc483bea4fe3 35 if (strlen(arg_reason_phrase) < REASON_PHRASE_SIZE)
aktk 0:cc483bea4fe3 36 return 0;
aktk 0:cc483bea4fe3 37 else
aktk 0:cc483bea4fe3 38 return -1;
aktk 0:cc483bea4fe3 39 }
aktk 0:cc483bea4fe3 40
aktk 0:cc483bea4fe3 41 int ResponseMessenger::setHeaderField(
aktk 0:cc483bea4fe3 42 const char* arg_field_name, const char* arg_field_val)
aktk 0:cc483bea4fe3 43 {
aktk 11:0ee7d100db24 44 const int nField = 7;
aktk 0:cc483bea4fe3 45 char registered_field_name[nField][32]= {
aktk 0:cc483bea4fe3 46 "Connection",
aktk 0:cc483bea4fe3 47 "Location",
aktk 0:cc483bea4fe3 48 "Keep-Alive",
aktk 10:4a48594c2f44 49 "Content-Type",
aktk 10:4a48594c2f44 50 "Upgrade",
aktk 10:4a48594c2f44 51 "Sec-WebSocket-Accept",
aktk 10:4a48594c2f44 52 "Access-Control-Allow-Origin"
aktk 0:cc483bea4fe3 53 };
aktk 0:cc483bea4fe3 54 bool flag = false;
aktk 0:cc483bea4fe3 55 char header_field_line_buffer[128];
aktk 0:cc483bea4fe3 56 int buffer_size = strlen(header_field_buffer);
aktk 0:cc483bea4fe3 57
aktk 0:cc483bea4fe3 58 for (int i = 0; i < nField; i++) {
aktk 0:cc483bea4fe3 59 if(strcmp(arg_field_name, registered_field_name[i]) == 0)
aktk 0:cc483bea4fe3 60 flag = true;
aktk 0:cc483bea4fe3 61 }
aktk 0:cc483bea4fe3 62 if(flag) {
aktk 0:cc483bea4fe3 63 sprintf(header_field_line_buffer, "%s: %s\r\n", arg_field_name, arg_field_val);
aktk 0:cc483bea4fe3 64 strcat(header_field_buffer, header_field_line_buffer);
aktk 11:0ee7d100db24 65 //printf("(RM) header field: \r\n%s\r\n", header_field_buffer);
aktk 0:cc483bea4fe3 66 }
aktk 0:cc483bea4fe3 67 // To be safe on the sage side
aktk 0:cc483bea4fe3 68 header_field_buffer[HEADER_FIELDS_SIZE - 1] = '\0';
aktk 0:cc483bea4fe3 69 // Send 0 if arg str size is too big, else -1.
aktk 0:cc483bea4fe3 70 if (buffer_size + strlen(arg_field_name) + strlen(arg_field_val) < HEADER_FIELDS_SIZE + 1)
aktk 0:cc483bea4fe3 71 return 0;
aktk 0:cc483bea4fe3 72 else
aktk 0:cc483bea4fe3 73 return -1;
aktk 0:cc483bea4fe3 74 }
aktk 0:cc483bea4fe3 75
aktk 0:cc483bea4fe3 76 int ResponseMessenger::setHeaderField(
aktk 0:cc483bea4fe3 77 const char* arg_field_name, int arg_field_val)
aktk 0:cc483bea4fe3 78 {
aktk 0:cc483bea4fe3 79 const int nField = 1;
aktk 0:cc483bea4fe3 80 char registered_field_name[nField][32]= {
aktk 0:cc483bea4fe3 81 "Content-Length"
aktk 0:cc483bea4fe3 82 };
aktk 0:cc483bea4fe3 83 bool flag = false;
aktk 0:cc483bea4fe3 84 char header_field_line_buffer[128];
aktk 0:cc483bea4fe3 85 int buffer_size = strlen(header_field_buffer);
aktk 0:cc483bea4fe3 86
aktk 0:cc483bea4fe3 87 for (int i = 0; i < nField; i++) {
aktk 0:cc483bea4fe3 88 if(strcmp(arg_field_name, registered_field_name[i]) == 0)
aktk 0:cc483bea4fe3 89 flag = true;
aktk 0:cc483bea4fe3 90 }
aktk 0:cc483bea4fe3 91 if(flag) {
aktk 0:cc483bea4fe3 92 sprintf(header_field_line_buffer, "%s: %d\r\n", arg_field_name, arg_field_val);
aktk 0:cc483bea4fe3 93 strcat(header_field_buffer, header_field_line_buffer);
aktk 11:0ee7d100db24 94 //printf("(RM) header field: \r\n%s\r\n", header_field_buffer);
aktk 0:cc483bea4fe3 95 }
aktk 0:cc483bea4fe3 96 // To be safe on the sage side
aktk 0:cc483bea4fe3 97 header_field_buffer[HEADER_FIELDS_SIZE - 1] = '\0';
aktk 0:cc483bea4fe3 98 // Send 0 if arg str size is too big, else -1.
aktk 0:cc483bea4fe3 99 if (buffer_size + strlen(arg_field_name) + 10 < HEADER_FIELDS_SIZE + 1)
aktk 0:cc483bea4fe3 100 return 0;
aktk 0:cc483bea4fe3 101 else
aktk 0:cc483bea4fe3 102 return -1;
aktk 0:cc483bea4fe3 103 }
aktk 1:3a1fe94c6e42 104
aktk 1:3a1fe94c6e42 105 int ResponseMessenger::rmHeaderField(
aktk 1:3a1fe94c6e42 106 const char* arg_field_name)
aktk 1:3a1fe94c6e42 107 {
aktk 1:3a1fe94c6e42 108 char* removedLineHead;
aktk 1:3a1fe94c6e42 109 char* removedLineEnd;
aktk 1:3a1fe94c6e42 110 int buffer_size;
aktk 1:3a1fe94c6e42 111
aktk 1:3a1fe94c6e42 112 // Look for the head of the line to want to remove
aktk 1:3a1fe94c6e42 113 removedLineHead = strstr(header_field_buffer, arg_field_name);
aktk 3:59884bc0a238 114 if(removedLineHead == NULL) return -1;
aktk 1:3a1fe94c6e42 115 // Look for the first "\r\n" which is the end of the line
aktk 1:3a1fe94c6e42 116 removedLineEnd = strstr(removedLineHead, "\r\n");
aktk 1:3a1fe94c6e42 117 removedLineEnd += 3; //pointing next line head or '\0' if the line of the last one.
aktk 1:3a1fe94c6e42 118 buffer_size = strlen(removedLineEnd);
aktk 1:3a1fe94c6e42 119
aktk 1:3a1fe94c6e42 120 for(int i = 0; i < buffer_size + 1; i++)
aktk 1:3a1fe94c6e42 121 removedLineHead[i] = removedLineEnd[i];
aktk 1:3a1fe94c6e42 122
aktk 1:3a1fe94c6e42 123 return 0;
aktk 1:3a1fe94c6e42 124 }
aktk 1:3a1fe94c6e42 125
aktk 0:cc483bea4fe3 126 int ResponseMessenger::getStatusCode()
aktk 0:cc483bea4fe3 127 {
aktk 0:cc483bea4fe3 128 return status_code;
aktk 0:cc483bea4fe3 129 }
aktk 0:cc483bea4fe3 130
aktk 0:cc483bea4fe3 131 char ResponseMessenger::sendHTTPResponse(
aktk 0:cc483bea4fe3 132 TCPSocketConnection &arg_connection)
aktk 0:cc483bea4fe3 133 {
aktk 0:cc483bea4fe3 134 int err_log = 0;
aktk 0:cc483bea4fe3 135 int err_code = 0;
aktk 0:cc483bea4fe3 136 enum {
aktk 0:cc483bea4fe3 137 MAX_BUFFER_SIZE = 1024
aktk 0:cc483bea4fe3 138 };
aktk 0:cc483bea4fe3 139 char buffer[MAX_BUFFER_SIZE] = "\0";
aktk 0:cc483bea4fe3 140
aktk 0:cc483bea4fe3 141 //
aktk 0:cc483bea4fe3 142 // Header
aktk 0:cc483bea4fe3 143 //
aktk 6:4eb469f51570 144 printf("(RM) [send]Header\r\n");
aktk 0:cc483bea4fe3 145 // Status Line
aktk 0:cc483bea4fe3 146 sprintf(buffer, "%s %d %s\r\n", http_ver, status_code, reason_phrase);
aktk 0:cc483bea4fe3 147 buffer[MAX_BUFFER_SIZE - 1] = '\0';
aktk 0:cc483bea4fe3 148 err_log = arg_connection.send_all(buffer, strlen(buffer));
aktk 0:cc483bea4fe3 149 if(err_log < 0) err_code = ((err_code << 1) | 1);
aktk 0:cc483bea4fe3 150 // Response Header
aktk 0:cc483bea4fe3 151 err_log = arg_connection.send_all(header_field_buffer, strlen(header_field_buffer));
aktk 0:cc483bea4fe3 152 if(err_log < 0) err_code = ((err_code << 1) | 1);
aktk 0:cc483bea4fe3 153 // Blank line
aktk 0:cc483bea4fe3 154 err_log = arg_connection.send_all("\r\n", strlen("\r\n"));
aktk 0:cc483bea4fe3 155 if(err_log < 0) err_code = ((err_code << 1) | 1);
aktk 6:4eb469f51570 156 printf("(RM) [Header has sent]\r\n");
aktk 0:cc483bea4fe3 157 //return error code
aktk 0:cc483bea4fe3 158 return err_code << 2;
aktk 0:cc483bea4fe3 159
aktk 0:cc483bea4fe3 160 }
aktk 0:cc483bea4fe3 161
aktk 0:cc483bea4fe3 162 char ResponseMessenger::sendHTTPResponse(
aktk 0:cc483bea4fe3 163 TCPSocketConnection &arg_connection,
aktk 0:cc483bea4fe3 164 FileHandler &arg_file)
aktk 0:cc483bea4fe3 165 {
aktk 0:cc483bea4fe3 166 int err_log = 0;
aktk 0:cc483bea4fe3 167 int err_code = 0;
aktk 0:cc483bea4fe3 168 enum {
aktk 0:cc483bea4fe3 169 MAX_BUFFER_SIZE = 1024
aktk 0:cc483bea4fe3 170 };
aktk 0:cc483bea4fe3 171 signed char buffer[MAX_BUFFER_SIZE];
aktk 0:cc483bea4fe3 172
aktk 0:cc483bea4fe3 173 //
aktk 0:cc483bea4fe3 174 // Header
aktk 0:cc483bea4fe3 175 //
aktk 0:cc483bea4fe3 176 err_code = sendHTTPResponse(arg_connection);
aktk 0:cc483bea4fe3 177 //
aktk 0:cc483bea4fe3 178 // Body
aktk 0:cc483bea4fe3 179 //
aktk 0:cc483bea4fe3 180 if (arg_file.arrival() && status_code == 200) {
aktk 6:4eb469f51570 181 printf("(RM) [send]Body\r\n");
aktk 0:cc483bea4fe3 182 do {
aktk 0:cc483bea4fe3 183 int i = 0;
aktk 0:cc483bea4fe3 184 do {
aktk 0:cc483bea4fe3 185 buffer[i++] = arg_file.getc();//return a byte from file ponter, or -1 if EOF or ERROR
aktk 0:cc483bea4fe3 186 } while ((i < MAX_BUFFER_SIZE - 1) && (buffer[i - 1] != EOF));
aktk 0:cc483bea4fe3 187 if(buffer[i - 1] == EOF)buffer[i - 1] = '\0';
aktk 0:cc483bea4fe3 188 buffer[i] = '\0';
aktk 0:cc483bea4fe3 189 if (!arg_file.hasError()) {
aktk 0:cc483bea4fe3 190 err_log = arg_connection.send_all((char*)buffer, i);
aktk 6:4eb469f51570 191 //printf("(RM) buffer log: %s", buffer);
aktk 0:cc483bea4fe3 192 }
aktk 11:0ee7d100db24 193 if (arg_file.hasError()) printf("(RM)---[ERR]---\r\n");
aktk 11:0ee7d100db24 194 if (arg_file.atEOF()) printf("(RM)---[EOF]---\r\n");
aktk 0:cc483bea4fe3 195 } while (!arg_file.atEOF() && !arg_file.hasError());
aktk 6:4eb469f51570 196 printf("(RM) [Body has sent]\r\n");
aktk 0:cc483bea4fe3 197
aktk 0:cc483bea4fe3 198 if (err_log < 0) err_code = ((err_code) | 2);
aktk 0:cc483bea4fe3 199 if (!arg_file.hasError())err_code = ((err_code) | 1);
aktk 1:3a1fe94c6e42 200 } else {
aktk 6:4eb469f51570 201 printf("(RM) [No Body]\r\n");
aktk 0:cc483bea4fe3 202 }
aktk 0:cc483bea4fe3 203 return (char)err_code;
aktk 0:cc483bea4fe3 204 }