HTTP Server upon new mbed Ethernet Interface. Based on original code by Henry Leinen.

Dependencies:   EthernetInterface mbed-rtos mbed

Fork of HTTP_server by pablo gindel

Committer:
pabloxid
Date:
Mon Aug 05 05:51:16 2013 +0000
Revision:
4:2a34139c7246
Parent:
3:27b3a889b327
Some minor changes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pabloxid 0:fcceff3299be 1 #include "mbed.h"
pabloxid 0:fcceff3299be 2 #include "HTTPServer.h"
pabloxid 0:fcceff3299be 3
pabloxid 0:fcceff3299be 4 RequestConfig rq_conf[] = {
pabloxid 0:fcceff3299be 5 { "GET", HTTP_RT_GET },
pabloxid 0:fcceff3299be 6 { "POST", HTTP_RT_POST}
pabloxid 0:fcceff3299be 7 };
pabloxid 0:fcceff3299be 8
pabloxid 0:fcceff3299be 9 HTTPServer::HTTPServer (int port, const char* _path) {
pabloxid 0:fcceff3299be 10
pabloxid 0:fcceff3299be 11 INFO("Binding to port %d...", port);
pabloxid 0:fcceff3299be 12 if (socketServer.bind (port) < 0) {
pabloxid 0:fcceff3299be 13 ERR("Failed to bind to port !\n");
pabloxid 0:fcceff3299be 14 error("Binding");
pabloxid 0:fcceff3299be 15 }
pabloxid 0:fcceff3299be 16
pabloxid 0:fcceff3299be 17 INFO("Listening ...");
pabloxid 0:fcceff3299be 18 if (socketServer.listen(1) < 0) {
pabloxid 0:fcceff3299be 19 ERR("Failed to listen !\n");
pabloxid 0:fcceff3299be 20 error("Listening");
pabloxid 0:fcceff3299be 21 }
pabloxid 0:fcceff3299be 22
pabloxid 0:fcceff3299be 23 INFO("Connected !");
pabloxid 3:27b3a889b327 24 // set into blocking operation
pabloxid 2:dc9184e97328 25 socketServer.set_blocking (true);
pabloxid 0:fcceff3299be 26
pabloxid 0:fcceff3299be 27 path = _path;
pabloxid 4:2a34139c7246 28 msg = NULL;
pabloxid 4:2a34139c7246 29 cliente = NULL;
pabloxid 0:fcceff3299be 30
pabloxid 0:fcceff3299be 31 }
pabloxid 0:fcceff3299be 32
pabloxid 0:fcceff3299be 33 HTTPServer::~HTTPServer() { };
pabloxid 0:fcceff3299be 34
pabloxid 0:fcceff3299be 35 int HTTPServer::poll () {
pabloxid 0:fcceff3299be 36
pabloxid 0:fcceff3299be 37 cliente = new TCPSocketConnection;
pabloxid 0:fcceff3299be 38 cliente->set_blocking (false, TIMEOUT);
pabloxid 0:fcceff3299be 39
pabloxid 4:2a34139c7246 40 int retvalue = socketServer.accept (*cliente);
pabloxid 3:27b3a889b327 41
pabloxid 3:27b3a889b327 42 if (retvalue == OK) {
pabloxid 3:27b3a889b327 43 // a new connection was received
pabloxid 3:27b3a889b327 44 INFO("Client (IP=%s) is connected !", cliente->get_address());
pabloxid 3:27b3a889b327 45 msg = new HTTPMsg; // estructura para decodificar y alojar el mensaje
pabloxid 3:27b3a889b327 46
pabloxid 3:27b3a889b327 47 retvalue = pollConnection (); // esto parsea y llena las cosas contenidas en msg
pabloxid 3:27b3a889b327 48
pabloxid 3:27b3a889b327 49 if (retvalue == OK) {
pabloxid 3:27b3a889b327 50 // Handle the request
pabloxid 3:27b3a889b327 51 INFO("Handling request !");
pabloxid 4:2a34139c7246 52
pabloxid 4:2a34139c7246 53 handleRequest (); // handling request
pabloxid 4:2a34139c7246 54
pabloxid 3:27b3a889b327 55 }
pabloxid 3:27b3a889b327 56 delete msg;
pabloxid 3:27b3a889b327 57 } else { // retvalue == ERROR
pabloxid 4:2a34139c7246 58 ERR("Error accepting client");
pabloxid 0:fcceff3299be 59 }
pabloxid 0:fcceff3299be 60
pabloxid 0:fcceff3299be 61 delete cliente;
pabloxid 0:fcceff3299be 62
pabloxid 2:dc9184e97328 63 INFO("Leaving polling thread\n");
pabloxid 3:27b3a889b327 64 return retvalue;
pabloxid 3:27b3a889b327 65
pabloxid 0:fcceff3299be 66 }
pabloxid 0:fcceff3299be 67
pabloxid 0:fcceff3299be 68 int HTTPServer::pollConnection () {
pabloxid 0:fcceff3299be 69
pabloxid 0:fcceff3299be 70 INFO("Waiting for new data in connection");
pabloxid 3:27b3a889b327 71
pabloxid 3:27b3a889b327 72 // Try receiving request line
pabloxid 4:2a34139c7246 73 int received = receiveLine ();
pabloxid 0:fcceff3299be 74
pabloxid 0:fcceff3299be 75 if (received == ERROR) {
pabloxid 3:27b3a889b327 76 // there was an error, probably the connection was closed, so close this connection as well
pabloxid 0:fcceff3299be 77 INFO("No more data available. Will close this connection now.");
pabloxid 0:fcceff3299be 78 return ERROR;
pabloxid 0:fcceff3299be 79 }
pabloxid 0:fcceff3299be 80
pabloxid 3:27b3a889b327 81 // Request has not yet been received, so try it
pabloxid 3:27b3a889b327 82 received = parseRequest ();
pabloxid 0:fcceff3299be 83
pabloxid 4:2a34139c7246 84 /*alternative (fast) parse request method:
pabloxid 4:2a34139c7246 85 * ret = sscanf(buffer, "%s %s HTTP/%*d.%*d", request, uri);
pabloxid 4:2a34139c7246 86 */
pabloxid 4:2a34139c7246 87
pabloxid 0:fcceff3299be 88 if (received == ERROR) {
pabloxid 3:27b3a889b327 89 // Invalid content received, so close the connection
pabloxid 0:fcceff3299be 90 INFO("Invalid message received, so sending negative response and closing connection !");
pabloxid 2:dc9184e97328 91 tcpsend ("HTTP/1.1 400 BadRequest\n\rContent-Length: %d\n\rContent-Type: text\n\r\n\r\n\r", 0);
pabloxid 0:fcceff3299be 92 return ERROR;
pabloxid 0:fcceff3299be 93 }
pabloxid 0:fcceff3299be 94
pabloxid 3:27b3a889b327 95 // Request has been received, try receive the headers section
pabloxid 0:fcceff3299be 96 do {
pabloxid 0:fcceff3299be 97 received = receiveLine ();
pabloxid 0:fcceff3299be 98 if (received == ERROR) {return ERROR;}
pabloxid 3:27b3a889b327 99 // First check if we received an empty line;
pabloxid 3:27b3a889b327 100 // This would indicate the end of headers section.
pabloxid 0:fcceff3299be 101 if (received == EMPTY) {
pabloxid 3:27b3a889b327 102 // there was an empty line, so the headers section is complete
pabloxid 0:fcceff3299be 103 INFO("Request Header was received completely. Performing request.");
pabloxid 4:2a34139c7246 104 received = OK;
pabloxid 0:fcceff3299be 105 break;
pabloxid 0:fcceff3299be 106 } else {
pabloxid 3:27b3a889b327 107 // parse header field
pabloxid 3:27b3a889b327 108 if (parseHeader() != OK) {
pabloxid 0:fcceff3299be 109 WARN("Invalid message header received !");
pabloxid 3:27b3a889b327 110 }
pabloxid 0:fcceff3299be 111 }
pabloxid 3:27b3a889b327 112 } while (received > 0);
pabloxid 0:fcceff3299be 113
pabloxid 0:fcceff3299be 114 INFO("Leaving poll function!");
pabloxid 0:fcceff3299be 115 return received;
pabloxid 0:fcceff3299be 116 }
pabloxid 0:fcceff3299be 117
pabloxid 0:fcceff3299be 118 int HTTPServer::receiveLine () {
pabloxid 0:fcceff3299be 119
pabloxid 0:fcceff3299be 120 buffer[0] = 0;
pabloxid 0:fcceff3299be 121
pabloxid 0:fcceff3299be 122 int i;
pabloxid 0:fcceff3299be 123
pabloxid 0:fcceff3299be 124 // Try to receive up to the max number of characters
pabloxid 0:fcceff3299be 125 for (i=0; i<BUFFER_SIZE-1; i++) {
pabloxid 0:fcceff3299be 126 int c = cliente->receive (buffer+i, 1);
pabloxid 0:fcceff3299be 127 // Check that - if no character was currently received - the timeout period is reached.
pabloxid 0:fcceff3299be 128 if (c == 0 || c == -1) {
pabloxid 0:fcceff3299be 129 // no character was read, so check if operation timed out
pabloxid 4:2a34139c7246 130 ERR("Timeout occured in function 'receiveLine'.");
pabloxid 4:2a34139c7246 131 return ERROR;
pabloxid 0:fcceff3299be 132 }
pabloxid 0:fcceff3299be 133 // Check if line terminating character was received
pabloxid 0:fcceff3299be 134 if (buffer[i] == '\n') {break;}
pabloxid 0:fcceff3299be 135 }
pabloxid 0:fcceff3299be 136 // Terminate with \0
pabloxid 0:fcceff3299be 137 buffer[i] = 0;
pabloxid 0:fcceff3299be 138
pabloxid 0:fcceff3299be 139 // Trim for '\r' linefeed at the end
pabloxid 0:fcceff3299be 140 if (i>0 && buffer[i-1] == '\r') {
pabloxid 0:fcceff3299be 141 i--;
pabloxid 0:fcceff3299be 142 buffer[i] = 0;
pabloxid 0:fcceff3299be 143 }
pabloxid 0:fcceff3299be 144
pabloxid 0:fcceff3299be 145 // return number of characters received in the line or return -2 if an empty line was received
pabloxid 0:fcceff3299be 146 if (i==0 || (i==1 && buffer[0]=='\r')) {
pabloxid 0:fcceff3299be 147 // empty line received, so return -2
pabloxid 0:fcceff3299be 148 return EMPTY;
pabloxid 0:fcceff3299be 149 }
pabloxid 0:fcceff3299be 150 // retorna número de caracteres leidos
pabloxid 0:fcceff3299be 151 return i;
pabloxid 0:fcceff3299be 152 }
pabloxid 0:fcceff3299be 153
pabloxid 3:27b3a889b327 154 int HTTPServer::parseRequest () {
pabloxid 0:fcceff3299be 155
pabloxid 0:fcceff3299be 156 // Check if buffer content is not long enough.
pabloxid 0:fcceff3299be 157 if (strlen(buffer) < MIN_LONG) {
pabloxid 0:fcceff3299be 158 ERR("Buffer content is invalid or too short.");
pabloxid 0:fcceff3299be 159 return ERROR;
pabloxid 0:fcceff3299be 160 }
pabloxid 0:fcceff3299be 161
pabloxid 0:fcceff3299be 162 std::vector<std::string> args;
pabloxid 0:fcceff3299be 163
pabloxid 0:fcceff3299be 164 int argno = 0;
pabloxid 0:fcceff3299be 165 // decompose string into a list of arguments
pabloxid 0:fcceff3299be 166 int start = 0; // current starting char
pabloxid 0:fcceff3299be 167 int nLen = strlen(buffer)+1;
pabloxid 0:fcceff3299be 168 for (int i=0; i<nLen; i++) {
pabloxid 0:fcceff3299be 169 if ((buffer[i] == ' ') || (buffer[i] == '\n') || (buffer[i] == 0)) {
pabloxid 0:fcceff3299be 170 // new arg found
pabloxid 0:fcceff3299be 171 buffer[i] = 0;
pabloxid 0:fcceff3299be 172 if (argno++ == 1) {
pabloxid 0:fcceff3299be 173 // it's the uri
pabloxid 0:fcceff3299be 174 // parse the uri args
pabloxid 0:fcceff3299be 175 parseUriArgs (&buffer[start]);
pabloxid 0:fcceff3299be 176 }
pabloxid 0:fcceff3299be 177 INFO("Found argument \"%s\"", &buffer[start]);
pabloxid 0:fcceff3299be 178 args.push_back(&buffer[start]);
pabloxid 0:fcceff3299be 179 start = i+1;
pabloxid 0:fcceff3299be 180 }
pabloxid 0:fcceff3299be 181 }
pabloxid 0:fcceff3299be 182
pabloxid 0:fcceff3299be 183 // store the uri and the HTTP version
pabloxid 0:fcceff3299be 184 msg->uri = args[1];
pabloxid 0:fcceff3299be 185 msg->version = args[2];
pabloxid 0:fcceff3299be 186
pabloxid 0:fcceff3299be 187 // Find matching request type
pabloxid 0:fcceff3299be 188 for (int i=0; i<sizeof(rq_conf)/sizeof(RequestConfig) ; i++) {
pabloxid 0:fcceff3299be 189 if (args.at(0) == rq_conf[i].request_string) {
pabloxid 0:fcceff3299be 190 msg->request = rq_conf[i].request_type;
pabloxid 0:fcceff3299be 191 }
pabloxid 0:fcceff3299be 192 }
pabloxid 0:fcceff3299be 193
pabloxid 3:27b3a889b327 194 // init body section length
pabloxid 3:27b3a889b327 195 msg->body_length = 0;
pabloxid 3:27b3a889b327 196
pabloxid 0:fcceff3299be 197 return OK;
pabloxid 0:fcceff3299be 198 }
pabloxid 0:fcceff3299be 199
pabloxid 0:fcceff3299be 200 int HTTPServer::parseHeader () {
pabloxid 0:fcceff3299be 201
pabloxid 0:fcceff3299be 202 // Check if the buffer content is too short to be meaningful
pabloxid 0:fcceff3299be 203 if (strlen(buffer) < MIN_LONG) {return ERROR;}
pabloxid 0:fcceff3299be 204
pabloxid 0:fcceff3299be 205 // decompose string into a touple of <field name> : <field value>
pabloxid 0:fcceff3299be 206 int value_start = 0;
pabloxid 0:fcceff3299be 207 int buflen = strlen(buffer)+1;
pabloxid 0:fcceff3299be 208 for (int i=0; i<buflen; i++) {
pabloxid 0:fcceff3299be 209 if (buffer[i] == ':') {
pabloxid 0:fcceff3299be 210 // touple found
pabloxid 0:fcceff3299be 211 buffer[i] = 0;
pabloxid 0:fcceff3299be 212 value_start = i+1;
pabloxid 3:27b3a889b327 213 // headers storage is disabled; uncomment next line to enable
pabloxid 3:27b3a889b327 214 // msg->headers[buffer] = &buffer[value_start];
pabloxid 0:fcceff3299be 215 INFO("Header name=\"%s\" : value=\"%s\".", buffer, &buffer[value_start]);
pabloxid 3:27b3a889b327 216 // Look for "Content-Length" header
pabloxid 3:27b3a889b327 217 if (strcmp (buffer, "Content-Length") == 0) {
pabloxid 3:27b3a889b327 218 msg->body_length = atoi(&buffer[value_start]);
pabloxid 3:27b3a889b327 219 INFO ("Body section found. Length: %i", msg->body_length);
pabloxid 3:27b3a889b327 220 }
pabloxid 0:fcceff3299be 221 return OK;
pabloxid 0:fcceff3299be 222 }
pabloxid 0:fcceff3299be 223 }
pabloxid 0:fcceff3299be 224
pabloxid 3:27b3a889b327 225 ERR("Did not receive a valid header : \"%s\".", buffer);
pabloxid 0:fcceff3299be 226 return ERROR;
pabloxid 0:fcceff3299be 227 }
pabloxid 0:fcceff3299be 228
pabloxid 0:fcceff3299be 229 int HTTPServer::parseUriArgs (char *uri_buffer) {
pabloxid 0:fcceff3299be 230
pabloxid 0:fcceff3299be 231 // Check if the buffer content is too short to be meaningful
pabloxid 0:fcceff3299be 232 if (strlen(uri_buffer) < MIN_LONG) {return ERROR;}
pabloxid 0:fcceff3299be 233
pabloxid 0:fcceff3299be 234 int args_start = -1;
pabloxid 0:fcceff3299be 235 int value_start = -1;
pabloxid 0:fcceff3299be 236 int buflen = strlen(uri_buffer) + 1;
pabloxid 0:fcceff3299be 237 char* argname = NULL;
pabloxid 0:fcceff3299be 238 char* valuename = NULL;
pabloxid 0:fcceff3299be 239 for (int i=0; i<buflen; i++) {
pabloxid 4:2a34139c7246 240 if (args_start == -1) { // args section not yet found
pabloxid 0:fcceff3299be 241 if (uri_buffer[i] == '?') { // starts with a question mark, so got it
pabloxid 0:fcceff3299be 242 uri_buffer[i] = 0;
pabloxid 4:2a34139c7246 243 args_start = i; // set the start of the args section
pabloxid 0:fcceff3299be 244 INFO("Argument section found !");
pabloxid 0:fcceff3299be 245 }
pabloxid 4:2a34139c7246 246 } else { // search arg-value touples
pabloxid 4:2a34139c7246 247 if (argname == NULL) { // arg-name found ?
pabloxid 0:fcceff3299be 248 if (uri_buffer[i] == '=') {
pabloxid 3:27b3a889b327 249 // yes, separate the arg-name
pabloxid 0:fcceff3299be 250 uri_buffer[i] = 0;
pabloxid 0:fcceff3299be 251 argname = &uri_buffer[args_start];
pabloxid 0:fcceff3299be 252 value_start = i+1;
pabloxid 0:fcceff3299be 253 INFO("Argument name %s", argname);
pabloxid 0:fcceff3299be 254 }
pabloxid 0:fcceff3299be 255 } else { // search for end of value
pabloxid 0:fcceff3299be 256 if ((uri_buffer[i] == '&') || (uri_buffer[i] == 0) || (uri_buffer[i] == '\r') || (uri_buffer[i] == '\n')) {
pabloxid 0:fcceff3299be 257 buffer[i] = 0;
pabloxid 0:fcceff3299be 258 valuename = &uri_buffer[value_start];
pabloxid 0:fcceff3299be 259 INFO("Argument value %s", valuename);
pabloxid 3:27b3a889b327 260 msg->uri_args[argname] = valuename;
pabloxid 3:27b3a889b327 261 // reset all indicators
pabloxid 0:fcceff3299be 262 argname = NULL;
pabloxid 0:fcceff3299be 263 valuename = NULL;
pabloxid 0:fcceff3299be 264 }
pabloxid 0:fcceff3299be 265 }
pabloxid 0:fcceff3299be 266 }
pabloxid 0:fcceff3299be 267 }
pabloxid 0:fcceff3299be 268 return OK;
pabloxid 0:fcceff3299be 269 }
pabloxid 0:fcceff3299be 270
pabloxid 0:fcceff3299be 271 void HTTPServer::handleRequest () {
pabloxid 0:fcceff3299be 272
pabloxid 0:fcceff3299be 273 int err_;
pabloxid 0:fcceff3299be 274
pabloxid 0:fcceff3299be 275 switch (msg->request) {
pabloxid 0:fcceff3299be 276 case HTTP_RT_GET:
pabloxid 0:fcceff3299be 277 INFO("Dispatching GET Request.");
pabloxid 0:fcceff3299be 278 err_ = handleGetRequest();
pabloxid 0:fcceff3299be 279 break;
pabloxid 0:fcceff3299be 280 case HTTP_RT_POST:
pabloxid 0:fcceff3299be 281 INFO("Dispatching POST request.");
pabloxid 0:fcceff3299be 282 err_ = handlePostRequest();
pabloxid 0:fcceff3299be 283 break;
pabloxid 0:fcceff3299be 284 default:
pabloxid 0:fcceff3299be 285 INFO("Error in handleRequest, unhandled request type.");
pabloxid 0:fcceff3299be 286 err_ = 501; // HTTP_NotImplemented
pabloxid 0:fcceff3299be 287 break;
pabloxid 0:fcceff3299be 288 }
pabloxid 0:fcceff3299be 289
pabloxid 0:fcceff3299be 290 // if any of these functions returns a negative number, call the error handler
pabloxid 0:fcceff3299be 291 if (err_ > 0) {
pabloxid 0:fcceff3299be 292 handleError (err_);
pabloxid 0:fcceff3299be 293 }
pabloxid 0:fcceff3299be 294
pabloxid 0:fcceff3299be 295 }
pabloxid 0:fcceff3299be 296
pabloxid 0:fcceff3299be 297 int HTTPServer::handleGetRequest() {
pabloxid 0:fcceff3299be 298
pabloxid 2:dc9184e97328 299 int retval = OK; //success
pabloxid 0:fcceff3299be 300
pabloxid 2:dc9184e97328 301 INFO("Handling Get Request.");
pabloxid 0:fcceff3299be 302
pabloxid 0:fcceff3299be 303 // maping to root path
pabloxid 0:fcceff3299be 304 std::string reqPath = path + msg->uri.substr(1);
pabloxid 0:fcceff3299be 305
pabloxid 0:fcceff3299be 306 // Check if we received a directory with the local path
pabloxid 0:fcceff3299be 307 if (reqPath.substr(reqPath.length()-1, 1) == "/") {
pabloxid 0:fcceff3299be 308 // yes, we shall append the default page name
pabloxid 0:fcceff3299be 309 reqPath += "index.htm";
pabloxid 0:fcceff3299be 310 }
pabloxid 0:fcceff3299be 311
pabloxid 0:fcceff3299be 312 INFO("Mapping \"%s\" to \"%s\"", msg->uri.c_str(), reqPath.c_str());
pabloxid 0:fcceff3299be 313
pabloxid 2:dc9184e97328 314 FILE *file = fopen(reqPath.c_str(), "r");
pabloxid 2:dc9184e97328 315 if (file != NULL) {
pabloxid 0:fcceff3299be 316
pabloxid 2:dc9184e97328 317 // File was found and can be returned; first determine the size
pabloxid 2:dc9184e97328 318 fseek (file, 0, SEEK_END);
pabloxid 2:dc9184e97328 319 int size = ftell (file);
pabloxid 2:dc9184e97328 320 fseek (file, 0, SEEK_SET);
pabloxid 0:fcceff3299be 321
pabloxid 2:dc9184e97328 322 startResponse (200, size); // response: 200 = HTTP_Ok
pabloxid 2:dc9184e97328 323 while (!feof(file) && !ferror(file)) {
pabloxid 4:2a34139c7246 324 // TODO: handle filesystem errors too
pabloxid 3:27b3a889b327 325 int count = fread (buffer, 1, CHUNK_SIZE, file);
pabloxid 2:dc9184e97328 326 INFO("Processing Response (%d bytes)!", count);
pabloxid 4:2a34139c7246 327 tcpsend (buffer, count);
pabloxid 0:fcceff3299be 328 }
pabloxid 0:fcceff3299be 329 INFO("Ending Response !");
pabloxid 0:fcceff3299be 330
pabloxid 2:dc9184e97328 331 fclose (file);
pabloxid 0:fcceff3299be 332
pabloxid 0:fcceff3299be 333 } else {
pabloxid 0:fcceff3299be 334 retval = 404;
pabloxid 0:fcceff3299be 335 ERR("Requested file was not found !");
pabloxid 0:fcceff3299be 336 }
pabloxid 0:fcceff3299be 337
pabloxid 0:fcceff3299be 338 return retval;
pabloxid 0:fcceff3299be 339
pabloxid 0:fcceff3299be 340 }
pabloxid 0:fcceff3299be 341
pabloxid 0:fcceff3299be 342 int HTTPServer::handlePostRequest() {
pabloxid 0:fcceff3299be 343
pabloxid 3:27b3a889b327 344 // Try receive the body data, if there is any
pabloxid 3:27b3a889b327 345 if (msg->body_length > 0) {
pabloxid 3:27b3a889b327 346
pabloxid 4:2a34139c7246 347 char post_buffer [msg->body_length];
pabloxid 4:2a34139c7246 348
pabloxid 4:2a34139c7246 349 INFO("Receiving body data. (%i bytes)", msg->body_length);
pabloxid 3:27b3a889b327 350
pabloxid 3:27b3a889b327 351 int bytes_read = 0;
pabloxid 3:27b3a889b327 352 while (bytes_read < msg->body_length) {
pabloxid 4:2a34139c7246 353 int result = cliente->receive_all(post_buffer+bytes_read, msg->body_length-bytes_read);
pabloxid 3:27b3a889b327 354 if (result == ERROR) {
pabloxid 3:27b3a889b327 355 WARN("Error receiving body data.");
pabloxid 3:27b3a889b327 356 break;
pabloxid 3:27b3a889b327 357 }
pabloxid 3:27b3a889b327 358 bytes_read += result;
pabloxid 3:27b3a889b327 359 }
pabloxid 3:27b3a889b327 360
pabloxid 3:27b3a889b327 361 INFO("Body data received.");
pabloxid 4:2a34139c7246 362
pabloxid 3:27b3a889b327 363 // do something
pabloxid 4:2a34139c7246 364 // use the url_decode function :)
pabloxid 4:2a34139c7246 365
pabloxid 3:27b3a889b327 366 INFO("Done !\n");
pabloxid 4:2a34139c7246 367
pabloxid 3:27b3a889b327 368 return handleGetRequest();
pabloxid 4:2a34139c7246 369
pabloxid 3:27b3a889b327 370 } else {
pabloxid 3:27b3a889b327 371 ERR("POST data not found !");
pabloxid 3:27b3a889b327 372 }
pabloxid 3:27b3a889b327 373
pabloxid 0:fcceff3299be 374 return 404;
pabloxid 0:fcceff3299be 375 }
pabloxid 0:fcceff3299be 376
pabloxid 0:fcceff3299be 377 static const char hdrStandard[] = "DNT: 1\r\n"
pabloxid 0:fcceff3299be 378 "MaxAge: 0\r\n"
pabloxid 0:fcceff3299be 379 "Connection: Keep-Alive\r\n"
pabloxid 2:dc9184e97328 380 "Content-Type: text/html\r\n" // TODO: handle file types
pabloxid 0:fcceff3299be 381 "Server: mbed embedded\r\n"
pabloxid 0:fcceff3299be 382 "Accessible: 1\r\n"
pabloxid 3:27b3a889b327 383 "Pragma: no-cache\r\n"
pabloxid 3:27b3a889b327 384 "Cache-control: no-cache;no-store\r\n"
pabloxid 3:27b3a889b327 385 "Expires: 0\r\n"
pabloxid 0:fcceff3299be 386 "\r\n";
pabloxid 0:fcceff3299be 387
pabloxid 2:dc9184e97328 388 void HTTPServer::startResponse (int returnCode, int nLen) {
pabloxid 0:fcceff3299be 389
pabloxid 2:dc9184e97328 390 INFO("Starting response (%d bytes in total)!", nLen);
pabloxid 2:dc9184e97328 391
pabloxid 2:dc9184e97328 392 tcpsend ("HTTP/1.1 %d OK\r\n", returnCode);
pabloxid 2:dc9184e97328 393 tcpsend ("Content-Length: %d\r\n", nLen); // Add 2 chars for the terminating CR+LF
pabloxid 0:fcceff3299be 394 INFO("Sending standard headers !");
pabloxid 2:dc9184e97328 395 tcpsend (hdrStandard);
pabloxid 0:fcceff3299be 396
pabloxid 2:dc9184e97328 397 INFO("Done !");
pabloxid 0:fcceff3299be 398
pabloxid 0:fcceff3299be 399 }
pabloxid 0:fcceff3299be 400
pabloxid 0:fcceff3299be 401 static const char* errorPage = "<HTML><HEAD><META content=\"text/html\" http-equiv=Content-Type></HEAD><BODY><h1>Error</h1><P>HTTPServer Error<P></BODY></HTML>\r\n\r\n";
pabloxid 0:fcceff3299be 402
pabloxid 0:fcceff3299be 403 void HTTPServer::handleError (int errorCode) {
pabloxid 0:fcceff3299be 404
pabloxid 0:fcceff3299be 405 INFO("Handling error !");
pabloxid 0:fcceff3299be 406
pabloxid 2:dc9184e97328 407 tcpsend ("HTTP/1.1 %d Error\r\n", errorCode);
pabloxid 2:dc9184e97328 408 tcpsend ("Content-Length: %d\r\n", strlen(errorPage));
pabloxid 2:dc9184e97328 409 tcpsend ("Content-Type: text/html\r\nServer: mbed embedded\r\n\r\n");
pabloxid 2:dc9184e97328 410 tcpsend (errorPage); // TODO: better error page (handle error type)
pabloxid 0:fcceff3299be 411
pabloxid 0:fcceff3299be 412 INFO("Done !");
pabloxid 0:fcceff3299be 413
pabloxid 0:fcceff3299be 414 }
pabloxid 3:27b3a889b327 415
pabloxid 3:27b3a889b327 416 ////////////////////////////////////////////////////////////////////////////////////////////////////
pabloxid 3:27b3a889b327 417 // UTILS //
pabloxid 3:27b3a889b327 418 ////////////////////////////////////////////////////////////////////////////////////////////////////
pabloxid 3:27b3a889b327 419
pabloxid 3:27b3a889b327 420 #include <ctype.h>
pabloxid 3:27b3a889b327 421
pabloxid 3:27b3a889b327 422 /* Converts a hex character to its integer value */
pabloxid 3:27b3a889b327 423 char from_hex (char ch) {
pabloxid 3:27b3a889b327 424 return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
pabloxid 3:27b3a889b327 425 }
pabloxid 3:27b3a889b327 426
pabloxid 3:27b3a889b327 427 /* Returns a url-decoded version of str */
pabloxid 3:27b3a889b327 428 void url_decode (char *str) {
pabloxid 3:27b3a889b327 429 char *lee = str, *escribe = str;
pabloxid 3:27b3a889b327 430 while (*lee) {
pabloxid 3:27b3a889b327 431 if (*lee == '%') {
pabloxid 3:27b3a889b327 432 if (lee[1] && lee[2]) {
pabloxid 3:27b3a889b327 433 *escribe++ = from_hex(lee[1])<<4 | from_hex(lee[2]);
pabloxid 3:27b3a889b327 434 lee += 2;
pabloxid 3:27b3a889b327 435 }
pabloxid 3:27b3a889b327 436 } else if (*lee == '+') {
pabloxid 3:27b3a889b327 437 *escribe++ = ' ';
pabloxid 3:27b3a889b327 438 } else {
pabloxid 3:27b3a889b327 439 *escribe++ = *lee;
pabloxid 3:27b3a889b327 440 }
pabloxid 3:27b3a889b327 441 lee++;
pabloxid 3:27b3a889b327 442 }
pabloxid 3:27b3a889b327 443 *escribe = 0;
pabloxid 3:27b3a889b327 444 }