• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Unionman Technology Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef JQHTTPSERVER_H
17 #define JQHTTPSERVER_H
18 
19 #ifndef QT_NETWORK_LIB
20 #error("Please add network in pro file")
21 #endif
22 
23 #ifndef QT_CONCURRENT_LIB
24 #error("Please add concurrent in pro file")
25 #endif
26 
27 // C++ lib import
28 #include <functional>
29 
30 // Qt lib import
31 #include <QHostAddress>
32 #include <QMap>
33 #include <QMutex>
34 #include <QObject>
35 #include <QPointer>
36 #include <QSet>
37 #include <QSharedPointer>
38 #include <QUrl>
39 #include <QVector>
40 
41 class QIODevice;
42 class QThreadPool;
43 class QHostAddress;
44 class QTimer;
45 class QImage;
46 class QTcpServer;
47 class QLocalServer;
48 class QSslCertificate;
49 class QSslKey;
50 class QSslConfiguration;
51 
52 namespace JQHttpServer {
53 
54     class Session : public QObject {
55         Q_OBJECT
56         Q_DISABLE_COPY(Session)
57 
58     public:
59         Session(const QPointer<QIODevice>& tcpSocket);
60 
61         ~Session();
62 
setHandleAcceptedCallback(const std::function<void (const QPointer<Session> &)> & callback)63         inline void setHandleAcceptedCallback(const std::function<void(const QPointer<Session>&)>& callback)
64         {
65             handleAcceptedCallback_ = callback;
66         }
67 
requestMethod()68         inline QString requestMethod() const
69         {
70             return requestMethod_;
71         }
72 
requestUrl()73         inline QString requestUrl() const
74         {
75             return requestUrl_;
76         }
77 
requestCrlf()78         inline QString requestCrlf() const
79         {
80             return requestCrlf_;
81         }
82 
requestHeader()83         inline QMap<QString, QString> requestHeader() const
84         {
85             return requestHeader_;
86         }
87 
requestBody()88         inline QByteArray requestBody() const
89         {
90             return requestBody_;
91         }
92 
93         QString requestUrlPath() const;
94 
95         QStringList requestUrlPathSplitToList() const;
96 
97         QMap<QString, QString> requestUrlQuery() const;
98 
GetIODevice()99         inline QIODevice* GetIODevice() const
100         {
101             return ioDevice_.data();
102         }
103 
104     public slots:
105         void ReplyText(const QString& replyData, const int& httpStatusCode = 200);
106 
107         void ReplyRedirects(const QUrl& targetUrl, const int& httpStatusCode = 200);
108 
109         void ReplyJsonObject(const QJsonObject& jsonObject, const int& httpStatusCode = 200);
110 
111         void ReplyJsonArray(const QJsonArray& jsonArray, const int& httpStatusCode = 200);
112 
113         void ReplyFile(const QString& filePath, const int& httpStatusCode = 200);
114 
115         void ReplyImage(const QImage& image, const int& httpStatusCode = 200);
116 
117         void ReplyImage(const QString& imageFilePath, const int& httpStatusCode = 200);
118 
119         void ReplyBytes(const QByteArray& bytes, const int& httpStatusCode = 200);
120 
121         void ReplyOptions();
122 
123     private:
124         void InspectionBufferSetup1();
125 
126         void InspectionBufferSetup2();
127 
128     private:
129         QPointer<QIODevice> ioDevice_;
130         std::function<void(const QPointer<Session>&)> handleAcceptedCallback_;
131         QSharedPointer<QTimer> timerForClose_;
132 
133         QByteArray buffer_;
134 
135         QString requestMethod_;
136         QString requestUrl_;
137         QString requestCrlf_;
138 
139         QMap<QString, QString> requestHeader_;
140         bool headerAcceptedFinish_ = false;
141         qint64 contentLength_ = -1;
142         bool alreadyReply_ = false;
143 
144         QByteArray requestBody_;
145 
146         qint64 waitWrittenByteCount_ = 0;
147         QSharedPointer<QIODevice> ioDeviceForReply_;
148     };
149 
150     class AbstractManage : public QObject {
151         Q_OBJECT
152         Q_DISABLE_COPY(AbstractManage)
153 
154     public:
155         AbstractManage(const int& handleMaxThreadCount);
156 
157         virtual ~AbstractManage();
158 
setHttpAcceptedCallback(const std::function<void (const QPointer<Session> & session)> & httpAcceptedCallback)159         inline void setHttpAcceptedCallback(
160             const std::function<void(const QPointer<Session>& session)>& httpAcceptedCallback)
161         {
162             httpAcceptedCallback_ = httpAcceptedCallback;
163         }
164 
handleThreadPool()165         inline QSharedPointer<QThreadPool> handleThreadPool()
166         {
167             return handleThreadPool_;
168         }
169 
serverThreadPool()170         inline QSharedPointer<QThreadPool> serverThreadPool()
171         {
172             return serverThreadPool_;
173         }
174 
175         virtual bool IsRunning() = 0;
176 
177     protected Q_SLOTS:
178         bool Begin();
179 
180         void Close();
181 
182     protected:
183         virtual bool OnStart() = 0;
184 
185         virtual void OnFinish() = 0;
186 
187         bool StartServerThread();
188 
189         void StopHandleThread();
190 
191         void StopServerThread();
192 
193         void NewSession(const QPointer<Session>& session);
194 
195         void HandleAccepted(const QPointer<Session>& session);
196 
197     signals:
198         void readyToClose();
199 
200     protected:
201         QSharedPointer<QThreadPool> serverThreadPool_;
202         QSharedPointer<QThreadPool> handleThreadPool_;
203 
204         QMutex mutex_;
205 
206         std::function<void(const QPointer<Session>& session)> httpAcceptedCallback_;
207 
208         QSet<Session*> availableSessions_;
209     };
210 
211     class TcpServerManage : public AbstractManage {
212         Q_OBJECT
213         Q_DISABLE_COPY(TcpServerManage)
214 
215     public:
216         TcpServerManage(const int& handleMaxThreadCount = 2);
217 
218         ~TcpServerManage() override;
219 
220         bool Listen(const QHostAddress& address, const quint16& port);
221 
222         bool IsRunning() override;
223 
224     private:
225         bool OnStart() override;
226 
227         void OnFinish() override;
228 
229     private:
230         QPointer<QTcpServer> tcpServer_;
231 
232         QHostAddress listenAddress_ = QHostAddress::Any;
233         quint16 listenPort_ = 0;
234     };
235 
236 #ifndef QT_NO_SSL
237     class SslServerHelper;
238 
239     class SslServerManage : public AbstractManage {
240         Q_OBJECT
241         Q_DISABLE_COPY(SslServerManage)
242 
243     public:
244         SslServerManage(const int& handleMaxThreadCount = 2);
245 
246         ~SslServerManage() override;
247 
248         bool Listen(const QHostAddress& address, const quint16& port, const QString& crtFilePath,
249             const QString& keyFilePath, const QList<QPair<QString, bool>>& caFileList = {} // [ { filePath, isPem } ]
250         );
251 
252         bool IsRunning() override;
253 
254     private:
255         bool OnStart() override;
256 
257         void OnFinish() override;
258 
259     private:
260         QPointer<SslServerHelper> tcpServer_;
261 
262         QHostAddress listenAddress_ = QHostAddress::Any;
263         quint16 listenPort_ = 0;
264 
265         QSharedPointer<QSslConfiguration> sslConfiguration_;
266     };
267 #endif
268 
269     class LocalServerManage : public AbstractManage {
270         Q_OBJECT
271         Q_DISABLE_COPY(LocalServerManage)
272 
273     public:
274         LocalServerManage(const int& handleMaxThreadCount);
275 
276         ~LocalServerManage() override;
277 
278         bool Listen(const QString& name);
279 
280         bool IsRunning() override;
281 
282     private:
283         bool OnStart() override;
284 
285         void OnFinish() override;
286 
287     private:
288         QPointer<QLocalServer> localServer_;
289 
290         QString listenName_;
291     };
292 
293 }
294 
295 #endif // JQHTTPSERVER_H_
296