Path: blob/trunk/third_party/cpp/civetweb/CivetServer.h
2868 views
/* Copyright (c) 2013-2017 the Civetweb developers1* Copyright (c) 2013 No Face Press, LLC2*3* License http://opensource.org/licenses/mit-license.php MIT License4*/56#ifndef _CIVETWEB_SERVER_H_7#define _CIVETWEB_SERVER_H_8#ifdef __cplusplus910#include "civetweb.h"11#include <map>12#include <stdexcept>13#include <string>14#include <vector>1516// forward declaration17class CivetServer;1819/**20* Exception class for thrown exceptions within the CivetHandler object.21*/22class CIVETWEB_API CivetException : public std::runtime_error23{24public:25CivetException(const std::string &msg) : std::runtime_error(msg)26{27}28};2930/**31* Basic interface for a URI request handler. Handlers implementations32* must be reentrant.33*/34class CIVETWEB_API CivetHandler35{36public:37/**38* Destructor39*/40virtual ~CivetHandler()41{42}4344/**45* Callback method for GET request.46*47* @param server - the calling server48* @param conn - the connection information49* @returns true if implemented, false otherwise50*/51virtual bool handleGet(CivetServer *server, struct mg_connection *conn);5253/**54* Callback method for POST request.55*56* @param server - the calling server57* @param conn - the connection information58* @returns true if implemented, false otherwise59*/60virtual bool handlePost(CivetServer *server, struct mg_connection *conn);6162/**63* Callback method for HEAD request.64*65* @param server - the calling server66* @param conn - the connection information67* @returns true if implemented, false otherwise68*/69virtual bool handleHead(CivetServer *server, struct mg_connection *conn);7071/**72* Callback method for PUT request.73*74* @param server - the calling server75* @param conn - the connection information76* @returns true if implemented, false otherwise77*/78virtual bool handlePut(CivetServer *server, struct mg_connection *conn);7980/**81* Callback method for DELETE request.82*83* @param server - the calling server84* @param conn - the connection information85* @returns true if implemented, false otherwise86*/87virtual bool handleDelete(CivetServer *server, struct mg_connection *conn);8889/**90* Callback method for OPTIONS request.91*92* @param server - the calling server93* @param conn - the connection information94* @returns true if implemented, false otherwise95*/96virtual bool handleOptions(CivetServer *server, struct mg_connection *conn);9798/**99* Callback method for PATCH request.100*101* @param server - the calling server102* @param conn - the connection information103* @returns true if implemented, false otherwise104*/105virtual bool handlePatch(CivetServer *server, struct mg_connection *conn);106};107108/**109* Basic interface for a URI authorization handler. Handler implementations110* must be reentrant.111*/112class CIVETWEB_API CivetAuthHandler113{114public:115/**116* Destructor117*/118virtual ~CivetAuthHandler()119{120}121122/**123* Callback method for authorization requests. It is up the this handler124* to generate 401 responses if authorization fails.125*126* @param server - the calling server127* @param conn - the connection information128* @returns true if authorization succeeded, false otherwise129*/130virtual bool authorize(CivetServer *server, struct mg_connection *conn) = 0;131};132133/**134* Basic interface for a websocket handler. Handlers implementations135* must be reentrant.136*/137class CIVETWEB_API CivetWebSocketHandler138{139public:140/**141* Destructor142*/143virtual ~CivetWebSocketHandler()144{145}146147/**148* Callback method for when the client intends to establish a websocket149*connection, before websocket handshake.150*151* @param server - the calling server152* @param conn - the connection information153* @returns true to keep socket open, false to close it154*/155virtual bool handleConnection(CivetServer *server,156const struct mg_connection *conn);157158/**159* Callback method for when websocket handshake is successfully completed,160*and connection is ready for data exchange.161*162* @param server - the calling server163* @param conn - the connection information164*/165virtual void handleReadyState(CivetServer *server,166struct mg_connection *conn);167168/**169* Callback method for when a data frame has been received from the client.170*171* @param server - the calling server172* @param conn - the connection information173* @bits: first byte of the websocket frame, see websocket RFC at174*http://tools.ietf.org/html/rfc6455, section 5.2175* @data, data_len: payload, with mask (if any) already applied.176* @returns true to keep socket open, false to close it177*/178virtual bool handleData(CivetServer *server,179struct mg_connection *conn,180int bits,181char *data,182size_t data_len);183184/**185* Callback method for when the connection is closed.186*187* @param server - the calling server188* @param conn - the connection information189*/190virtual void handleClose(CivetServer *server,191const struct mg_connection *conn);192};193194/**195* CivetCallbacks196*197* wrapper for mg_callbacks198*/199struct CIVETWEB_API CivetCallbacks : public mg_callbacks {200CivetCallbacks();201};202203/**204* CivetServer205*206* Basic class for embedded web server. This has an URL mapping built-in.207*/208class CIVETWEB_API CivetServer209{210public:211/**212* Constructor213*214* This automatically starts the sever.215* It is good practice to call getContext() after this in case there216* were errors starting the server.217*218* Note: CivetServer should not be used as a static instance in a Windows219* DLL, since the constructor creates threads and the destructor joins220* them again (creating/joining threads should not be done in static221* constructors).222*223* @param options - the web server options.224* @param callbacks - optional web server callback methods.225*226* @throws CivetException227*/228CivetServer(const char **options,229const struct CivetCallbacks *callbacks = 0,230const void *UserContext = 0);231CivetServer(std::vector<std::string> options,232const struct CivetCallbacks *callbacks = 0,233const void *UserContext = 0);234235/**236* Destructor237*/238virtual ~CivetServer();239240/**241* close()242*243* Stops server and frees resources.244*/245void close();246247/**248* getContext()249*250* @return the context or 0 if not running.251*/252const struct mg_context *253getContext() const254{255return context;256}257258/**259* addHandler(const std::string &, CivetHandler *)260*261* Adds a URI handler. If there is existing URI handler, it will262* be replaced with this one.263*264* URI's are ordered and prefix (REST) URI's are supported.265*266* @param uri - URI to match.267* @param handler - handler instance to use.268*/269void addHandler(const std::string &uri, CivetHandler *handler);270271void272addHandler(const std::string &uri, CivetHandler &handler)273{274addHandler(uri, &handler);275}276277/**278* addWebSocketHandler279*280* Adds a WebSocket handler for a specific URI. If there is existing URI281*handler, it will282* be replaced with this one.283*284* URI's are ordered and prefix (REST) URI's are supported.285*286* @param uri - URI to match.287* @param handler - handler instance to use.288*/289void addWebSocketHandler(const std::string &uri,290CivetWebSocketHandler *handler);291292void293addWebSocketHandler(const std::string &uri, CivetWebSocketHandler &handler)294{295addWebSocketHandler(uri, &handler);296}297298/**299* removeHandler(const std::string &)300*301* Removes a handler.302*303* @param uri - the exact URL used in addHandler().304*/305void removeHandler(const std::string &uri);306307/**308* removeWebSocketHandler(const std::string &)309*310* Removes a web socket handler.311*312* @param uri - the exact URL used in addWebSocketHandler().313*/314void removeWebSocketHandler(const std::string &uri);315316/**317* addAuthHandler(const std::string &, CivetAuthHandler *)318*319* Adds a URI authorization handler. If there is existing URI authorization320* handler, it will be replaced with this one.321*322* URI's are ordered and prefix (REST) URI's are supported.323*324* @param uri - URI to match.325* @param handler - authorization handler instance to use.326*/327void addAuthHandler(const std::string &uri, CivetAuthHandler *handler);328329void330addAuthHandler(const std::string &uri, CivetAuthHandler &handler)331{332addAuthHandler(uri, &handler);333}334335/**336* removeAuthHandler(const std::string &)337*338* Removes an authorization handler.339*340* @param uri - the exact URL used in addAuthHandler().341*/342void removeAuthHandler(const std::string &uri);343344/**345* getListeningPorts()346*347* Returns a list of ports that are listening348*349* @return A vector of ports350*/351352std::vector<int> getListeningPorts();353354/**355* getCookie(struct mg_connection *conn, const std::string &cookieName,356*std::string &cookieValue)357*358* Puts the cookie value string that matches the cookie name in the359*cookieValue destinaton string.360*361* @param conn - the connection information362* @param cookieName - cookie name to get the value from363* @param cookieValue - cookie value is returned using thiis reference364* @returns the size of the cookie value string read.365*/366static int getCookie(struct mg_connection *conn,367const std::string &cookieName,368std::string &cookieValue);369370/**371* getHeader(struct mg_connection *conn, const std::string &headerName)372* @param conn - the connection information373* @param headerName - header name to get the value from374* @returns a char array which contains the header value as string375*/376static const char *getHeader(struct mg_connection *conn,377const std::string &headerName);378379/**380* getParam(struct mg_connection *conn, const char *, std::string &, size_t)381*382* Returns a query which contained in the supplied buffer. The383* occurrence value is a zero-based index of a particular key name. This384* should not be confused with the index over all of the keys. Note that385*this386* function assumes that parameters are sent as text in http query string387* format, which is the default for web forms. This function will work for388* html forms with method="GET" and method="POST" attributes. In other389*cases,390* you may use a getParam version that directly takes the data instead of391*the392* connection as a first argument.393*394* @param conn - parameters are read from the data sent through this395*connection396* @param name - the key to search for397* @param dst - the destination string398* @param occurrence - the occurrence of the selected name in the query (0399*based).400* @return true if key was found401*/402static bool getParam(struct mg_connection *conn,403const char *name,404std::string &dst,405size_t occurrence = 0);406407/**408* getParam(const std::string &, const char *, std::string &, size_t)409*410* Returns a query parameter contained in the supplied buffer. The411* occurrence value is a zero-based index of a particular key name. This412* should not be confused with the index over all of the keys.413*414* @param data - the query string (text)415* @param name - the key to search for416* @param dst - the destination string417* @param occurrence - the occurrence of the selected name in the query (0418*based).419* @return true if key was found420*/421static bool422getParam(const std::string &data,423const char *name,424std::string &dst,425size_t occurrence = 0)426{427return getParam(data.c_str(), data.length(), name, dst, occurrence);428}429430/**431* getParam(const char *, size_t, const char *, std::string &, size_t)432*433* Returns a query parameter contained in the supplied buffer. The434* occurrence value is a zero-based index of a particular key name. This435* should not be confused with the index over all of the keys.436*437* @param data the - query string (text)438* @param data_len - length of the query string439* @param name - the key to search for440* @param dst - the destination string441* @param occurrence - the occurrence of the selected name in the query (0442*based).443* @return true if key was found444*/445static bool getParam(const char *data,446size_t data_len,447const char *name,448std::string &dst,449size_t occurrence = 0);450451/**452* getPostData(struct mg_connection *)453*454* Returns response body from a request made as POST. Since the455* connections map is protected, it can't be directly accessed.456* This uses string to store post data to handle big posts.457*458* @param conn - connection from which post data will be read459* @return Post data (empty if not available).460*/461static std::string getPostData(struct mg_connection *conn);462463/**464* urlDecode(const std::string &, std::string &, bool)465*466* @param src - string to be decoded467* @param dst - destination string468* @param is_form_url_encoded - true if form url encoded469* form-url-encoded data differs from URI encoding in a way that it470* uses '+' as character for space, see RFC 1866 section 8.2.1471* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt472*/473static void474urlDecode(const std::string &src,475std::string &dst,476bool is_form_url_encoded = true)477{478urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);479}480481/**482* urlDecode(const char *, size_t, std::string &, bool)483*484* @param src - buffer to be decoded485* @param src_len - length of buffer to be decoded486* @param dst - destination string487* @param is_form_url_encoded - true if form url encoded488* form-url-encoded data differs from URI encoding in a way that it489* uses '+' as character for space, see RFC 1866 section 8.2.1490* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt491*/492static void urlDecode(const char *src,493size_t src_len,494std::string &dst,495bool is_form_url_encoded = true);496497/**498* urlDecode(const char *, std::string &, bool)499*500* @param src - buffer to be decoded (0 terminated)501* @param dst - destination string502* @param is_form_url_encoded true - if form url encoded503* form-url-encoded data differs from URI encoding in a way that it504* uses '+' as character for space, see RFC 1866 section 8.2.1505* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt506*/507static void urlDecode(const char *src,508std::string &dst,509bool is_form_url_encoded = true);510511/**512* urlEncode(const std::string &, std::string &, bool)513*514* @param src - buffer to be encoded515* @param dst - destination string516* @param append - true if string should not be cleared before encoding.517*/518static void519urlEncode(const std::string &src, std::string &dst, bool append = false)520{521urlEncode(src.c_str(), src.length(), dst, append);522}523524/**525* urlEncode(const char *, size_t, std::string &, bool)526*527* @param src - buffer to be encoded (0 terminated)528* @param dst - destination string529* @param append - true if string should not be cleared before encoding.530*/531static void532urlEncode(const char *src, std::string &dst, bool append = false);533534/**535* urlEncode(const char *, size_t, std::string &, bool)536*537* @param src - buffer to be encoded538* @param src_len - length of buffer to be decoded539* @param dst - destination string540* @param append - true if string should not be cleared before encoding.541*/542static void urlEncode(const char *src,543size_t src_len,544std::string &dst,545bool append = false);546547// generic user context which can be set/read,548// the server does nothing with this apart from keep it.549const void *550getUserContext() const551{552return UserContext;553}554555protected:556class CivetConnection557{558public:559char *postData;560unsigned long postDataLen;561562CivetConnection();563~CivetConnection();564};565566struct mg_context *context;567std::map<struct mg_connection *, class CivetConnection> connections;568569// generic user context which can be set/read,570// the server does nothing with this apart from keep it.571const void *UserContext;572573private:574/**575* requestHandler(struct mg_connection *, void *cbdata)576*577* Handles the incoming request.578*579* @param conn - the connection information580* @param cbdata - pointer to the CivetHandler instance.581* @returns 0 if implemented, false otherwise582*/583static int requestHandler(struct mg_connection *conn, void *cbdata);584585static int webSocketConnectionHandler(const struct mg_connection *conn,586void *cbdata);587static void webSocketReadyHandler(struct mg_connection *conn, void *cbdata);588static int webSocketDataHandler(struct mg_connection *conn,589int bits,590char *data,591size_t data_len,592void *cbdata);593static void webSocketCloseHandler(const struct mg_connection *conn,594void *cbdata);595/**596* authHandler(struct mg_connection *, void *cbdata)597*598* Handles the authorization requests.599*600* @param conn - the connection information601* @param cbdata - pointer to the CivetAuthHandler instance.602* @returns 1 if authorized, 0 otherwise603*/604static int authHandler(struct mg_connection *conn, void *cbdata);605606/**607* closeHandler(struct mg_connection *)608*609* Handles closing a request (internal handler)610*611* @param conn - the connection information612*/613static void closeHandler(const struct mg_connection *conn);614615/**616* Stores the user provided close handler617*/618void (*userCloseHandler)(const struct mg_connection *conn);619};620621#endif /* __cplusplus */622#endif /* _CIVETWEB_SERVER_H_ */623624625