File indexing completed on 2025-03-09 04:23:09
0001 /* 0002 * Copyright 2011 Nikhil Marathe <nsm.nikhil@gmail.com> 0003 * 0004 * Permission is hereby granted, free of charge, to any person obtaining a copy 0005 * of this software and associated documentation files (the "Software"), to 0006 * deal in the Software without restriction, including without limitation the 0007 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 0008 * sell copies of the Software, and to permit persons to whom the Software is 0009 * furnished to do so, subject to the following conditions: 0010 * 0011 * The above copyright notice and this permission notice shall be included in 0012 * all copies or substantial portions of the Software. 0013 * 0014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 0018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 0019 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 0020 * IN THE SOFTWARE. 0021 */ 0022 0023 #ifndef Q_HTTP_REQUEST 0024 #define Q_HTTP_REQUEST 0025 0026 #include <QObject> 0027 #include <QHash> 0028 #include <QMetaEnum> 0029 #include <QMetaType> 0030 #include <QUrl> 0031 0032 class QTcpSocket; 0033 0034 class QHttpConnection; 0035 0036 typedef QHash<QString, QString> HeaderHash; 0037 0038 /* Request Methods */ 0039 0040 /*! \class QHttpRequest 0041 * 0042 * The QHttpRequest class represents the header and data 0043 * sent by the client. 0044 * 0045 * Header data is available immediately. 0046 * 0047 * Body data is streamed as it comes in via the data(const QByteArray&) signal. 0048 * As a consequence the application's request callback should ensure that it 0049 * connects to the data() signal before control returns back to the event loop. 0050 * Otherwise there is a risk of some data never being received by the 0051 * application. 0052 * 0053 * The class is <strong>read-only</strong> by users of %QHttpServer. 0054 */ 0055 class QHttpRequest : public QObject 0056 { 0057 Q_OBJECT 0058 0059 Q_PROPERTY(HeaderHash headers READ headers) 0060 Q_PROPERTY(QString remoteAddress READ remoteAddress) 0061 Q_PROPERTY(quint16 remotePort READ remotePort) 0062 Q_PROPERTY(QString method READ method) 0063 Q_PROPERTY(QUrl url READ url) 0064 Q_PROPERTY(QString path READ path) 0065 Q_PROPERTY(QString httpVersion READ httpVersion) 0066 Q_ENUMS(HttpMethod) 0067 0068 public: 0069 virtual ~QHttpRequest(); 0070 0071 /*! 0072 * Request Methods 0073 * Taken from http_parser.h -- make sure to keep synced 0074 */ 0075 enum HttpMethod { 0076 HTTP_DELETE = 0, 0077 HTTP_GET, 0078 HTTP_HEAD, 0079 HTTP_POST, 0080 HTTP_PUT, 0081 /* pathological */ 0082 HTTP_CONNECT, 0083 HTTP_OPTIONS, 0084 HTTP_TRACE, 0085 /* webdav */ 0086 HTTP_COPY, 0087 HTTP_LOCK, 0088 HTTP_MKCOL, 0089 HTTP_MOVE, 0090 HTTP_PROPFIND, 0091 HTTP_PROPPATCH, 0092 HTTP_SEARCH, 0093 HTTP_UNLOCK, 0094 /* subversion */ 0095 HTTP_REPORT, 0096 HTTP_MKACTIVITY, 0097 HTTP_CHECKOUT, 0098 HTTP_MERGE, 0099 /* upnp */ 0100 HTTP_MSEARCH, 0101 HTTP_NOTIFY, 0102 HTTP_SUBSCRIBE, 0103 HTTP_UNSUBSCRIBE, 0104 /* RFC-5789 */ 0105 HTTP_PATCH, 0106 HTTP_PURGE 0107 }; 0108 0109 /*! 0110 * Returns the method string for the request 0111 */ 0112 const QString methodString() const { return MethodToString(method()); } 0113 0114 /*! 0115 * The method used for the request. 0116 */ 0117 HttpMethod method() const { return m_method; }; 0118 0119 /*! 0120 * The complete URL for the request. This 0121 * includes the path and query string. 0122 * 0123 */ 0124 const QUrl& url() const { return m_url; }; 0125 0126 /*! 0127 * The path portion of the query URL. 0128 * 0129 * \sa url() 0130 */ 0131 const QString path() const { return m_url.path(); }; 0132 0133 /*! 0134 * The HTTP version used by the client as a 0135 * 'x.x' string. 0136 */ 0137 const QString& httpVersion() const { return m_version; }; 0138 0139 /*! 0140 * Any query string included as part of a request. 0141 * Usually used to send data in a GET request. 0142 */ 0143 const QString& queryString() const; 0144 0145 /*! 0146 * Get a hash of the headers sent by the client. 0147 * NOTE: All header names are <strong>lowercase</strong> 0148 * so that Content-Length becomes content-length and so on. 0149 * 0150 * This returns a reference! If you want to store headers 0151 * somewhere else, where the request may be deleted, 0152 * make sure you store them as a copy. 0153 */ 0154 const HeaderHash& headers() const { return m_headers; }; 0155 0156 /*! 0157 * Get the value of a header 0158 * 0159 * \param field Name of the header field (lowercase). 0160 * \return Value of the header or null QString() 0161 */ 0162 QString header(const QString &field) { return m_headers[field]; }; 0163 0164 /*! 0165 * IP Address of the client in dotted decimal format 0166 */ 0167 const QString& remoteAddress() const { return m_remoteAddress; }; 0168 0169 /*! 0170 * Outbound connection port for the client. 0171 */ 0172 quint16 remotePort() const { return m_remotePort; }; 0173 0174 /*! 0175 * Post data 0176 */ 0177 const QByteArray &body() const { return m_body; } 0178 0179 /*! 0180 * Set immediately before end has been emitted, 0181 * stating whether the message was properly received. 0182 * Defaults to false untiil the message has completed. 0183 */ 0184 bool successful() const { return m_success; } 0185 0186 /*! 0187 * connect to data and store all data in a QByteArray 0188 * accessible at body() 0189 */ 0190 void storeBody() 0191 { 0192 connect(this, SIGNAL(data(const QByteArray &)), 0193 this, SLOT(appendBody(const QByteArray &)), 0194 Qt::UniqueConnection); 0195 } 0196 0197 Q: 0198 /*! 0199 * This signal is emitted whenever body data is encountered 0200 * in a message. 0201 * This may be emitted zero or more times. 0202 */ 0203 void data(const QByteArray &); 0204 0205 /*! 0206 * Emitted at the end of the HTTP request. 0207 * No data() Q will be emitted after this. 0208 */ 0209 void end(); 0210 0211 private: 0212 QHttpRequest(QHttpConnection *connection, QObject *parent = 0); 0213 0214 static QString MethodToString(HttpMethod method) 0215 { 0216 int index = staticMetaObject.indexOfEnumerator("HttpMethod"); 0217 return staticMetaObject.enumerator(index).valueToKey(method); 0218 } 0219 0220 void setMethod(HttpMethod method) { m_method = method; } 0221 void setVersion(const QString &version) { m_version = version; } 0222 void setUrl(const QUrl &url) { m_url = url; } 0223 void setHeaders(const HeaderHash headers) { m_headers = headers; } 0224 void setSuccessful(bool success) { m_success = success; } 0225 0226 QHttpConnection *m_connection; 0227 HeaderHash m_headers; 0228 HttpMethod m_method; 0229 QUrl m_url; 0230 QString m_version; 0231 QString m_remoteAddress; 0232 quint16 m_remotePort; 0233 QByteArray m_body; 0234 bool m_success; 0235 0236 friend class QHttpConnection; 0237 0238 private Q_SLOTS: 0239 void appendBody(const QByteArray &body) 0240 { 0241 m_body.append(body); 0242 } 0243 }; 0244 0245 #endif