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