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>
handlers/ResponseMessenger.cpp@0:cc483bea4fe3, 2016-02-16 (annotated)
- Committer:
- aktk
- Date:
- Tue Feb 16 10:59:31 2016 +0000
- Revision:
- 0:cc483bea4fe3
- Child:
- 1:3a1fe94c6e42
add comment
Who changed what in which revision?
User | Revision | Line number | New 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 | 0:cc483bea4fe3 | 20 | header_field_buffer[0]='\0'; |
aktk | 0:cc483bea4fe3 | 21 | // Response Header |
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 | 0:cc483bea4fe3 | 44 | const int nField = 4; |
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 | 0:cc483bea4fe3 | 49 | "Content-Type" |
aktk | 0:cc483bea4fe3 | 50 | }; |
aktk | 0:cc483bea4fe3 | 51 | bool flag = false; |
aktk | 0:cc483bea4fe3 | 52 | char header_field_line_buffer[128]; |
aktk | 0:cc483bea4fe3 | 53 | int buffer_size = strlen(header_field_buffer); |
aktk | 0:cc483bea4fe3 | 54 | |
aktk | 0:cc483bea4fe3 | 55 | for (int i = 0; i < nField; i++) { |
aktk | 0:cc483bea4fe3 | 56 | if(strcmp(arg_field_name, registered_field_name[i]) == 0) |
aktk | 0:cc483bea4fe3 | 57 | flag = true; |
aktk | 0:cc483bea4fe3 | 58 | } |
aktk | 0:cc483bea4fe3 | 59 | if(flag) { |
aktk | 0:cc483bea4fe3 | 60 | sprintf(header_field_line_buffer, "%s: %s\r\n", arg_field_name, arg_field_val); |
aktk | 0:cc483bea4fe3 | 61 | strcat(header_field_buffer, header_field_line_buffer); |
aktk | 0:cc483bea4fe3 | 62 | printf("header field: \r\n%s\r\n", header_field_buffer); |
aktk | 0:cc483bea4fe3 | 63 | } |
aktk | 0:cc483bea4fe3 | 64 | // To be safe on the sage side |
aktk | 0:cc483bea4fe3 | 65 | header_field_buffer[HEADER_FIELDS_SIZE - 1] = '\0'; |
aktk | 0:cc483bea4fe3 | 66 | // Send 0 if arg str size is too big, else -1. |
aktk | 0:cc483bea4fe3 | 67 | if (buffer_size + strlen(arg_field_name) + strlen(arg_field_val) < HEADER_FIELDS_SIZE + 1) |
aktk | 0:cc483bea4fe3 | 68 | return 0; |
aktk | 0:cc483bea4fe3 | 69 | else |
aktk | 0:cc483bea4fe3 | 70 | return -1; |
aktk | 0:cc483bea4fe3 | 71 | } |
aktk | 0:cc483bea4fe3 | 72 | |
aktk | 0:cc483bea4fe3 | 73 | int ResponseMessenger::setHeaderField( |
aktk | 0:cc483bea4fe3 | 74 | const char* arg_field_name, int arg_field_val) |
aktk | 0:cc483bea4fe3 | 75 | { |
aktk | 0:cc483bea4fe3 | 76 | const int nField = 1; |
aktk | 0:cc483bea4fe3 | 77 | char registered_field_name[nField][32]= { |
aktk | 0:cc483bea4fe3 | 78 | "Content-Length" |
aktk | 0:cc483bea4fe3 | 79 | }; |
aktk | 0:cc483bea4fe3 | 80 | bool flag = false; |
aktk | 0:cc483bea4fe3 | 81 | char header_field_line_buffer[128]; |
aktk | 0:cc483bea4fe3 | 82 | int buffer_size = strlen(header_field_buffer); |
aktk | 0:cc483bea4fe3 | 83 | |
aktk | 0:cc483bea4fe3 | 84 | for (int i = 0; i < nField; i++) { |
aktk | 0:cc483bea4fe3 | 85 | if(strcmp(arg_field_name, registered_field_name[i]) == 0) |
aktk | 0:cc483bea4fe3 | 86 | flag = true; |
aktk | 0:cc483bea4fe3 | 87 | } |
aktk | 0:cc483bea4fe3 | 88 | if(flag) { |
aktk | 0:cc483bea4fe3 | 89 | sprintf(header_field_line_buffer, "%s: %d\r\n", arg_field_name, arg_field_val); |
aktk | 0:cc483bea4fe3 | 90 | strcat(header_field_buffer, header_field_line_buffer); |
aktk | 0:cc483bea4fe3 | 91 | printf("header field: \r\n%s\r\n", header_field_buffer); |
aktk | 0:cc483bea4fe3 | 92 | } |
aktk | 0:cc483bea4fe3 | 93 | // To be safe on the sage side |
aktk | 0:cc483bea4fe3 | 94 | header_field_buffer[HEADER_FIELDS_SIZE - 1] = '\0'; |
aktk | 0:cc483bea4fe3 | 95 | // Send 0 if arg str size is too big, else -1. |
aktk | 0:cc483bea4fe3 | 96 | if (buffer_size + strlen(arg_field_name) + 10 < HEADER_FIELDS_SIZE + 1) |
aktk | 0:cc483bea4fe3 | 97 | return 0; |
aktk | 0:cc483bea4fe3 | 98 | else |
aktk | 0:cc483bea4fe3 | 99 | return -1; |
aktk | 0:cc483bea4fe3 | 100 | } |
aktk | 0:cc483bea4fe3 | 101 | int ResponseMessenger::getStatusCode() |
aktk | 0:cc483bea4fe3 | 102 | { |
aktk | 0:cc483bea4fe3 | 103 | return status_code; |
aktk | 0:cc483bea4fe3 | 104 | } |
aktk | 0:cc483bea4fe3 | 105 | |
aktk | 0:cc483bea4fe3 | 106 | char ResponseMessenger::sendHTTPResponse( |
aktk | 0:cc483bea4fe3 | 107 | TCPSocketConnection &arg_connection) |
aktk | 0:cc483bea4fe3 | 108 | { |
aktk | 0:cc483bea4fe3 | 109 | int err_log = 0; |
aktk | 0:cc483bea4fe3 | 110 | int err_code = 0; |
aktk | 0:cc483bea4fe3 | 111 | enum { |
aktk | 0:cc483bea4fe3 | 112 | MAX_BUFFER_SIZE = 1024 |
aktk | 0:cc483bea4fe3 | 113 | }; |
aktk | 0:cc483bea4fe3 | 114 | char buffer[MAX_BUFFER_SIZE] = "\0"; |
aktk | 0:cc483bea4fe3 | 115 | |
aktk | 0:cc483bea4fe3 | 116 | // |
aktk | 0:cc483bea4fe3 | 117 | // Header |
aktk | 0:cc483bea4fe3 | 118 | // |
aktk | 0:cc483bea4fe3 | 119 | printf("[send]Header\r\n"); |
aktk | 0:cc483bea4fe3 | 120 | // Status Line |
aktk | 0:cc483bea4fe3 | 121 | sprintf(buffer, "%s %d %s\r\n", http_ver, status_code, reason_phrase); |
aktk | 0:cc483bea4fe3 | 122 | buffer[MAX_BUFFER_SIZE - 1] = '\0'; |
aktk | 0:cc483bea4fe3 | 123 | err_log = arg_connection.send_all(buffer, strlen(buffer)); |
aktk | 0:cc483bea4fe3 | 124 | if(err_log < 0) err_code = ((err_code << 1) | 1); |
aktk | 0:cc483bea4fe3 | 125 | // Response Header |
aktk | 0:cc483bea4fe3 | 126 | err_log = arg_connection.send_all(header_field_buffer, strlen(header_field_buffer)); |
aktk | 0:cc483bea4fe3 | 127 | if(err_log < 0) err_code = ((err_code << 1) | 1); |
aktk | 0:cc483bea4fe3 | 128 | // Blank line |
aktk | 0:cc483bea4fe3 | 129 | err_log = arg_connection.send_all("\r\n", strlen("\r\n")); |
aktk | 0:cc483bea4fe3 | 130 | if(err_log < 0) err_code = ((err_code << 1) | 1); |
aktk | 0:cc483bea4fe3 | 131 | printf("[Header has sent]\r\n"); |
aktk | 0:cc483bea4fe3 | 132 | //return error code |
aktk | 0:cc483bea4fe3 | 133 | return err_code << 2; |
aktk | 0:cc483bea4fe3 | 134 | |
aktk | 0:cc483bea4fe3 | 135 | } |
aktk | 0:cc483bea4fe3 | 136 | |
aktk | 0:cc483bea4fe3 | 137 | char ResponseMessenger::sendHTTPResponse( |
aktk | 0:cc483bea4fe3 | 138 | TCPSocketConnection &arg_connection, |
aktk | 0:cc483bea4fe3 | 139 | FileHandler &arg_file) |
aktk | 0:cc483bea4fe3 | 140 | { |
aktk | 0:cc483bea4fe3 | 141 | int err_log = 0; |
aktk | 0:cc483bea4fe3 | 142 | int err_code = 0; |
aktk | 0:cc483bea4fe3 | 143 | enum { |
aktk | 0:cc483bea4fe3 | 144 | MAX_BUFFER_SIZE = 1024 |
aktk | 0:cc483bea4fe3 | 145 | }; |
aktk | 0:cc483bea4fe3 | 146 | signed char buffer[MAX_BUFFER_SIZE]; |
aktk | 0:cc483bea4fe3 | 147 | |
aktk | 0:cc483bea4fe3 | 148 | // |
aktk | 0:cc483bea4fe3 | 149 | // Header |
aktk | 0:cc483bea4fe3 | 150 | // |
aktk | 0:cc483bea4fe3 | 151 | err_code = sendHTTPResponse(arg_connection); |
aktk | 0:cc483bea4fe3 | 152 | // |
aktk | 0:cc483bea4fe3 | 153 | // Body |
aktk | 0:cc483bea4fe3 | 154 | // |
aktk | 0:cc483bea4fe3 | 155 | if (arg_file.arrival() && status_code == 200) { |
aktk | 0:cc483bea4fe3 | 156 | printf("[send]Body\r\n"); |
aktk | 0:cc483bea4fe3 | 157 | do { |
aktk | 0:cc483bea4fe3 | 158 | int i = 0; |
aktk | 0:cc483bea4fe3 | 159 | do { |
aktk | 0:cc483bea4fe3 | 160 | buffer[i++] = arg_file.getc();//return a byte from file ponter, or -1 if EOF or ERROR |
aktk | 0:cc483bea4fe3 | 161 | } while ((i < MAX_BUFFER_SIZE - 1) && (buffer[i - 1] != EOF)); |
aktk | 0:cc483bea4fe3 | 162 | if(buffer[i - 1] == EOF)buffer[i - 1] = '\0'; |
aktk | 0:cc483bea4fe3 | 163 | buffer[i] = '\0'; |
aktk | 0:cc483bea4fe3 | 164 | if (!arg_file.hasError()) { |
aktk | 0:cc483bea4fe3 | 165 | err_log = arg_connection.send_all((char*)buffer, i); |
aktk | 0:cc483bea4fe3 | 166 | //printf("buffer log: %s", buffer); |
aktk | 0:cc483bea4fe3 | 167 | } |
aktk | 0:cc483bea4fe3 | 168 | if (arg_file.hasError()) printf("\r\n[ERR][ERR][ERR]\r\n"); |
aktk | 0:cc483bea4fe3 | 169 | if (arg_file.atEOF()) printf("\r\n[EOF][EOF][EOF]\r\n"); |
aktk | 0:cc483bea4fe3 | 170 | } while (!arg_file.atEOF() && !arg_file.hasError()); |
aktk | 0:cc483bea4fe3 | 171 | printf("[Body has sent]\r\n"); |
aktk | 0:cc483bea4fe3 | 172 | |
aktk | 0:cc483bea4fe3 | 173 | if (err_log < 0) err_code = ((err_code) | 2); |
aktk | 0:cc483bea4fe3 | 174 | if (!arg_file.hasError())err_code = ((err_code) | 1); |
aktk | 0:cc483bea4fe3 | 175 | } |
aktk | 0:cc483bea4fe3 | 176 | else{ |
aktk | 0:cc483bea4fe3 | 177 | printf("[No Body]\r\n"); |
aktk | 0:cc483bea4fe3 | 178 | } |
aktk | 0:cc483bea4fe3 | 179 | return (char)err_code; |
aktk | 0:cc483bea4fe3 | 180 | } |