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:
Tue Jul 30 04:37:09 2013 +0000
Revision:
3:27b3a889b327
Parent:
2:dc9184e97328
Child:
4:2a34139c7246
some fixes; post handling added

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