Single instance HTTP Server using WiFly Interface.

Dependents:   WiFlyHTTPServerSample MultiThreadingHTTPServer

This is my implementation for a HTTP Server using the WiFly Interface. Please note that this is still under development.

It may still contain several bugs. I have tested it using a 1768 on an application board plus RN-XV board.

Currently there is only a FileSystem implemented. Also it is limited to GET request.

I try to extend it further so it will be more useful.

Btw, it does NOT work with RTOS, which seems not to be the Problem of my library.

Do not Forget to Import the WiFly Interface into your Project when using this library.

Change History:

REV5: - added support for basic RPC GET request functionality.

REV4: - added argument parsing from the request uri. - documentation extended and updated.

Committer:
leihen
Date:
Wed Jun 26 22:41:05 2013 +0000
Revision:
14:7f9fbfc18623
Moved the HttpServer module inside this library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leihen 14:7f9fbfc18623 1 #ifndef __HTTPSERVER_H__
leihen 14:7f9fbfc18623 2 #define __HTTPSERVER_H__
leihen 14:7f9fbfc18623 3
leihen 14:7f9fbfc18623 4 #include "Wifly.h"
leihen 14:7f9fbfc18623 5 #include "rtos.h"
leihen 14:7f9fbfc18623 6 #include "HTTPConnection.h"
leihen 14:7f9fbfc18623 7 #include "HTTPRequestHandler.h"
leihen 14:7f9fbfc18623 8
leihen 14:7f9fbfc18623 9 #include <string>
leihen 14:7f9fbfc18623 10 #include <map>
leihen 14:7f9fbfc18623 11
leihen 14:7f9fbfc18623 12 typedef enum {
leihen 14:7f9fbfc18623 13 msg_get,
leihen 14:7f9fbfc18623 14 msg_post,
leihen 14:7f9fbfc18623 15 msg_head,
leihen 14:7f9fbfc18623 16 msg_put,
leihen 14:7f9fbfc18623 17 msg_delete,
leihen 14:7f9fbfc18623 18 msg_trace,
leihen 14:7f9fbfc18623 19 msg_options,
leihen 14:7f9fbfc18623 20 msg_connect
leihen 14:7f9fbfc18623 21 } msg_t;
leihen 14:7f9fbfc18623 22
leihen 14:7f9fbfc18623 23
leihen 14:7f9fbfc18623 24 typedef struct {
leihen 14:7f9fbfc18623 25 msg_t requestType;
leihen 14:7f9fbfc18623 26 char requestUri[256];
leihen 14:7f9fbfc18623 27 // map<string, string> messageHeaders;
leihen 14:7f9fbfc18623 28 } request_msg_t;
leihen 14:7f9fbfc18623 29
leihen 14:7f9fbfc18623 30 /** Typedefinition for a handler function
leihen 14:7f9fbfc18623 31 */
leihen 14:7f9fbfc18623 32 typedef void (*HTTPRequestHandlerFunction)(HTTPConnection::HTTPMessage&);
leihen 14:7f9fbfc18623 33
leihen 14:7f9fbfc18623 34
leihen 14:7f9fbfc18623 35 /** This is the non-blocking HTTP Server class. The idea behind this class is as follows:
leihen 14:7f9fbfc18623 36 * the user may instantiate the class and initialize it. Once the server is setup and
leihen 14:7f9fbfc18623 37 * listening, the server will stay in an endless loop and keep on listening for new
leihen 14:7f9fbfc18623 38 * connections and for new HTTP requests. Once a request is received it will be placed
leihen 14:7f9fbfc18623 39 * in a queue. The queue itself will be handled in a separate task.
leihen 14:7f9fbfc18623 40 */
leihen 14:7f9fbfc18623 41 class HttpServer : public Wifly
leihen 14:7f9fbfc18623 42 {
leihen 14:7f9fbfc18623 43 Thread *m_listener;
leihen 14:7f9fbfc18623 44 Thread *m_worker;
leihen 14:7f9fbfc18623 45
leihen 14:7f9fbfc18623 46 request_msg_t* checkMessageReceived(char *);
leihen 14:7f9fbfc18623 47 void processMessageHeader(char* headerLine, char **fieldname, char **fieldvalue);
leihen 14:7f9fbfc18623 48
leihen 14:7f9fbfc18623 49 public:
leihen 14:7f9fbfc18623 50 HttpServer(PinName tx, PinName rx, PinName reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec, Wifly::WiflyBaudrate_t baud = Wifly::Wifly_115200);
leihen 14:7f9fbfc18623 51 ~HttpServer();
leihen 14:7f9fbfc18623 52
leihen 14:7f9fbfc18623 53 bool start(int port);
leihen 14:7f9fbfc18623 54
leihen 14:7f9fbfc18623 55 virtual void handler_rx(void);
leihen 14:7f9fbfc18623 56 virtual void attach_rx(bool);
leihen 14:7f9fbfc18623 57
leihen 14:7f9fbfc18623 58 virtual bool join();
leihen 14:7f9fbfc18623 59 virtual int send(const char * str, int len, const char * ACK = NULL, char * res = NULL, int timeout = DEFAULT_WAIT_RESP_TIMEOUT);
leihen 14:7f9fbfc18623 60
leihen 14:7f9fbfc18623 61 public:
leihen 14:7f9fbfc18623 62
leihen 14:7f9fbfc18623 63
leihen 14:7f9fbfc18623 64 /**
leihen 14:7f9fbfc18623 65 * Structure which will allow to order the stored handlers according to their associated path.
leihen 14:7f9fbfc18623 66 */
leihen 14:7f9fbfc18623 67 struct handlersComp //Used to order handlers in the right way
leihen 14:7f9fbfc18623 68 {
leihen 14:7f9fbfc18623 69 bool operator() (const string& handler1, const string& handler2) const
leihen 14:7f9fbfc18623 70 {
leihen 14:7f9fbfc18623 71 //The first handler is longer than the second one
leihen 14:7f9fbfc18623 72 if (handler1.length() > handler2.length())
leihen 14:7f9fbfc18623 73 return true; //Returns true if handler1 is to appear before handler2
leihen 14:7f9fbfc18623 74 else if (handler1.length() < handler2.length())
leihen 14:7f9fbfc18623 75 return false;
leihen 14:7f9fbfc18623 76 else //To avoid the == case, sort now by address
leihen 14:7f9fbfc18623 77 return ((&handler1)>(&handler2));
leihen 14:7f9fbfc18623 78 }
leihen 14:7f9fbfc18623 79 };
leihen 14:7f9fbfc18623 80 /** The standard error handler function.
leihen 14:7f9fbfc18623 81 * @param msg : Request message data.
leihen 14:7f9fbfc18623 82 * @param tcp : Socket to be used for responding.
leihen 14:7f9fbfc18623 83 */
leihen 14:7f9fbfc18623 84 static void StdErrorHandler(HTTPConnection::HTTPMessage& msg);
leihen 14:7f9fbfc18623 85
leihen 14:7f9fbfc18623 86
leihen 14:7f9fbfc18623 87 /** Internal function which processes a request and which will try to find the matching handler function
leihen 14:7f9fbfc18623 88 * for the given request. Please note that the function will search through the list of handlers, iterating
leihen 14:7f9fbfc18623 89 * from longest to shortest \c paths. If the registered \c path is a subset of the request the associated
leihen 14:7f9fbfc18623 90 * handler is considered as being a match.
leihen 14:7f9fbfc18623 91 * @param msg : Request message data. Contains the requested logical \c uri.
leihen 14:7f9fbfc18623 92 * @param tcp : Socket to be used for communication with the client.
leihen 14:7f9fbfc18623 93 */
leihen 14:7f9fbfc18623 94 void HandleRequest(HTTPConnection::HTTPMessage* msg);
leihen 14:7f9fbfc18623 95
leihen 14:7f9fbfc18623 96 /** Map of handler objects. Can be any object derived from \ref HTTPRequestHeader. Use the \ref addHandler function
leihen 14:7f9fbfc18623 97 * to register new handler objects.
leihen 14:7f9fbfc18623 98 */
leihen 14:7f9fbfc18623 99 static map<string, HTTPRequestHandler* (*)(const char*, const char*, HTTPConnection::HTTPMessage&), handlersComp> m_lpHandlers;
leihen 14:7f9fbfc18623 100
leihen 14:7f9fbfc18623 101 /**
leihen 14:7f9fbfc18623 102 * Adds a request handler to the handlers list. You will have to use one of the existing implementations.
leihen 14:7f9fbfc18623 103 * With each handler a \c uri or \c path is associated. Whenever a request is received the server will
leihen 14:7f9fbfc18623 104 * walk through all registered handlers and check which \c path is matching.
leihen 14:7f9fbfc18623 105 * @param T : class which will be instanciated to serve these requests for the associated \b path.
leihen 14:7f9fbfc18623 106 * @param path : request uri starting with this \c path will be served using this handler.
leihen 14:7f9fbfc18623 107 */
leihen 14:7f9fbfc18623 108 template<typename T>
leihen 14:7f9fbfc18623 109 void addHandler(const char* path)
leihen 14:7f9fbfc18623 110 { m_lpHandlers[path] = &T::create; }
leihen 14:7f9fbfc18623 111
leihen 14:7f9fbfc18623 112 /**
leihen 14:7f9fbfc18623 113 * Replaces the standard error Handler. The error Handler will be called everytime a request is not
leihen 14:7f9fbfc18623 114 * matching any of the registered \c paths or \c uris.
leihen 14:7f9fbfc18623 115 * @param hdlFunc: User specified handler function which will be used in error conditions.
leihen 14:7f9fbfc18623 116 */
leihen 14:7f9fbfc18623 117 void addErrorHandler(HTTPRequestHandlerFunction hdlFunc)
leihen 14:7f9fbfc18623 118 { m_pErrorHandler = hdlFunc!=NULL ?hdlFunc : StdErrorHandler; }
leihen 14:7f9fbfc18623 119 HTTPRequestHandlerFunction m_pErrorHandler;
leihen 14:7f9fbfc18623 120
leihen 14:7f9fbfc18623 121 protected:
leihen 14:7f9fbfc18623 122 bool bind(int port);
leihen 14:7f9fbfc18623 123 void listenForRequests();
leihen 14:7f9fbfc18623 124 void serveRequests();
leihen 14:7f9fbfc18623 125
leihen 14:7f9fbfc18623 126 bool parseRequest(char *request);
leihen 14:7f9fbfc18623 127
leihen 14:7f9fbfc18623 128 static void listen_thread(const void * parms);
leihen 14:7f9fbfc18623 129 static void worker_thread(const void * parms);
leihen 14:7f9fbfc18623 130 };
leihen 14:7f9fbfc18623 131
leihen 14:7f9fbfc18623 132 #endif // __HTTPSERVER_H__