| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /*
- Copyright 2017 Herik Lima de Castro and Marcelo Medeiros Eler
- Distributed under MIT license, or public domain if desired and
- recognized in your jurisdiction.
- See file LICENSE for detail.
- */
- #include "response.h"
- #include <QDateTime>
- #include "configuration.h"
- CWF_BEGIN_NAMESPACE
- Response::Response(QTcpSocket &socket, const Configuration &configuration)
- : socket(socket)
- , configuration(configuration)
- {}
- static void sendBytes(QTcpSocket &socket, const QByteArray &text, int timeOut)
- {
- const QAbstractSocket::SocketState &state = socket.state();
- if (state == QAbstractSocket::ConnectedState && text.size() > 0) {
- socket.write(text, text.size());
- socket.flush();
- if (state == QAbstractSocket::ConnectedState) {
- socket.waitForBytesWritten(timeOut);
- }
- }
- }
- static void buildHeadersString(QByteArray &temp, const QMap<QByteArray, QByteArray> &headers)
- {
- QList<QByteArray> headersList(headers.keys());
- for (const auto &i : headersList) {
- temp.push_back(i);
- temp.push_back(HTTP::SEPARATOR);
- temp.push_back(headers.value(i));
- temp.push_back(HTTP::END_LINE);
- }
- }
- static void buildCookiesString(QByteArray &temp, const QVector<QNetworkCookie> &cookies)
- {
- for (const auto &i : cookies) {
- temp.push_back(HTTP::SET_COOKIE);
- temp.push_back(i.toRawForm());
- temp.push_back(HTTP::END_LINE);
- }
- }
- static void sendHeaders(int statusCode,
- int timeOut,
- const QByteArray &statusText,
- QMap<QByteArray, QByteArray> &headers,
- QVector<QNetworkCookie> &cookies,
- QTcpSocket &socket)
- {
- QByteArray temp(HTTP::HTTP_1_1);
- temp.reserve(100);
- temp.push_back(QByteArray::number(statusCode));
- temp.push_back(' ');
- temp.push_back(statusText);
- temp.push_back(HTTP::END_LINE);
- if (!headers.contains(HTTP::CONTENT_TYPE)) {
- headers.insert(HTTP::CONTENT_TYPE, HTTP::TEXT_HTML_UTF8);
- }
- buildHeadersString(temp, headers);
- buildCookiesString(temp, cookies);
- temp.push_back(HTTP::END_LINE);
- sendBytes(socket, temp, timeOut);
- }
- void Response::flushBuffer()
- {
- const int max = 32768;
- if (!content.isEmpty()) {
- static QLocale englishLocale(QLocale::English);
- int timeOut = configuration.getTimeOut();
- bool biggerThanLimit = content.size() > max;
- headers.insert(HTTP::CONTENT_LENGTH, QByteArray::number(content.size()));
- headers.insert(HTTP::SERVER, HTTP::SERVER_VERSION);
- headers.insert(HTTP::DATA,
- QByteArray(
- englishLocale
- .toString(QDateTime::currentDateTime(), "ddd, dd MMM yyyy hh:mm:ss")
- .toUtf8()
- + " GMT"));
- if (!biggerThanLimit) {
- sendHeaders(statusCode, timeOut, statusText, headers, cookies, socket);
- sendBytes(socket, content, timeOut);
- } else {
- headers.insert(HTTP::TRANSFER_ENCODING, HTTP::CHUNKED);
- sendHeaders(statusCode, timeOut, statusText, headers, cookies, socket);
- int total = (content.size() / max) + 1, last = 0;
- QVector<QByteArray> vetor;
- for (int i = 0; i < total; ++i) {
- vetor.push_back(content.mid(last, max));
- last += max;
- }
- for (auto &i : vetor) {
- QByteArray data(std::move(i));
- if (!data.isEmpty()) {
- sendBytes(socket,
- (QByteArray::number(data.size(), 16) + HTTP::END_LINE),
- timeOut);
- sendBytes(socket, data, timeOut);
- sendBytes(socket, HTTP::END_LINE, timeOut);
- }
- }
- sendBytes(socket, HTTP::END_OF_MESSAGE_WITH_ZERO, timeOut);
- }
- socket.disconnectFromHost();
- // content.clear();
- }
- }
- void Response::sendError(int sc, const QByteArray &msg)
- {
- int timeOut = configuration.getTimeOut();
- sendHeaders(statusCode, timeOut, statusText, headers, cookies, socket);
- sendBytes(socket,
- "<html><body><h1>" + QByteArray::number(sc) + " " + msg + "</h1></body></html>",
- timeOut);
- }
- void Response::sendJsonError(int sc, const QByteArray &msg)
- {
- int timeOut = configuration.getTimeOut();
- sendHeaders(statusCode, timeOut, statusText, headers, cookies, socket);
- QString data = QString(R"__({"code": 500, "data": -1, "message": "%1", "status": false})__")
- .arg((QString::number(sc) + " " + msg));
- sendBytes(socket, data.toUtf8(), timeOut);
- }
- void Response::write(const QJsonObject &json, bool writeContentType)
- {
- if (writeContentType)
- addHeader(CWF::HTTP::CONTENT_TYPE, CWF::HTTP::APPLICATION_JSON);
- content = QJsonDocument(json).toJson();
- flushBuffer();
- }
- void Response::write(const QJsonArray &array, bool writeContentType)
- {
- if (writeContentType)
- addHeader(CWF::HTTP::CONTENT_TYPE, CWF::HTTP::APPLICATION_JSON);
- content = QJsonDocument(array).toJson();
- flushBuffer();
- }
- void Response::write(QByteArray &&data)
- {
- content = std::move(data);
- flushBuffer();
- }
- void Response::write(const QByteArray &data, bool flush)
- {
- content += data;
- if (flush)
- flushBuffer();
- }
- void Response::setStatus(int statusCode, const QByteArray &description)
- {
- this->statusCode = statusCode;
- statusText = description;
- }
- void Response::sendRedirect(const QByteArray &url)
- {
- setStatus(Response::SC_SEE_OTHER, HTTP::SEE_OTHER);
- addHeader(HTTP::LOCATION, url);
- write(HTTP::REDIRECT, true);
- }
- CWF_END_NAMESPACE
|