9#include <Cutelyst/Context>
10#include <Cutelyst/response_p.h>
12#include <QLoggingCategory>
13Q_LOGGING_CATEGORY(CUTELYST_ENGINEREQUEST,
"cutelyst.engine_request", QtWarningMsg)
17EngineRequest::EngineRequest()
21EngineRequest::~EngineRequest()
28 if (!(
status & EngineRequest::Chunked)) {
33 if (!
body->isSequential()) {
37 char block[64 * 1024];
38 while (!
body->atEnd()) {
39 qint64 in =
body->read(block,
sizeof(block));
44 if (
write(block, in) != in) {
45 qCWarning(CUTELYST_ENGINEREQUEST) <<
"Failed to write body";
50 const QByteArray bodyByteArray = response->
body();
51 write(bodyByteArray.constData(), bodyByteArray.size());
53 }
else if (!(
status & EngineRequest::ChunkedDone)) {
76 res->
setStatus(Response::InternalServerError);
89 status |= EngineRequest::Finalized;
97 const auto cookies = res->
cookies();
98 for (
const QNetworkCookie &cookie : cookies) {
110 qint64 size = response->
size();
119 status |= EngineRequest::FinalizedHeaders;
125 if (!(
status & EngineRequest::Chunked)) {
127 }
else if (!(
status & EngineRequest::ChunkedDone)) {
128 const QByteArray chunkSize = QByteArray::number(len, 16).toUpper();
130 chunk.reserve(
int(len + chunkSize.size() + 4));
131 chunk.append(chunkSize).append(
"\r\n", 2).append(data,
int(len)).append(
"\r\n", 2);
133 qint64 retWrite =
doWrite(chunk.data(), chunk.size());
137 status |= EngineRequest::ChunkedDone;
140 return retWrite == chunk.size() ? len : -1;
145bool EngineRequest::webSocketHandshake(
const QByteArray &key,
146 const QByteArray &origin,
147 const QByteArray &protocol)
149 if (
status & EngineRequest::FinalizedHeaders) {
153 if (webSocketHandshakeDo(key, origin,
protocol)) {
154 status |= EngineRequest::FinalizedHeaders | EngineRequest::Async | EngineRequest::IOWrite;
164bool EngineRequest::webSocketSendTextMessage(
const QString &message)
170bool EngineRequest::webSocketSendBinaryMessage(
const QByteArray &message)
176bool EngineRequest::webSocketSendPing(
const QByteArray &payload)
182bool EngineRequest::webSocketClose(quint16 code,
const QString &reason)
193bool EngineRequest::webSocketHandshakeDo(
const QByteArray &key,
194 const QByteArray &origin,
195 const QByteArray &protocol)
210 char *data = rawPath;
211 const char *inputPtr = data;
213 bool lastSlash =
false;
214 bool skipUtf8 =
true;
216 for (
int i = 0; i < len; ++i, ++outlen) {
217 const char c = inputPtr[i];
218 if (c ==
'%' && i + 2 < len) {
219 int a = inputPtr[++i];
220 int b = inputPtr[++i];
222 if (a >=
'0' && a <=
'9')
224 else if (a >=
'a' && a <=
'f')
226 else if (a >=
'A' && a <=
'F')
229 if (b >=
'0' && b <=
'9')
231 else if (b >=
'a' && b <=
'f')
233 else if (b >=
'A' && b <=
'F')
236 *data++ = char((a << 4) | b);
238 }
else if (c ==
'+') {
240 }
else if (c ==
'/') {
256 path = QString::fromLatin1(rawPath, outlen);
258 path = QString::fromUtf8(rawPath, outlen);
261 if (!
path.startsWith(u
'/')) {
266#include "moc_enginerequest.cpp"
QStringList errors() const noexcept
Returns a list of errors that were defined.
void finalize()
finalize the request right away this is automatically called at the end of the actions chain
bool error() const noexcept
Returns true if an error was set.
Response * response() const noexcept
virtual qint64 doWrite(const char *data, qint64 len)=0
Reimplement this to do the RAW writing to the client.
Context * context
The Cutelyst::Context of this request.
virtual void finalizeBody()
Engines must reimplement this to write the response body back to the caller.
virtual void finalizeError()
Engines should overwrite this if they want to to make custom error messages.
QString path
Call setPath() instead.
Status status
Connection status.
void finalize()
Called by Application to deal with finalizing cookies, headers and body.
qint64 write(const char *data, qint64 len)
Called by Response to manually write data.
void setPath(char *rawPath, const int len)
This method sets the path and already does the decoding so that it is done a single time.
QByteArray protocol
The protocol requested by the user agent 'HTTP1/1'.
Headers headers
The request headers.
virtual bool writeHeaders(quint16 status, const Headers &headers)=0
Reimplement this to write the headers back to the client.
virtual bool finalizeHeaders()
Finalize the headers, and call doWriteHeader(), reimplemententions must call this first.
virtual void finalizeCookies()
Reimplement if you need a custom way to Set-Cookie, the default implementation writes them to c->res(...
QIODevice * body
The QIODevice containing the body (if any) of the request.
virtual void processingFinished()
This is called when the Application chain is finished processing this request, here the request can s...
qint64 size() const noexcept override
void setContentType(const QByteArray &type)
void setStatus(quint16 status) noexcept
void setBody(QIODevice *body)
Headers & headers() noexcept
QList< QNetworkCookie > cookies() const
QIODevice * bodyDevice() const noexcept
quint16 status() const noexcept
The Cutelyst namespace holds all public Cutelyst API.