Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: RPC_HTTP RPC_HTTP_WIZnetInterface RPC_HTTP rpc_over_http_TL_interrupter_gatePJ
Fork of HTTPServer by
Revision 4:d065642c32cc, committed 2013-05-28
- Comitter:
- leihen
- Date:
- Tue May 28 21:20:58 2013 +0000
- Parent:
- 3:d6224049b3bf
- Child:
- 5:dc88012caef1
- Commit message:
- Added parameter parsing from uri in http webrequest.
; Documentation updated.
Changed in this revision
--- a/HTTPConnection.cpp Tue May 28 01:56:14 2013 +0000
+++ b/HTTPConnection.cpp Tue May 28 21:20:58 2013 +0000
@@ -20,6 +20,20 @@
+const struct HTTPRequestConfig {
+ const char* request_string;
+ HTTPRequestType request_type;
+} g_requestConfig[] = {
+ { "GET", HTTP_RT_GET },
+ { "POST", HTTP_RT_POST},
+ { "PUT", HTTP_RT_PUT},
+ { "OPTIONS",HTTP_RT_OPTIONS},
+ { "HEAD", HTTP_RT_HEAD},
+ { "DELETE", HTTP_RT_DELETE},
+ { "TRACE", HTTP_RT_TRACE},
+ { "CONNECT",HTTP_RT_CONNECT}
+};
+
HTTPConnection::HTTPConnection()
{
@@ -136,14 +150,16 @@
int HTTPConnection::parse(char* buffer)
{
+ // Check if buffer is invalid or its content not long enough.
if ((buffer == NULL) || (strlen(buffer) < 4)) {
ERR("Buffer content is invalid or too short.");
return -1;
}
- vector<std::string> args;
+ std::vector<std::string> args;
args.clear();
+ int argno = 0;
// decompose string into a list of arguments
char s = 0; // current starting char
int nLen = strlen(buffer)+1;
@@ -151,25 +167,25 @@
if ((buffer[i] == ' ') || (buffer[i] == '\n') || (buffer[i] == 0)) {
// new arg found
buffer[i] = 0;
+ if (argno++ == 1) {
+ // its the uri
+ // parse the uri args
+ parseUriArgs(&buffer[s], m_Msg.args);
+ }
INFO("Found argument \"%s\"", &buffer[s]);
args.push_back(&buffer[s]);
s = i+1;
}
}
-
- if (args.at(0) == "GET") {
- m_Msg.request = HTTP_RT_GET;
- m_Msg.uri = args[1];
- m_Msg.version = args[2];
- }
- else {
- if (args.at(0) == "POST") {
- m_Msg.request = HTTP_RT_GET;
- m_Msg.uri = args[1];
- m_Msg.version = args[2];
- }
- else {
- INFO("unhandled message.");
+
+ // store the uri and the HTTP version
+ m_Msg.uri = args[1];
+ m_Msg.version = args[2];
+
+ // Find matching request type
+ for (int i = 0 ; i < sizeof(g_requestConfig)/sizeof(struct HTTPRequestConfig) ; i++) {
+ if (args.at(0) == g_requestConfig[i].request_string) {
+ m_Msg.request = g_requestConfig[i].request_type;
}
}
args.clear();
@@ -180,6 +196,7 @@
int HTTPConnection::parseHeader(char *buffer)
{
+ // Check if the buffer is invalid or if the content is too short to be meaningful
if ((strlen(buffer) <3) || (buffer == NULL))
return -1;
@@ -201,3 +218,49 @@
ERR("Did not recieve a valid header : \"%s\".", buffer);
return -1;
}
+
+int HTTPConnection::parseUriArgs(char *buffer, map<string,string>&args)
+{
+ // Check if the buffer is invalid or if the content is too short to be meaningful
+ if ((strlen(buffer) <3) || (buffer == NULL))
+ return -1;
+
+ int args_start = -1;
+ int value_start = -1;
+ int buflen = strlen(buffer) +1;
+ const char* argname = NULL;
+ const char* valuename = NULL;
+ for (int i = 0; i < buflen ; i++) {
+ if (args_start == -1) { // args section not yet found
+ if (buffer[i] == '?') { // starts with a question mark, so got it
+ buffer[i] = 0;
+ args_start = i; // set the start of the args section
+ INFO("Argument section found !");
+ }
+ }
+ else { // search arg-value touples
+ if (argname == NULL) { // arg-name found ?
+ if (buffer[i] == '=') {
+ // yes, separate the arg-name
+ buffer[i] = 0;
+ argname = &buffer[args_start];
+ value_start = i+1;
+ INFO("Argument name %s", argname);
+ }
+ }
+ else { // search for end of value
+ if ((buffer[i] == '&') || (buffer[i] == 0) || (buffer[i] == '\r') || (buffer[i] == '\n')) {
+ buffer[i] = 0;
+ valuename = &buffer[value_start];
+ INFO("Argument value %s", valuename);
+ args[argname] = valuename;
+ // reset all indicators
+ argname = NULL;
+ valuename = NULL;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
--- a/HTTPConnection.h Tue May 28 01:56:14 2013 +0000
+++ b/HTTPConnection.h Tue May 28 21:20:58 2013 +0000
@@ -45,7 +45,6 @@
HTTP_RT_CONNECT /*!< CONNECT request */
} HTTPRequestType;
-
/** class HTTPConnection, encapsulates one connection being made throught the HTTPServer
*
*/
@@ -58,17 +57,21 @@
{
/** Specifies the request type received
*/
- HTTPRequestType request;
+ HTTPRequestType request;
/** The uri associated with the request.
*/
- std::string uri;
+ std::string uri;
/** Contains the HTTP/1.1 or HTTP/1.0 version requested by client.
*/
- std::string version;
+ std::string version;
/** Map of headers provided by the client in the form <HeaderName>:<HeaderValue>
*/
- std::map<std::string, std::string> headers;
+ std::map<std::string, std::string> headers;
+ /** Map of arguments that came with the uri string
+ */
+ std::map<std::string, std::string> args;
} HTTPMessage;
+
/** Public constructor for HTTPConnection objects.
*
*/
@@ -99,11 +102,37 @@
TCPSocketConnection m_Tcp;
HTTPMessage m_Msg;
+
+ /** parse a HTTP request line from the content of the buffer.
+ * @param buffer : the request received from the client in the form <RequestType> <uri> <Http Version>
+ * @returns -1 if the request is invalid or 0 if the request is valid
+ */
int parse(char *buffer);
+
+ /** parses the received string in \c buffer for HTTP request headers.
+ * @param buffer : buffer which contains the string to parse for headers.
+ * @returns -1 in case of an error, otherwise returns 0
+ */
int parseHeader(char *buffer);
int receiveHeaders(const char* buffer, int nBuffSize);
+
+ /** Function which receives a line from the current Socket
+ * @param szline : will contain one line received from the socket
+ * @param nMaxLen : the size of the buffer. If the line is longer than the buffer the line is cropped at the end.
+ * @param nTimeout : if the timeout elapses, only the portion that has been received within this time will be returned.
+ * @param szLineTerm : the \c end-of-line character to be used to detect the end of the line.
+ * @returns -1 in case of an error or timeout, -2 in case of an empty line or the number of received characters.
+ */
int receiveLine(char* szLine, int nMaxLen, int nTimeout = -1, char szLineTerm = '\n');
+
+ /** parse the receoved \c uri_string for arguments which will be stored in the \c args map.
+ * @parse uri_string : the uri string which was received from the client.
+ * @parse args : the args map which will receive the argument:value touples from the \c uri_string.
+ * @returns -1 if an error occured, otherwise returns 0.
+ */
+ int parseUriArgs(char *uri_string, map<string,string>& args);
+
};
#endif // __HTTPConnection_H__
\ No newline at end of file
--- a/HTTPFsRequestHandler.cpp Tue May 28 01:56:14 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/* HTTPFsRequestHandler.cpp */
-#include "mbed.h"
-#include "HTTPFsRequestHandler.h"
-
-
-
-#if (1 && !defined(TARGET_LPC11U24))
-#define INFO(x, ...) std::printf("[HTTPFsRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__);
-#define WARN(x, ...) std::printf("[HTTPFsRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__);
-#define ERR(x, ...) std::printf("[HTTPFsRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__);
-#else
-#define INFO(x, ...)
-#define WARN(x, ...)
-#define ERR(x, ...)
-#endif
-
-
-#define MAX_BUFFERSIZE 128
-static char buffer[MAX_BUFFERSIZE];
-
-
-std::map<const char*, const char*> HTTPFsRequestHandler::m_fsMap;
-
-HTTPFsRequestHandler::HTTPFsRequestHandler(const char* rootPath, const char* localPath, HTTPConnection::HTTPMessage& Msg, TCPSocketConnection& Tcp)
- : HTTPRequestHandler(Msg, Tcp)
-{
- m_rootPath = rootPath;
- m_localPath = localPath;
-
- // Now replace the virtual root path with a mounted device path
- std::map<const char*, const char*>::iterator it;
- for (it = m_fsMap.begin() ; it != m_fsMap.end() ; it++) {
- // find best match (if the given logical path is containted in the root
- if (m_rootPath.find( it->second ) == 0) {
- m_rootPath = it->first;
- break;
- }
- }
-
- handleRequest();
-}
-
-HTTPFsRequestHandler::~HTTPFsRequestHandler()
-{
-}
-
-int HTTPFsRequestHandler::handleGetRequest()
-{
- INFO("Handling Get Request.");
- int retval = 200; //success
- std::string reqPath;
-
- // Check if we received a directory with the local bath
- if ((m_localPath.length() == 0) || (m_localPath.substr( m_localPath.length()-1, 1) == "/")) {
- // yes, we shall append the default page name
- m_localPath += "index.html";
- }
-
- reqPath = m_rootPath + m_localPath;
-
- INFO("Mapping \"%s\" to \"%s\"", msg.uri.c_str(), reqPath.c_str());
-
- FILE *fp = fopen(reqPath.c_str(), "r");
- if (fp != NULL) {
- // File was found and can be returned
-
- // first determine the size
- fseek(fp, 0, SEEK_END);
- long size = ftell(fp);
- fseek(fp, 0, SEEK_SET);
-
- startResponse(200, size);
- while(!feof(fp) && !ferror(fp)) {
- int cnt = fread(buffer, 1, MAX_BUFFERSIZE , fp);
- processResponse(cnt, buffer);
- }
- endResponse();
- fclose(fp);
- }
- else {
- retval = 404;
- ERR("Requested file was not found !");
- }
-
- return retval;
-}
--- a/HTTPFsRequestHandler.h Tue May 28 01:56:14 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/* HTTPFsRequestHandler.h */
-/*
-Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-#ifndef __HTTPFSREQUESTHANDLER_H__
-#define __HTTPFSREQUESTHANDLER_H__
-
-#include "mbed.h"
-#include "HTTPRequestHandler.h"
-
-#include <map>
-#include <string>
-
-class HTTPFsRequestHandler : public HTTPRequestHandler
-{
- std::string m_rootPath;
- std::string m_localPath;
-
- public:
- HTTPFsRequestHandler(const char* roottPath, const char* localPath, HTTPConnection::HTTPMessage& Msg, TCPSocketConnection& Tcp);
- virtual ~HTTPFsRequestHandler();
-
- static inline HTTPRequestHandler* create(const char* rootPath, const char* localPath, HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp) { return new HTTPFsRequestHandler(rootPath, localPath, msg, tcp); }
-
- /** Handler function to serve GET requests
- */
- virtual int handleGetRequest();
-
- static std::map<const char*, const char*> m_fsMap;
- static void mount(const char* requestPath, const char* localPath) { m_fsMap[requestPath] = localPath; }
-};
-#endif // __HTTPFSREQUESTHANDLER_H__
\ No newline at end of file
--- a/HTTPRequestHandler.cpp Tue May 28 01:56:14 2013 +0000
+++ b/HTTPRequestHandler.cpp Tue May 28 21:20:58 2013 +0000
@@ -35,13 +35,15 @@
err = handleGetRequest();
break;
-// case HTTP_RT_POST:
-// err = handlePostRequest();
-// break;
+ case HTTP_RT_POST:
+ INFO("Dispatching POST request.");
+ err = handlePostRequest();
+ break;
-// case HTTP_RT_PUT:
-// err = handlePutRequest();
-// break;
+ case HTTP_RT_PUT:
+ INFO("Dispatching PUT request.");
+ err = handlePutRequest();
+ break;
default:
INFO("Error in handleRequest, unhandled request type.");
@@ -117,4 +119,3 @@
INFO("Ending Response !");
tcp.send("\r\n", 2);
}
-
--- a/HTTPRequestHandler.h Tue May 28 01:56:14 2013 +0000
+++ b/HTTPRequestHandler.h Tue May 28 21:20:58 2013 +0000
@@ -33,6 +33,7 @@
/** class HTTPRequestHandler is the base class for HTTP Handler request implementations.
*
*/
+
class HTTPRequestHandler
{
protected:
@@ -49,8 +50,12 @@
virtual ~HTTPRequestHandler();
/** Handler function which will be used by the HTTPServer to serve requests.
- * @param msg : Request Message information.
- * @param tcp : The socket which represents the active connection to the client.
+ * The default version of this function will dispatch respective handler member
+ * functions according to the request type given in the HTTPMessage object.
+ * The list of possible functions dispatched is :
+ * * handleGetRequest
+ * * handlePostRequest
+ * * handlePutRequest
*/
virtual void handleRequest();
@@ -74,18 +79,17 @@
void endResponse();
protected:
- /** Handler function to serve GET requests
+ /** Handler function to serve GET requests. Download ressource from server from \c uri location.
*/
virtual int handleGetRequest() = 0;
- /** Handler function to serve PUT requests
+ /** Handler function to serve PUT requests. Upload ressource to server to \c uri location.
*/
-// virtual int handlePutRequest() = 0;
+ virtual int handlePutRequest() = 0;
- /** Handler function to serve POST requests
+ /** Handler function to serve POST requests. Send data to webserver. Can also be appended to uri.
*/
-// virtual int handlePostRequest() = 0;
-
+ virtual int handlePostRequest() = 0;
};
#endif // __HTTPREQUESTHANDLER_H__
\ No newline at end of file
--- a/HTTPServer.cpp Tue May 28 01:56:14 2013 +0000
+++ b/HTTPServer.cpp Tue May 28 21:20:58 2013 +0000
@@ -1,12 +1,16 @@
#include "mbed.h"
#include "HTTPServer.h"
+#define _DEBUG 1
+
+#ifdef _DEBUG
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
+#endif
-#if (1 && !defined(TARGET_LPC11U24))
+#if (_DEBUG && !defined(TARGET_LPC11U24))
#define INFO(x, ...) if (m_pDbg) m_pDbg->printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__); else printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
#define WARN(x, ...) if (m_pDbg) m_pDbg->printf("[HttpServer : WARN]"x"\r\n", ##__VA_ARGS__); else printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
#define ERR(x, ...) if (m_pDbg) m_pDbg->printf("[HttpServer : ERR]"x"\r\n", ##__VA_ARGS__); else printf("[HttpServer : DBG]"x"\r\n", ##__VA_ARGS__);
@@ -16,11 +20,13 @@
#define ERR(x, ...)
#endif
+
+/* Constructor */
+/* initialize all members and set the standard error handler. */
HTTPServer::HTTPServer(Serial *dbg)
{
m_pDbg = dbg;
m_pSvr = NULL;
- m_bServerListening = false;
m_pErrorHandler = StdErrorHandler;
}
@@ -29,17 +35,15 @@
if (m_pSvr) {
delete m_pSvr;
m_pSvr = NULL;
- m_bServerListening = false;
}
}
-const char* szStdErrorPage = "<HTML><HEAD><META content=\"text/html\" http-equiv=Content-Type></HEAD><BODY><h1>Error 404</h1><P>This resource is not available<P></BODY></HTML>\r\n\r\n";
+static const char* szStdErrorPage = "<HTML><HEAD><META content=\"text/html\" http-equiv=Content-Type></HEAD><BODY><h1>Error 404</h1><P>This resource is not available<P></BODY></HTML>\r\n\r\n";
void HTTPServer::StdErrorHandler(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
{
- char echoHeader[512];
-
+ char echoHeader[256];
tcp.set_blocking(true, 1500);
sprintf(echoHeader,"HTTP/1.1 404 Fail\r\nContent-Length: %d\r\nContent-Type: text/html\r\nServer: mbed embedded\r\n\n\r",strlen(szStdErrorPage));
tcp.send(echoHeader, strlen(echoHeader));
@@ -54,8 +58,6 @@
ERR("start function was already called, server is already in listening state.");
return -1;
}
-
- m_bServerListening = false;
// Create a new server object
m_pSvr = new TCPSocketServer();
@@ -78,7 +80,6 @@
}
else {
INFO("Listening\n");
- m_bServerListening = true;
}
// set into non blocking operation
@@ -96,36 +97,47 @@
// If so , a new HTTPConnection is created and the connection thread is started.
TCPSocketConnection Clnt;
+#ifdef _DEBUG
led4 = 1; // Indicate we are waiting for a new connection
+#endif
if (m_pSvr->accept(Clnt) < 0) {
// an error occured
ERR("There was an error, Accept returned with an error. Probably the connection to the router was lost. Shutting down server");
+#ifdef _DEBUG
led2 = 0;
- m_bServerListening = false;
+#endif
m_pSvr->close();
delete m_pSvr;
m_pSvr = NULL;
+#ifdef _DEBUG
led4 = 0;
led3 = 1; // ERROR
led2 = 0;
led1 = 0;
+#endif
return -1;
}
else {
+#ifdef _DEBUG
led4 = 0;
+#endif
// a new connection was received
INFO("Client (IP=%s) is connected !\n", Clnt.get_address());
// Start the main connection thread
+#ifdef _DEBUG
led3 = 1;
led2 = 1;
+#endif
HTTPConnection con;
int c = con.poll();
if (c == 0) {
// Handle the request
HandleRequest(con.m_Msg, Clnt);
}
+#ifdef _DEBUG
led2 = 0;
led3 = 0;
+#endif
}
INFO("Leaving polling thread");
@@ -137,12 +149,13 @@
std::string localPath;
std::map<std::string, HTTPRequestHandler*(*)(const char*, const char*, HTTPConnection::HTTPMessage&, TCPSocketConnection&), handlersComp>::const_iterator it;
+ // Iterate through registered handlers and check if the handler's path is a subset of the requested uri.
for (it = m_lpHandlers.begin() ; it != m_lpHandlers.end() ; it++) {
// check if this entries' path is fully contained at the beginning of the requested path
std::string curpth = it->first;
if (msg.uri.find(curpth) == 0) {
- // handler found
+ // firts matching handler found, we just take it and we'll be happy
localPath = msg.uri.substr(curpth.length());
break;
}
@@ -155,31 +168,12 @@
INFO("Webrequest left unhandled.");
}
else {
+ // Valid handler was found
INFO("Routing webrequest !");
-
+ // Instantiate the handler object (handling will be done from withing the object's constructor
HTTPRequestHandler *phdl = (*it->second)(it->first.c_str(), localPath.c_str(), msg, tcp);
+ // now we can delete the object, because handling is completed.
if (phdl != NULL)
delete phdl;
}
-
}
-/*
-void HTTPServer::HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp)
-{
- map<string, HTTPRequestHandlerFunction>::iterator it;
-
- it = m_pHandlers.find(msg.uri);
-
- if (it == m_pHandlers.end()) {
- // There is no such handler, so return invalid
-
- m_pErrorHandler(msg, tcp);
- INFO("Webrequest left unhandled.");
- }
- else {
- // Handler was found so pass action to handler
- INFO("Routing webrequest !");
- (it->second)(msg, tcp);
- }
-}
-*/
\ No newline at end of file
--- a/HTTPServer.h Tue May 28 01:56:14 2013 +0000
+++ b/HTTPServer.h Tue May 28 21:20:58 2013 +0000
@@ -74,6 +74,11 @@
*/
class HTTPServer
{
+
+ TCPSocketServer* m_pSvr;
+ bool m_bServerListening;
+ Serial* m_pDbg;
+
public:
/** Constructor for HTTPServer objects.
*/
@@ -83,6 +88,9 @@
*/
~HTTPServer();
+ /**
+ * Structure which will allow to order the stored handlers according to their associated path.
+ */
struct handlersComp //Used to order handlers in the right way
{
bool operator() (const string& handler1, const string& handler2) const
@@ -97,20 +105,21 @@
}
};
- ///Adds a handler
/**
- Appends a handler to the handlers list
- @param T : class which will be instanciated to serve these requests
- @param path : requests starting with this path will be served using this handler
+ * Adds a request handler to the handlers list. You will have to use one of the existing implementations.
+ * With each handler a \c uri or \c path is associated. Whenever a request is received the server will
+ * walk through all registered handlers and check which \c path is matching.
+ * @param T : class which will be instanciated to serve these requests for the associated \b path.
+ * @param path : request uri starting with this \c path will be served using this handler.
*/
template<typename T>
void addHandler(const char* path)
{ m_lpHandlers[path] = &T::create; }
/**
- Replaces the standard error Handler. The error Handler will be called everytime a request is not
- handled by a handler from the handler list.
- @param hdlFunc: Handler which serves an error condition.
+ * Replaces the standard error Handler. The error Handler will be called everytime a request is not
+ * matching any of the registered \c paths or \c uris.
+ * @param hdlFunc: User specified handler function which will be used in error conditions.
*/
void addErrorHandler(HTTPRequestHandlerFunction hdlFunc)
{ m_pErrorHandler = hdlFunc!=NULL ?hdlFunc : StdErrorHandler; }
@@ -124,18 +133,30 @@
/** Performs the regular polling of the server component. Needs to be called cyclically.
* The function will internally check whether new connections are requested by a client and will also poll all existing client connections.
+ * @returns -1 if there was a problem. If 0 is returned, the latest request was served successfully and the server is
+ * ready for processing the next request. Simply call \c poll as long as you want to serve new incoming requests.
*/
int poll();
- private:
- static void StdErrorHandler(HTTPConnection::HTTPMessage&, TCPSocketConnection&);
+ private:
+ /** The standard error handler function.
+ * @param msg : Request message data.
+ * @param tcp : Socket to be used for responding.
+ */
+ static void StdErrorHandler(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp);
- TCPSocketServer* m_pSvr;
- bool m_bServerListening;
-
- Serial* m_pDbg;
- void HandleRequest(HTTPConnection::HTTPMessage& con, TCPSocketConnection&);
+ /** Internal function which processes a request and which will try to find the matching handler function
+ * for the given request. Please note that the function will search through the list of handlers, iterating
+ * from longest to shortest \c paths. If the registered \c path is a subset of the request the associated
+ * handler is considered as being a match.
+ * @param msg : Request message data. Contains the requested logical \c uri.
+ * @param tcp : Socket to be used for communication with the client.
+ */
+ void HandleRequest(HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp);
+ /** Map of handler objects. Can be any object derived from \ref HTTPRequestHeader. Use the \ref addHandler function
+ * to register new handler objects.
+ */
map<string, HTTPRequestHandler* (*)(const char*, const char*, HTTPConnection::HTTPMessage&, TCPSocketConnection&), handlersComp> m_lpHandlers;
HTTPRequestHandlerFunction m_pErrorHandler;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Handler/HTTPFsRequestHandler.cpp Tue May 28 21:20:58 2013 +0000
@@ -0,0 +1,97 @@
+/* HTTPFsRequestHandler.cpp */
+#include "mbed.h"
+#include "HTTPFsRequestHandler.h"
+
+
+#define _DEBUG 1
+
+#if (_DEBUG && !defined(TARGET_LPC11U24))
+#define INFO(x, ...) std::printf("[HTTPFsRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__);
+#define WARN(x, ...) std::printf("[HTTPFsRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__);
+#define ERR(x, ...) std::printf("[HTTPFsRequestHandler : DBG]"x"\r\n", ##__VA_ARGS__);
+#else
+#define INFO(x, ...)
+#define WARN(x, ...)
+#define ERR(x, ...)
+#endif
+
+
+#define MAX_BUFFERSIZE 128
+static char buffer[MAX_BUFFERSIZE];
+
+
+std::map<const char*, const char*> HTTPFsRequestHandler::m_fsMap;
+
+HTTPFsRequestHandler::HTTPFsRequestHandler(const char* rootPath, const char* localPath, HTTPConnection::HTTPMessage& Msg, TCPSocketConnection& Tcp)
+ : HTTPRequestHandler(Msg, Tcp)
+{
+ m_rootPath = rootPath;
+ m_localPath = localPath;
+
+ // Now replace the virtual root path with a mounted device path
+ std::map<const char*, const char*>::iterator it;
+ for (it = m_fsMap.begin() ; it != m_fsMap.end() ; it++) {
+ // find best match (if the given logical path is containted in the root
+ if (m_rootPath.find( it->second ) == 0) {
+ m_rootPath = it->first;
+ break;
+ }
+ }
+
+ handleRequest();
+}
+
+HTTPFsRequestHandler::~HTTPFsRequestHandler()
+{
+}
+
+int HTTPFsRequestHandler::handleGetRequest()
+{
+ INFO("Handling Get Request.");
+ int retval = 200; //success
+ std::string reqPath;
+
+ // Check if we received a directory with the local bath
+ if ((m_localPath.length() == 0) || (m_localPath.substr( m_localPath.length()-1, 1) == "/")) {
+ // yes, we shall append the default page name
+ m_localPath += "index.html";
+ }
+
+ reqPath = m_rootPath + m_localPath;
+
+ INFO("Mapping \"%s\" to \"%s\"", msg.uri.c_str(), reqPath.c_str());
+
+ FILE *fp = fopen(reqPath.c_str(), "r");
+ if (fp != NULL) {
+ // File was found and can be returned
+
+ // first determine the size
+ fseek(fp, 0, SEEK_END);
+ long size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ startResponse(200, size);
+ while(!feof(fp) && !ferror(fp)) {
+ int cnt = fread(buffer, 1, MAX_BUFFERSIZE , fp);
+ processResponse(cnt, buffer);
+ }
+ endResponse();
+ fclose(fp);
+ }
+ else {
+ retval = 404;
+ ERR("Requested file was not found !");
+ }
+
+ return retval;
+}
+
+int HTTPFsRequestHandler::handlePostRequest()
+{
+ return 404;
+}
+
+int HTTPFsRequestHandler::handlePutRequest()
+{
+ return 404;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Handler/HTTPFsRequestHandler.h Tue May 28 21:20:58 2013 +0000
@@ -0,0 +1,81 @@
+/* HTTPFsRequestHandler.h */
+/*
+Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#ifndef __HTTPFSREQUESTHANDLER_H__
+#define __HTTPFSREQUESTHANDLER_H__
+
+#include "mbed.h"
+#include "HTTPRequestHandler.h"
+
+#include <map>
+#include <string>
+
+/** class HTTPFsRequestHandler serves requests with file-system objects
+*/
+class HTTPFsRequestHandler : public HTTPRequestHandler
+{
+ std::string m_rootPath;
+ std::string m_localPath;
+
+ public:
+ /** constructor for HTTPFsRequestHandler object and stores the request related data locally.
+ * the request handling will be initiated from within the constructor.
+ * @param rootPath : The path under which the handler was registered.
+ * @param localPath : The path which is relative to the registered file system root.
+ * @param Msg : Message request information that comes with the request.
+ * @param Tcp : The socket connection for communicating with the client.
+ */
+ HTTPFsRequestHandler(const char* rootPath, const char* localPath, HTTPConnection::HTTPMessage& Msg, TCPSocketConnection& Tcp);
+
+ /** Destructor
+ */
+ virtual ~HTTPFsRequestHandler();
+
+ /** static creation function for this object.
+ */
+ static inline HTTPRequestHandler* create(const char* rootPath, const char* localPath, HTTPConnection::HTTPMessage& msg, TCPSocketConnection& tcp) { return new HTTPFsRequestHandler(rootPath, localPath, msg, tcp); }
+
+ /** Handler function to serve GET requests
+ */
+ virtual int handleGetRequest();
+
+ /** Handler function to serve PUT requests
+ */
+ virtual int handlePutRequest();
+
+ /** Handler function to serve POST requests
+ */
+ virtual int handlePostRequest();
+
+ /** Map to register different file system types and associate them with different root paths
+ */
+ static std::map<const char*, const char*> m_fsMap;
+
+ /** static function to register a new file system type with a logical root path
+ */
+ static void mount(const char* requestPath, const char* localPath) { m_fsMap[requestPath] = localPath; }
+
+ /** Parse a uri string for uri file name and argument:value pairs
+ */
+ int parseUriArgs(string uri, map<string, string>& args);
+};
+#endif // __HTTPFSREQUESTHANDLER_H__
\ No newline at end of file
