File indexing completed on 2024-12-08 09:40:32
0001 /* 0002 SPDX-FileCopyrightText: 2010-2016 Klaralvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> 0003 SPDX-FileContributor: David Faure <david.faure@kdab.com> 0004 0005 This file initially comes from the KD Soap library. 0006 0007 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only 0008 */ 0009 0010 #ifndef HTTPSERVER_P_H 0011 #define HTTPSERVER_P_H 0012 0013 #include <QMutex> 0014 #include <QSemaphore> 0015 #include <QSslError> 0016 #include <QTcpServer> 0017 #include <QTcpSocket> 0018 #include <QThread> 0019 0020 class BlockingHttpServer; 0021 0022 class HttpServerThread : public QThread 0023 { 0024 Q_OBJECT 0025 public: 0026 enum Feature { 0027 Public = 0, // HTTP with no ssl and no authentication needed 0028 Ssl = 1, // HTTPS 0029 BasicAuth = 2, // Requires authentication 0030 Error404 = 4, // Return "404 not found" 0031 // bitfield, next item is 8 0032 }; 0033 Q_DECLARE_FLAGS(Features, Feature) 0034 0035 HttpServerThread(const QByteArray &dataToSend, Features features) 0036 : m_dataToSend(dataToSend) 0037 , m_features(features) 0038 { 0039 start(); 0040 m_ready.acquire(); 0041 } 0042 ~HttpServerThread() override 0043 { 0044 finish(); 0045 wait(); 0046 } 0047 0048 void setContentType(const QByteArray &mime) 0049 { 0050 QMutexLocker lock(&m_mutex); 0051 m_contentType = mime; 0052 } 0053 0054 void setResponseData(const QByteArray &data) 0055 { 0056 QMutexLocker lock(&m_mutex); 0057 m_dataToSend = data; 0058 } 0059 0060 void setFeatures(Features features) 0061 { 0062 QMutexLocker lock(&m_mutex); 0063 m_features = features; 0064 } 0065 0066 void disableSsl(); 0067 inline int serverPort() const 0068 { 0069 QMutexLocker lock(&m_mutex); 0070 return m_port; 0071 } 0072 QString endPoint() const 0073 { 0074 return QString::fromLatin1("%1://127.0.0.1:%2/path").arg(QString::fromLatin1((m_features & Ssl) ? "https" : "http")).arg(serverPort()); 0075 } 0076 0077 void finish(); 0078 0079 QByteArray receivedData() const 0080 { 0081 QMutexLocker lock(&m_mutex); 0082 return m_receivedData; 0083 } 0084 QByteArray receivedHeaders() const 0085 { 0086 QMutexLocker lock(&m_mutex); 0087 return m_receivedHeaders; 0088 } 0089 void resetReceivedBuffers() 0090 { 0091 QMutexLocker lock(&m_mutex); 0092 m_receivedData.clear(); 0093 m_receivedHeaders.clear(); 0094 } 0095 0096 QByteArray header(const QByteArray &value) const 0097 { 0098 QMutexLocker lock(&m_mutex); 0099 return m_headers.value(value); 0100 } 0101 0102 protected: 0103 /* \reimp */ void run() override; 0104 0105 private: 0106 QByteArray makeHttpResponse(const QByteArray &responseData) const; 0107 0108 private: 0109 QByteArray m_partialRequest; 0110 QSemaphore m_ready; 0111 QByteArray m_dataToSend; 0112 QByteArray m_contentType; 0113 0114 mutable QMutex m_mutex; // protects the 4 vars below 0115 QByteArray m_receivedData; 0116 QByteArray m_receivedHeaders; 0117 QMap<QByteArray, QByteArray> m_headers; 0118 int m_port; 0119 0120 Features m_features; 0121 BlockingHttpServer *m_server; 0122 }; 0123 0124 Q_DECLARE_OPERATORS_FOR_FLAGS(HttpServerThread::Features) 0125 0126 // A blocking http server (must be used in a thread) which supports SSL. 0127 class BlockingHttpServer : public QTcpServer 0128 { 0129 Q_OBJECT 0130 public: 0131 BlockingHttpServer(bool ssl) 0132 : doSsl(ssl) 0133 , sslSocket(nullptr) 0134 { 0135 } 0136 ~BlockingHttpServer() override 0137 { 0138 } 0139 0140 QTcpSocket *waitForNextConnectionSocket() 0141 { 0142 if (!waitForNewConnection(20000)) { // 2000 would be enough, except in valgrind 0143 return nullptr; 0144 } 0145 if (doSsl) { 0146 Q_ASSERT(sslSocket); 0147 return sslSocket; 0148 } else { 0149 // qDebug() << "returning nextPendingConnection"; 0150 return nextPendingConnection(); 0151 } 0152 } 0153 0154 void incomingConnection(qintptr socketDescriptor) override; 0155 0156 void disableSsl() 0157 { 0158 doSsl = false; 0159 } 0160 0161 private Q_SLOTS: 0162 void slotSslErrors(const QList<QSslError> &errors) 0163 { 0164 qDebug() << "server-side: slotSslErrors" << sslSocket->errorString() << errors; 0165 } 0166 0167 private: 0168 bool doSsl; 0169 QTcpSocket *sslSocket; 0170 }; 0171 0172 #endif /* HTTPSERVER_P_H */