TTKMusicPlayer  3.7.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
qhttpresponse.cpp
Go to the documentation of this file.
1 #include "qhttpresponse.h"
2 
3 #include <QDateTime>
4 #include <QLocale>
5 
6 #include "qhttpserver.h"
7 #include "qhttpconnection.h"
8 
12 class QHttpResponsePrivate : public TTKPrivate<QHttpResponse>
13 {
14 public:
16 
17  void writeHeaders();
18  void writeHead(int status);
19  void writeHeader(const char *field, const QString &value);
20  void write(const QByteArray &data);
21 
22  void setHeader(const QString &field, const QString &value);
23 
25 
27 
32  bool m_sentDate;
34  bool m_last;
36  bool m_finished;
37 
38 };
39 
41  : m_connection(nullptr),
42  m_headerWritten(false),
43  m_sentConnectionHeader(false),
44  m_sentContentLengthHeader(false),
45  m_sentTransferEncodingHeader(false),
46  m_sentDate(false),
47  m_keepAlive(true),
48  m_last(false),
49  m_useChunkedEncoding(false),
50  m_finished(false)
51 {
52 
53 }
54 
56 {
57  if(m_finished)
58  {
59  return;
60  }
61 
62  for(const QString &name : m_headers.keys())
63  {
64  QString value = m_headers[name];
65  if(name.compare("connection", Qt::CaseInsensitive) == 0)
66  {
68  if(value.compare("close", Qt::CaseInsensitive) == 0)
69  {
70  m_last = true;
71  }
72  else
73  {
74  m_keepAlive = true;
75  }
76  }
77  else if(name.compare("transfer-encoding", Qt::CaseInsensitive) == 0)
78  {
80  if(value.compare("chunked", Qt::CaseInsensitive) == 0)
81  {
82  m_useChunkedEncoding = true;
83  }
84  }
85  else if(name.compare("content-length", Qt::CaseInsensitive) == 0)
86  {
88  }
89  else if(name.compare("date", Qt::CaseInsensitive) == 0)
90  {
91  m_sentDate = true;
92  }
93 
94  writeHeader(name.toLatin1(), value.toLatin1());
95  }
96 
98  {
100  {
101  writeHeader("Connection", "keep-alive");
102  }
103  else
104  {
105  m_last = true;
106  writeHeader("Connection", "close");
107  }
108  }
109 
111  {
113  {
114  writeHeader("Transfer-Encoding", "chunked");
115  }
116  else
117  {
118  m_last = true;
119  }
120  }
121 
122  // Sun, 06 Nov 1994 08:49:37 GMT - RFC 822. Use QLocale::c() so english is used for month and
123  // day.
124  if(!m_sentDate)
125  {
126  writeHeader("Date",
127  QLocale::c().toString(QDateTime::currentDateTimeUtc(),
128  "ddd, dd MMM yyyy hh:mm:ss") + " GMT");
129  }
130 }
131 
133 {
134  if(m_finished)
135  {
136  qWarning() << "QHttpResponse::writeHead() Cannot write headers after response has finished.";
137  return;
138  }
139 
140  if(m_headerWritten){
141  qWarning() << "QHttpResponse::writeHead() Already called once for this response.";
142  return;
143  }
144 
145  m_connection->write(QString("HTTP/1.1 %1 %2\r\n").arg(status).arg(STATUS_CODES[status]).toLatin1());
146  writeHeaders();
147  m_connection->write("\r\n");
148 
149  m_headerWritten = true;
150 }
151 
152 void QHttpResponsePrivate::writeHeader(const char *field, const QString &value)
153 {
154  if(!m_finished)
155  {
156  m_connection->write(field);
157  m_connection->write(": ");
158  m_connection->write(value.toUtf8());
159  m_connection->write("\r\n");
160  }
161  else
162  {
163  qWarning() << "QHttpResponse::writeHeader() Cannot write headers after response has finished.";
164  }
165 }
166 
167 void QHttpResponsePrivate::write(const QByteArray &data)
168 {
169  if(m_finished)
170  {
171  qWarning() << "QHttpResponse::write() Cannot write body after response has finished.";
172  return;
173  }
174 
175  if(!m_headerWritten)
176  {
177  qWarning() << "QHttpResponse::write() You must call writeHead() before writing body data.";
178  return;
179  }
180 
181  m_connection->write(data);
182 }
183 
184 void QHttpResponsePrivate::setHeader(const QString &field, const QString &value)
185 {
186  if(!m_finished)
187  {
188  m_headers[field] = value;
189  }
190  else
191  {
192  qWarning() << "QHttpResponse::setHeader() Cannot set headers after response has finished.";
193  }
194 }
195 
196 
197 
199  : QObject(0)
200 {
203  d->m_connection = connection;
204  connect(connection, SIGNAL(allBytesWritten()), this, SIGNAL(allBytesWritten()));
205 }
206 
207 void QHttpResponse::setHeader(const QString &field, const QString &value)
208 {
210  d->setHeader(field, value);
211 }
212 
213 void QHttpResponse::writeHead(int status)
214 {
216  d->writeHead(status);
217 }
218 
220 {
222  d->writeHead(TTKStaticCast(int, statusCode));
223 }
224 
225 void QHttpResponse::write(const QByteArray &data)
226 {
228  d->write(data);
229 }
230 
232 {
234  d->m_connection->flush();
235 }
236 
238 {
240  d->m_connection->waitForBytesWritten();
241 }
242 
243 void QHttpResponse::end(const QByteArray &data)
244 {
246  if(d->m_finished)
247  {
248  qWarning() << "QHttpResponse::end() Cannot write end after response has finished.";
249  return;
250  }
251 
252  if(data.length() > 0)
253  {
254  write(data);
255  }
256  d->m_finished = true;
257 
258  Q_EMIT done();
259 
261  deleteLater();
262 }
263 
265 {
267  d->m_finished = true;
268  Q_EMIT done();
269  deleteLater();
270 }
271 
273 {
275  d->m_keepAlive = alive;
276 }
277 
279 {
281  return d->m_last;
282 }
#define TTKStaticCast(x, y)
Definition: ttkglobal.h:159
The class of the http response.
Definition: qhttpresponse.h:29
The class of the http connection.
void write(const QByteArray &data)
Writes a block of data to the client.
bool isLast() const
void flush()
Flushes the written data to the client.
void setKeepAlive(bool alive)
void end(const QByteArray &data="")
End/finish the response.
void writeHeader(const char *field, const QString &value)
void waitForBytesWritten()
Waiting for bytes to be written. See QAbstractSocket::waitForBytesWritten in the Qt documentation...
void connectionClosed()
QHash< int, QString > STATUS_CODES
Maps status codes to string reason phrases.
Definition: qhttpserver.cpp:9
const char * name
Definition: http_parser.c:458
StatusCode
HTTP status code.
Definition: qhttpresponse.h:34
QHttpConnection * m_connection
void write(const QByteArray &data)
void writeHead(int status)
void write(const QByteArray &data)
QHttpResponse(QHttpConnection *connection)
QHash< QString, QString > HeaderHash
The class of the http response private.
TTK_MODULE_EXPORT QString toString(Record type)
void done()
Emitted when the response is finished.
void setHeader(const QString &field, const QString &value)
Sets a response header field to value.
#define TTK_INIT_PRIVATE(Class)
Definition: ttkprivate.h:33
void setHeader(const QString &field, const QString &value)
void allBytesWritten()
Emitted when all the data has been sent.
The class of the ttk private base.
Definition: ttkprivate.h:48
void writeHead(int statusCode)
Writes the header section of the response using status as the response status code.
#define TTK_D(Class)
Definition: ttkprivate.h:41