File indexing completed on 2025-02-02 04:36:32

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_RESPONSE
0024 #define Q_HTTP_RESPONSE
0025 
0026 #include <QObject>
0027 #include <QHash>
0028 
0029 //
0030 class QTcpSocket;
0031 
0032 class QHttpConnection;
0033 
0034 typedef QHash<QString, QString> HeaderHash;
0035 
0036 /*!
0037  * The QHttpResponse class handles sending
0038  * data back to the client in response to a request.
0039  *
0040  * The way to respond is to:
0041  * <ol>
0042  * <li>Set headers (optional).</li>
0043  * <li>Call writeHead() with the HTTP status code.</li>
0044  * <li>Call write() zero or more times.</li>
0045  * <li>Call end() when you are ready to end the request.</li>
0046  * </ol>
0047  *
0048  */
0049 class QHttpResponse : public QObject
0050 {
0051     Q_OBJECT
0052 
0053 public:
0054     enum StatusCode {
0055       STATUS_CONTINUE = 100,
0056       STATUS_SWITCH_PROTOCOLS = 101,
0057       STATUS_OK = 200,
0058       STATUS_CREATED = 201,
0059       STATUS_ACCEPTED = 202,
0060       STATUS_NON_AUTHORITATIVE_INFORMATION = 203,
0061       STATUS_NO_CONTENT = 204,
0062       STATUS_RESET_CONTENT = 205,
0063       STATUS_PARTIAL_CONTENT = 206,
0064       STATUS_MULTIPLE_CHOICES = 300,
0065       STATUS_MOVED_PERMANENTLY = 301,
0066       STATUS_FOUND = 302,
0067       STATUS_SEE_OTHER = 303,
0068       STATUS_NOT_MODIFIED = 304,
0069       STATUS_USE_PROXY = 305,
0070       STATUS_TEMPORARY_REDIRECT = 307,
0071       STATUS_BAD_REQUEST = 400,
0072       STATUS_UNAUTHORIZED = 401,
0073       STATUS_PAYMENT_REQUIRED = 402,
0074       STATUS_FORBIDDEN = 403,
0075       STATUS_NOT_FOUND = 404,
0076       STATUS_METHOD_NOT_ALLOWED = 405,
0077       STATUS_NOT_ACCEPTABLE = 406,
0078       STATUS_PROXY_AUTHENTICATION_REQUIRED = 407,
0079       STATUS_REQUEST_TIMEOUT = 408,
0080       STATUS_CONFLICT = 409,
0081       STATUS_GONE = 410,
0082       STATUS_LENGTH_REQUIRED = 411,
0083       STATUS_PRECONDITION_FAILED = 412,
0084       STATUS_REQUEST_ENTITY_TOO_LARGE = 413,
0085       STATUS_REQUEST_URI_TOO_LONG = 414,
0086       STATUS_REQUEST_UNSUPPORTED_MEDIA_TYPE = 415,
0087       STATUS_REQUESTED_RANGE_NOT_SATISFIABLE = 416,
0088       STATUS_EXPECTATION_FAILED = 417,
0089       STATUS_INTERNAL_SERVER_ERROR = 500,
0090       STATUS_NOT_IMPLEMENTED = 501,
0091       STATUS_BAD_GATEWAY = 502,
0092       STATUS_SERVICE_UNAVAILABLE = 503,
0093       STATUS_GATEWAY_TIMEOUT = 504,
0094       STATUS_HTTP_VERSION_NOT_SUPPORTED = 505
0095     };
0096 
0097     virtual ~QHttpResponse();
0098 
0099 public Q_SLOTS:
0100     /*!
0101      * Write the header of the response
0102      * using @c status as the response status
0103      * code. Any headers should be set before this
0104      * is called.
0105      */
0106     Q_INVOKABLE void writeHead(int status);
0107 
0108     /*!
0109      * Write the block of data to the client.
0110      * 
0111      * \note
0112      * writeHead() has to be called before write(), otherwise the call will
0113      * fail.
0114      */
0115     Q_INVOKABLE void write(const QByteArray &data);
0116 
0117     /*!
0118      * Write a QString instead of a QByteArray.
0119      * \see write(const QByteArray &);
0120      */
0121     Q_INVOKABLE void write(const QString &data);
0122 
0123     /*!
0124      * Write data that has been encoded in base64.
0125      */
0126     Q_INVOKABLE void write_b64(const QByteArray &data);
0127 
0128     /*!
0129      * End the response. Data will be flushed
0130      * to the underlying socket and the connection
0131      * itself will be closed if this is the last
0132      * response.
0133      *
0134      * This will Q_EMIT done() and queue this object
0135      * for deletion. For details see \ref memorymanagement
0136      */
0137     Q_INVOKABLE void end(const QString &data=QString());
0138 
0139     /*!
0140      * Set a response header @c field to @c value
0141      */
0142     Q_INVOKABLE void setHeader(const QString &field, const QString &value);
0143 
0144 Q:
0145     /*!
0146      * Emitted once the response is finished.
0147      * You should NOT interact with this object
0148      * after done() has been emitted as the object
0149      * is scheduled for deletion at any time.
0150      */
0151     void done();
0152 
0153 private:
0154     QHttpResponse(QHttpConnection *connection);
0155 
0156     void writeHeaders();
0157     void writeHeader(const char *field, const QString &value);
0158 
0159     QHttpConnection *m_connection;
0160 
0161     bool m_headerWritten;
0162     HeaderHash m_headers;
0163     friend class QHttpConnection;
0164 
0165     bool m_sentConnectionHeader;
0166     bool m_sentContentLengthHeader;
0167     bool m_sentTransferEncodingHeader;
0168     bool m_sentDate;
0169     bool m_keepAlive;
0170     bool m_last;
0171     bool m_useChunkedEncoding;
0172     bool m_finished;
0173 
0174 private Q_SLOTS:
0175     void connectionClosed();
0176 
0177 };
0178 
0179 #endif