00001 /* 00002 * The information in this file is 00003 * Copyright(c) 2007 Ball Aerospace & Technologies Corporation 00004 * and is subject to the terms and conditions of the 00005 * GNU Lesser General Public License Version 2.1 00006 * The license text is available from 00007 * http://www.gnu.org/licenses/lgpl.html 00008 */ 00009 00010 #ifndef MUHTTPSERVER_H 00011 #define MUHTTPSERVER_H 00012 00013 #include "AttachmentPtr.h" 00014 #include "EnumWrapper.h" 00015 #include "SessionManager.h" 00016 #include <ehs.h> 00017 #include <QtCore/QMap> 00018 #include <QtCore/QObject> 00019 #include <QtCore/QString> 00020 #include <boost/any.hpp> 00021 00022 class QTextStream; 00023 class QTimer; 00024 class Subject; 00025 00026 /** 00027 * This class provides a framework for creating HTTP micro servers in Qt. 00028 */ 00029 class MuHttpServer : public QObject, public EHS 00030 { 00031 Q_OBJECT 00032 00033 public: 00034 /** 00035 * This structure contains information used to send a response to an HTTP request. 00036 */ 00037 struct Response 00038 { 00039 /** 00040 * The body of the response message if the response is 8-bit safe. (i.e. ASCII) 00041 */ 00042 QString mBody; 00043 00044 /** 00045 * The body of the response message if the response is not 8-bit safe. (i.e. a raw image) 00046 */ 00047 QByteArray mOctets; 00048 00049 /** 00050 * Additional HTTP headers to attach to the response message. 00051 * 00052 * The key is the name of the header and the value is the header data. 00053 */ 00054 QMap<QString,QString> mHeaders; 00055 00056 /** 00057 * The type of response. 00058 * 00059 * This can be the numeric code defined by the HTTP RFCs or 00060 * a convenience enum value as defined by the EHS library. (for example, HTTPRESPONSE_200_OK) 00061 */ 00062 ResponseCode mCode; 00063 00064 // What character encoding is the response body? 00065 enum CharacterEncodingTypeEnum 00066 { 00067 ASCII, /**< The response body is ASCII encoded and contained in the mBody member. */ 00068 UTF8, /**< The response body is UTF-8 encoded and contained in the mBody member. */ 00069 OCTET /**< The response body consists of raw octets and is contained in the mOctets member. */ 00070 }; 00071 00072 /** 00073 * @EnumWrapper MuHttpServer::Response::CharacterEncodingTypeEnum. 00074 */ 00075 typedef EnumWrapper<CharacterEncodingTypeEnum> CharacterEncodingType; 00076 00077 /** 00078 * What character encoding is the response body? 00079 */ 00080 CharacterEncodingType mEncoding; 00081 00082 /** 00083 * Create an uninitialized Response with a default encoding type of ASCII. 00084 */ 00085 Response() : mCode(HTTPRESPONSECODE_INVALID), mEncoding(ASCII) {} 00086 }; 00087 00088 /** 00089 * Initialize a MuHttpServer object. 00090 * 00091 * @param port 00092 * The TCP port that this server will listen. If port is 0, this 00093 * object is assumed to be a child handler and no network socket 00094 * will be set up. 00095 * @param pParent 00096 * The Qt parent of this object. 00097 * 00098 * @see registerPath() 00099 */ 00100 MuHttpServer(int port = 80, QObject *pParent = NULL); 00101 00102 /** 00103 * Clean up the MuHttpServer object and close network sockets. 00104 */ 00105 virtual ~MuHttpServer(); 00106 00107 /** 00108 * Listen to the network and start processing requests. 00109 * 00110 * @return True if successful or if the server is already running, false if there is an error. 00111 */ 00112 bool start(); 00113 00114 /** 00115 * Stop the server. 00116 */ 00117 void stop(Subject &subject, const std::string &signal, const boost::any &v); 00118 00119 /** 00120 * Attach a server path to a response object. 00121 * 00122 * Requests from the registered path will be handled by pObj. 00123 * For example, registerPath("/test", this) will cause the following 00124 * requests to be handled by the this object. 00125 * http://localhost/test/ 00126 * http://localhost/test/foo 00127 * http://localhost/test/bar 00128 * The following will not be handled by the this object. 00129 * http://localhost/test 00130 * http://localhost/test/foo/ 00131 * http://localhost/test/foo/bar 00132 * http://localhost/foo/ 00133 * 00134 * Any paths not explicitly registered will be handled by the root EHS object. 00135 * 00136 * @param path 00137 * The path prefix for processing. 00138 * @param pObj 00139 * The object that wants to processing path. 00140 */ 00141 void registerPath(const QString &path, EHS *pObj); 00142 00143 protected: 00144 /** 00145 * This handles HTTP POST requests. 00146 * 00147 * POST requests encode form data in the request body. 00148 * 00149 * The default behavior is to return an HTTP 403 Forbidden response 00150 * to the requesting client. 00151 * 00152 * @param uri 00153 * The URI of the request. If this object is handling sub requests 00154 * via registerPath(), this will be a partial URI rooted at the path 00155 * this object is registered to handle. 00156 * @param contentType 00157 * The HTTP Content-type of the request. 00158 * @param body 00159 * The body of the request. 00160 * @param form 00161 * Form data from the request body. 00162 * @return An HTTP Response. 00163 */ 00164 virtual Response postRequest(const QString& uri, const QString& contentType, const QString& body, 00165 const FormValueMap& form); 00166 00167 /** 00168 * This handles HTTP GET requests. 00169 * 00170 * GET requests encode form data in the request URL using ? and &. 00171 * 00172 * @param uri 00173 * The URI of the request. If this object is handling sub requests 00174 * via registerPath(), this will be a partial URI rooted at the path 00175 * this object is registered to handle. 00176 * @param contentType 00177 * The HTTP Content-type of the request. 00178 * @param body 00179 * The body of the request. This is usually empty with GET requests. 00180 * @param form 00181 * Form data encoded in the request URL. 00182 * @return An HTTP Response. 00183 */ 00184 virtual Response getRequest(const QString& uri, const QString& contentType, const QString& body, 00185 const FormValueMap& form) = 0; 00186 00187 protected slots: 00188 /** 00189 * Handle new and existing connections. 00190 * 00191 * This runs one cycle of the server's request loop. 00192 * The default behavior of a MuHttpServer is to call this slot 00193 * every 250ms. 00194 */ 00195 void processServer(); 00196 00197 /** 00198 * This provides debugging information about an HttpRequest. 00199 * 00200 * The default behavior is to do nothing. If an implementation wants 00201 * to log all requests for debugging purposes, this method should be overridden. 00202 * 00203 * @param pHttpRequest 00204 * The request object. 00205 */ 00206 virtual void debug(HttpRequest *pHttpRequest); 00207 00208 /** 00209 * Display a waning message. 00210 * 00211 * The default behavior is to do nothing. If an implementation wants 00212 * to display extra warning messages, this method should be overridden. 00213 * This method is called when the underlying HTTP server code throws an error 00214 * during socket setup, conntection, or processing. It is also called when 00215 * postRequest() or getRequest() return an HTTPRESPONSECODE_INVALID indicating 00216 * an internal server error. 00217 * 00218 * @param msg 00219 * A user displayable warning message. 00220 */ 00221 virtual void warning(const QString &msg); 00222 00223 /** 00224 * Allow connections from machines other than localhost. 00225 * 00226 * The default is to allow only localhost connections. 00227 * 00228 * @param val 00229 * If true, any machine can connect. If false, only localhost can connect. 00230 */ 00231 void allowNonLocalConnections(bool val) 00232 { 00233 mAllowNonLocal = val; 00234 } 00235 00236 private: 00237 MuHttpServer(const MuHttpServer& rhs); 00238 MuHttpServer& operator=(const MuHttpServer& rhs); 00239 ResponseCode HandleRequest(HttpRequest *pHttpRequest, HttpResponse *pHttpResponse); 00240 00241 EHSServerParameters mParams; 00242 QTimer* mpTimer; 00243 QMap<QString, EHS*> mRegistrations; 00244 bool mServerIsRunning; 00245 bool mAllowNonLocal; 00246 AttachmentPtr<SessionManager> mSession; 00247 }; 00248 00249 #endif