11#include <QCryptographicHash>
15#include <QtCore/QJsonDocument>
21 : d_ptr(new ResponsePrivate(defaultHeaders, engineRequest))
42 if (!(d->engineRequest->status & EngineRequest::FinalizedHeaders)) {
43 if (d->headers.header(
"Transfer-Encoding"_ba).compare(
"chunked") == 0) {
44 d->engineRequest->status |= EngineRequest::IOWrite | EngineRequest::Chunked;
48 d->headers.setHeader(
"Connection"_ba,
"Close"_ba);
49 d->engineRequest->status |= EngineRequest::IOWrite;
51 delete d->bodyIODevice;
52 d->bodyIODevice =
nullptr;
55 d->engineRequest->finalizeHeaders();
58 return d->engineRequest->write(data, len);
63 delete d_ptr->bodyIODevice;
82 return !d->bodyData.isEmpty() || d->bodyIODevice ||
83 d->engineRequest->status & EngineRequest::IOWrite;
89 if (d->bodyIODevice) {
90 delete d->bodyIODevice;
91 d->bodyIODevice =
nullptr;
101 return d->bodyIODevice;
109 if (!(d->engineRequest->status & EngineRequest::IOWrite)) {
111 if (d->bodyIODevice) {
112 delete d->bodyIODevice;
114 d->bodyIODevice =
body;
123 d->setBodyData(
body);
129 d->setBodyData(cbor);
130 d->headers.setContentType(
"application/cbor"_ba);
141 d->setBodyData(json);
142 d->headers.setContentType(
"application/json"_ba);
158 return d->headers.contentEncoding();
164 Q_ASSERT_X(!(d->engineRequest->status & EngineRequest::FinalizedHeaders),
165 "setContentEncoding",
166 "setting a header value after finalize_headers and the response callback has been "
167 "called. Not what you want.");
169 d->headers.setContentEncoding(encoding);
175 return d->headers.contentLength();
181 Q_ASSERT_X(!(d->engineRequest->status & EngineRequest::FinalizedHeaders),
183 "setting a header value after finalize_headers and the response callback has been "
184 "called. Not what you want.");
186 d->headers.setContentLength(length);
192 return d->headers.contentType();
198 return d->headers.contentTypeCharset();
210 return d->cookies.values();
230 return d->cookies.remove(name);
241 qCDebug(CUTELYST_RESPONSE) <<
"Redirecting to" <<
location <<
status;
243 d->headers.setHeader(
"Location"_ba,
location);
244 d->headers.setContentType(
"text/html; charset=utf-8"_ba);
246 const QByteArray buf = R
"V0G0N(<!DOCTYPE html>
247<html xmlns="http://www.w3.org/1999/xhtml">
252 <p>This item has moved <a href=")V0G0N" +
259 d->headers.removeHeader(
"Location"_ba);
260 qCDebug(CUTELYST_RESPONSE) <<
"Invalid redirect removing header" << url <<
status;
272 if (url.
matches(d->engineRequest->context->req()->uri(),
289 return d->headers.header(field);
295 Q_ASSERT_X(!(d->engineRequest->status & EngineRequest::FinalizedHeaders),
297 "setting a header value after finalize_headers and the response callback has been "
298 "called. Not what you want.");
300 d->headers.setHeader(key, value);
312 return d->engineRequest->status & EngineRequest::FinalizedHeaders;
323 if (d->engineRequest->status & EngineRequest::IOWrite) {
325 }
else if (d->bodyIODevice) {
326 return d->bodyIODevice->size();
328 return d->bodyData.size();
337 return d->engineRequest->webSocketHandshake(key, origin, protocol);
343 return d->engineRequest->webSocketSendTextMessage(message);
349 return d->engineRequest->webSocketSendBinaryMessage(message);
355 return d->engineRequest->webSocketSendPing(payload);
361 return d->engineRequest->webSocketClose(code, reason);
364void ResponsePrivate::setBodyData(
const QByteArray &body)
366 if (!(engineRequest->status & EngineRequest::IOWrite)) {
369 bodyIODevice =
nullptr;
377#include "moc_response.cpp"
void redirect(const QUrl &url, quint16 status=Found)
Headers & headers() noexcept
QVariant cookie(const QByteArray &name) const
QUrl location() const noexcept
qint64 contentLength() const
bool hasBody() const noexcept
void setStatus(quint16 status) noexcept
Response(const Headers &defaultHeaders, EngineRequest *conn=nullptr)
QByteArray contentEncoding() const noexcept
QByteArray contentTypeCharset() const
void redirectSafe(const QUrl &url, const QUrl &fallback)
void setBody(QIODevice *body)
bool webSocketHandshake(const QByteArray &key={}, const QByteArray &origin={}, const QByteArray &protocol={})
void setJsonArrayBody(const QJsonArray &array)
void setHeader(const QByteArray &key, const QByteArray &value)
void setCookies(const QList< QNetworkCookie > &cookies)
virtual qint64 writeData(const char *data, qint64 len) override
bool isSequential() const noexcept override
bool webSocketClose(quint16 code=Response::CloseCodeNormal, const QString &reason={})
QList< QNetworkCookie > cookies() const
bool webSocketPing(const QByteArray &payload={})
void setCborValueBody(const QCborValue &value)
void setContentLength(qint64 length)
int removeCookies(const QByteArray &name)
QByteArray header(const QByteArray &field) const noexcept
void setJsonObjectBody(const QJsonObject &obj)
bool webSocketBinaryMessage(const QByteArray &message)
virtual qint64 readData(char *data, qint64 maxlen) override
QIODevice * bodyDevice() const noexcept
void setCborBody(const QByteArray &cbor)
qint64 size() const noexcept override
bool webSocketTextMessage(const QString &message)
void setJsonBody(QStringView json)
quint16 status() const noexcept
void setCookie(const QNetworkCookie &cookie)
void setContentEncoding(const QByteArray &encoding)
QByteArray contentType() const
virtual ~Response() override
bool isFinalizedHeaders() const noexcept
The Cutelyst namespace holds all public Cutelyst API.
virtual bool open(QIODeviceBase::OpenMode mode)
bool isValid() const const
bool matches(const QUrl &url, QUrl::FormattingOptions options) const const
QByteArray toEncoded(QUrl::FormattingOptions options) const const
QVariant fromValue(T &&value)