cutelyst  5.0.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
testengine.cpp
1 #include "testengine.hpp"
2 
3 #include "testengine_p.h"
4 
5 #include <QBuffer>
6 
7 using namespace Cutelyst;
8 using namespace Qt::Literals::StringLiterals;
9 
10 TestEngine::TestEngine(Application *app, const QVariantMap &opts)
11  : Engine{app, 0, opts}
12 {
13 }
14 
15 int TestEngine::workerId() const
16 {
17  return 0;
18 }
19 
20 TestEngine::TestResponse TestEngine::createRequest(const QByteArray &method,
21  const QByteArray &path,
22  const QByteArray &query,
23  const Headers &headers,
24  QByteArray *body)
25 {
26  QIODevice *bodyDevice = nullptr;
27  if (headers.header("Sequential").isEmpty()) {
28  bodyDevice = new QBuffer(body);
29  } else {
30  bodyDevice = new SequentialBuffer(body);
31  }
32  bodyDevice->open(QIODevice::ReadOnly);
33 
34  Headers headersCL = headers;
35  if (bodyDevice->size()) {
36  headersCL.setContentLength(bodyDevice->size());
37  }
38 
39  TestEngineConnection req;
40  req.method = method;
41  QByteArray _path = path;
42  req.setPath(_path);
43  req.query = query;
44  req.protocol = "HTTP/1.1"_ba;
45  req.isSecure = false;
46  req.serverAddress = "127.0.0.1"_ba;
47  req.remoteAddress = QHostAddress(u"127.0.0.1"_s);
48  req.remotePort = 3000;
49  req.remoteUser = QString{};
50  req.headers = headersCL;
51  req.startOfRequest = std::chrono::steady_clock::now();
52  req.body = bodyDevice;
53 
54  Q_EMIT processRequestAsync(&req);
55 
56  // Due async requests we create a local event loop
57  req.m_eventLoop.exec();
58 
59  TestResponse ret;
60  ret.body = req.m_responseData;
61  ret.statusCode = req.m_statusCode;
62  ret.headers = req.m_headers;
63 
64  return ret;
65 }
66 
67 TestEngine::TestResponse TestEngine::createRequest(const QByteArray &method,
68  const QString &path,
69  const QByteArray &query,
70  const Headers &headers,
71  QByteArray *body)
72 {
73  return createRequest(method, path.toLatin1(), query, headers, body);
74 }
75 
76 bool TestEngine::init()
77 {
78  return initApplication() && postForkApplication();
79 }
80 
81 SequentialBuffer::SequentialBuffer(QByteArray *buffer)
82  : buf(buffer)
83 {
84 }
85 
86 bool SequentialBuffer::isSequential() const
87 {
88  return true;
89 }
90 
91 qint64 SequentialBuffer::bytesAvailable() const
92 {
93  return buf->size() + QIODevice::bytesAvailable();
94 }
95 
96 qint64 SequentialBuffer::readData(char *data, qint64 maxlen)
97 {
98  QByteArray mid = buf->mid(pos(), maxlen);
99  memcpy(data, mid.data(), mid.size());
100  // Sequential devices consume the body
101  buf->remove(0, mid.size());
102  return mid.size();
103 }
104 
105 qint64 SequentialBuffer::writeData(const char *data, qint64 len)
106 {
107  Q_UNUSED(data);
108  Q_UNUSED(len);
109  return -1;
110 }
111 
112 TestEngineConnection::TestEngineConnection() = default;
113 
114 qint64 TestEngineConnection::doWrite(const char *data, qint64 len)
115 {
116  m_responseData.append(data, len);
117  return len;
118 }
119 
120 bool TestEngineConnection::writeHeaders(quint16 status, const Headers &headers)
121 {
122  m_statusCode = status;
123  m_headers = headers;
124 
125  return true;
126 }
127 
128 void TestEngineConnection::processingFinished()
129 {
130  m_eventLoop.quit();
131 }
132 
133 #include "moc_testengine.cpp"
bool isEmpty() const const
Container for HTTP headers.
Definition: headers.h:23
virtual bool open(QIODeviceBase::OpenMode mode)
virtual qint64 size() const const
The Cutelyst namespace holds all public Cutelyst API.
QByteArray mid(qsizetype pos, qsizetype len) const const
virtual qint64 bytesAvailable() const const
QByteArray toLatin1() const const
char * data()
The Cutelyst application.
Definition: application.h:72
QByteArray header(QAnyStringView key) const noexcept
Definition: headers.cpp:419
void setContentLength(qint64 value)
Definition: headers.cpp:199
qsizetype size() const const
The Cutelyst Engine.
Definition: engine.h:19
QByteArray & remove(qsizetype pos, qsizetype len)