// // HTTPConnection.h // libraries/embedded-webserver/src // // Created by Stephen Birarda on 1/16/14. // Copyright 2014 High Fidelity, Inc. // // Heavily based on Andrzej Kapolka's original HTTPConnection class // found from another one of his projects. // https://github.com/ey6es/witgap/tree/master/src/cpp/server/http // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #ifndef hifi_HTTPConnection_h #define hifi_HTTPConnection_h #include #include #include #include #include #include #include #include #include #include class QTcpSocket; class HTTPManager; class MaskFilter; class ServerApp; /// Header hash typedef QHash Headers; /// A form data element typedef QPair FormData; /// Handles a single HTTP connection. class HTTPConnection : public QObject { Q_OBJECT public: static const char* StatusCode200; static const char* StatusCode301; static const char* StatusCode302; static const char* StatusCode400; static const char* StatusCode401; static const char* StatusCode403; static const char* StatusCode404; static const char* StatusCode500; static const char* DefaultContentType; /// WebSocket close status codes. enum ReasonCode { NoReason = 0, NormalClosure = 1000, GoingAway = 1001 }; class Storage { public: Storage() = default; virtual ~Storage() = default; virtual const QByteArray& content() const = 0; virtual qint64 bytesLeftToWrite() const = 0; virtual void write(const QByteArray& data) = 0; }; /// Initializes the connection. HTTPConnection(QTcpSocket* socket, HTTPManager* parentManager); /// Destroys the connection. virtual ~HTTPConnection(); /// Returns a pointer to the underlying socket, to which WebSocket message bodies should be written. QTcpSocket* socket() const { return _socket; } /// Returns the request operation. QNetworkAccessManager::Operation requestOperation() const { return _requestOperation; } /// Returns a reference to the request URL. const QUrl& requestUrl() const { return _requestUrl; } /// Returns a copy of the request header value. If it does not exist, it will return a default constructed QByteArray. QByteArray requestHeader(const QString& key) const { return _requestHeaders.value(key.toLower().toLocal8Bit()); } /// Returns a reference to the request content. const QByteArray& requestContent() const { return _requestContent->content(); } /// Parses the request content as form data, returning a list of header/content pairs. QList parseFormData() const; /// Parses the request content as a url encoded form, returning a hash of key/value pairs. /// Duplicate keys are not supported. QHash parseUrlEncodedForm(); /// Sends a response and closes the connection. void respond(const char* code, const QByteArray& content = QByteArray(), const char* contentType = DefaultContentType, const Headers& headers = Headers()); void respond(const char* code, std::unique_ptr device, const char* contentType = DefaultContentType, const Headers& headers = Headers()); protected slots: /// Reads the request line. void readRequest(); /// Reads the headers. void readHeaders(); /// Reads the content. void readContent(); protected: void respondWithStatusAndHeaders(const char* code, const char* contentType, const Headers& headers, qint64 size); /// The parent HTTP manager HTTPManager* _parentManager; /// The underlying socket. QTcpSocket* _socket; /// The stored address. QHostAddress _address; /// The requested operation. QNetworkAccessManager::Operation _requestOperation; /// The requested URL. QUrl _requestUrl; /// The request headers. Headers _requestHeaders; /// The last request header processed (used for continuations). QByteArray _lastRequestHeader; /// The content of the request. std::unique_ptr _requestContent; /// Response content std::unique_ptr _responseDevice; }; #endif // hifi_HTTPConnection_h