summaryrefslogtreecommitdiffstats
path: root/src/core/api/qwebenginehttprequest.cpp
blob: d199bff1d27950f95985fc7e8b6d582922e4ccd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qplatformdefs.h"
#include <QtCore/qshareddata.h>
#include <QtWebEngineCore/qwebenginehttprequest.h>
#include <algorithm>

QT_BEGIN_NAMESPACE

/*!
    \class QWebEngineHttpRequest
    \since 5.9
    \ingroup webengine
    \inmodule QtWebEngineCore

    \brief The QWebEngineHttpRequest class holds a request to be sent with WebEngine.

    QWebEngineHttpRequest represents an HTTP request in the WebEngine networking stack.
    It holds the information necessary to send a request over the network. It contains
    a URL and some ancillary information that can be used to modify the request.
    Both QWebEnginePage::load() and QWebEngineView::load() accept a QWebEngineHttpRequest
    as a parameter.
*/

/*!
    \enum QWebEngineHttpRequest::Method
    \brief This enum type describes the method used to send the HTTP request:

    \value Get The GET method.
    \value Post The POST method.
*/

class QWebEngineHttpRequestPrivate : public QSharedData {
public:
    QUrl url;
    QWebEngineHttpRequest::Method method;
    typedef QPair<QByteArray, QByteArray> HeaderPair;
    typedef QList<HeaderPair> Headers;
    Headers headers;
    QByteArray postData;

    QWebEngineHttpRequestPrivate() {}

    ~QWebEngineHttpRequestPrivate() {}

    QWebEngineHttpRequestPrivate(const QWebEngineHttpRequestPrivate &other) : QSharedData(other)
    {
        method = other.method;
        url = other.url;
        headers = other.headers;
    }

    bool operator==(const QWebEngineHttpRequestPrivate &other) const
    {
        return method == other.method
            && url == other.url
            && headers == other.headers;
    }

    Headers::ConstIterator findHeader(const QByteArray &key) const;
    Headers allHeaders() const;
    QList<QByteArray> headersKeys() const;
    void setHeader(const QByteArray &key, const QByteArray &value);
    void unsetHeader(const QByteArray &key);
    void setAllHeaders(const Headers &list);

private:
    void setHeaderInternal(const QByteArray &key, const QByteArray &value);
};

/*!
    Constructs a QWebEngineHttpRequest object with \a url as the URL to be
    requested and \a method as the method to be used.

    \sa url(), setUrl()
*/
QWebEngineHttpRequest::QWebEngineHttpRequest(const QUrl &url,
                                             const QWebEngineHttpRequest::Method &method)
    : d(new QWebEngineHttpRequestPrivate)
{
    d->method = method;
    d->url = url;
}

/*!
    Creates a copy of \a other.
*/
QWebEngineHttpRequest::QWebEngineHttpRequest(const QWebEngineHttpRequest &other) : d(other.d) {}

/*!
    Disposes of the QWebEngineHttpRequest object.
*/
QWebEngineHttpRequest::~QWebEngineHttpRequest()
{
    // QSharedDataPointer auto deletes
    d = 0;
}

/*!
    Returns \c true if this object is the same as \a other (that is, if they
    have the same method, URL, and headers).

    \sa operator!=()
*/
bool QWebEngineHttpRequest::operator==(const QWebEngineHttpRequest &other) const
{
    return d == other.d || *d == *other.d;
}

/*!
    \fn bool QWebEngineHttpRequest::operator!=(const QWebEngineHttpRequest &other) const

    Returns \c false if this object is not the same as \a other.

    \sa operator==()
*/

/*!
    Creates a copy of \a other.
*/
QWebEngineHttpRequest &QWebEngineHttpRequest::operator=(const QWebEngineHttpRequest &other)
{
    d = other.d;
    return *this;
}

/*!
    \fn void QWebEngineHttpRequest::swap(QWebEngineHttpRequest &other)

    Swaps this WebEngine request with \a other. This function is very
    fast and never fails.
*/

/*!
    Constructs a QWebEngineHttpRequest to \a url that uses the POST method.

    \note \a postData may contain arbitrary strings. They are translated
          to appropriate raw data.

    \sa postData, setPostData()
*/
QWebEngineHttpRequest QWebEngineHttpRequest::postRequest(const QUrl &url,
                                                         const QMap<QString, QString> &postData)
{
    QWebEngineHttpRequest result(url);
    result.setMethod(QWebEngineHttpRequest::Post);

    QByteArray buffer;
    for (QMap<QString, QString>::const_iterator it = postData.begin(); it != postData.end(); it++) {
        QByteArray key = QUrl::toPercentEncoding(it.key());
        QByteArray value = QUrl::toPercentEncoding(it.value());

        if (buffer.length() > 0)
            buffer += '&';
        buffer.append(key).append('=').append(value);
    }
    result.setPostData(buffer);

    result.setHeader(QByteArrayLiteral("Content-Type"),
                     QByteArrayLiteral("application/x-www-form-urlencoded"));
    return result;
}

/*!
    Returns the method this WebEngine request is using.

    \sa setMethod()
*/
QWebEngineHttpRequest::Method QWebEngineHttpRequest::method() const
{
    return d->method;
}

/*!
    Sets the method this WebEngine request is using to be \a method.

    \sa method()
*/
void QWebEngineHttpRequest::setMethod(QWebEngineHttpRequest::Method method)
{
    d->method = method;
}

/*!
    Returns the URL this WebEngine request is referring to.

    \sa setUrl()
*/
QUrl QWebEngineHttpRequest::url() const
{
    return d->url;
}

/*!
    Sets the URL this WebEngine request is referring to be \a url.

    \sa url()
*/
void QWebEngineHttpRequest::setUrl(const QUrl &url)
{
    d->url = url;
}

/*!
    Returns the (raw) POST data this WebEngine request contains.

    \sa setPostData()
*/
QByteArray QWebEngineHttpRequest::postData() const
{
    return d->postData;
}

/*!
    Sets the (raw) POST data this WebEngine request contains to be \a postData.

    \sa postData()
*/
void QWebEngineHttpRequest::setPostData(const QByteArray &postData)
{
    d->postData = postData;
}

/*!
    Returns \c true if the header \a headerName is present in this
    WebEngine request.

    \sa setHeader(), header(), unsetHeader(), headers()
*/
bool QWebEngineHttpRequest::hasHeader(const QByteArray &headerName) const
{
    return d->findHeader(headerName) != d->headers.constEnd();
}

/*!
    Returns the header specified by \a headerName. If no such header is
    present, an empty QByteArray is returned, which may be
    indistinguishable from a header that is present but has no content
    (use hasHeader() to find out if the header exists or not).

    Headers can be set with setHeader().

    \sa setHeader(), hasHeader(), unsetHeader(), headers()
*/
QByteArray QWebEngineHttpRequest::header(const QByteArray &headerName) const
{
    QWebEngineHttpRequestPrivate::Headers::ConstIterator it = d->findHeader(headerName);
    if (it != d->headers.constEnd())
        return it->second;
    return QByteArray();
}

/*!
    Returns a list of all headers that are set in this WebEngine
    request. The list is in the order that the headers were set.

    \sa setHeader(), header(), hasHeader(), unsetHeader()
*/
QList<QByteArray> QWebEngineHttpRequest::headers() const
{
    return d->headersKeys();
}

/*!
    Sets the header \a headerName to be of value \a headerValue.

    \note Setting the same header twice overrides the previous
    setting. To accomplish the behavior of multiple HTTP headers of
    the same name, you should concatenate the two values, separating
    them with a comma (",") and set one single header.

    \sa header(), hasHeader(), unsetHeader(), headers()
*/
void QWebEngineHttpRequest::setHeader(const QByteArray &headerName, const QByteArray &headerValue)
{
    d->setHeader(headerName, headerValue);
}

/*!
    Removes the header specified by \a key, if present.

    \sa setHeader(), header(), hasHeader(), headers()
*/
void QWebEngineHttpRequest::unsetHeader(const QByteArray &key)
{
    d->setHeader(key, QByteArray());
}

QWebEngineHttpRequestPrivate::Headers::ConstIterator QWebEngineHttpRequestPrivate::findHeader(const QByteArray &key) const
{
    Headers::ConstIterator it = headers.constBegin();
    Headers::ConstIterator end = headers.constEnd();
    for (; it != end; ++it)
        if (qstricmp(it->first.constData(), key.constData()) == 0)
            return it;

    return end; // not found
}

QWebEngineHttpRequestPrivate::Headers QWebEngineHttpRequestPrivate::allHeaders() const
{
    return headers;
}

QList<QByteArray> QWebEngineHttpRequestPrivate::headersKeys() const
{
    QList<QByteArray> result;
    result.reserve(headers.size());
    Headers::ConstIterator it = headers.constBegin(), end = headers.constEnd();
    for (; it != end; ++it)
        result << it->first;

    return result;
}

/*!
    \internal
    Sets the header specified by \a key to \a value.
*/
void QWebEngineHttpRequestPrivate::setHeader(const QByteArray &key, const QByteArray &value)
{
    if (key.isEmpty())
        // refuse to accept an empty header
        return;

    setHeaderInternal(key, value);
}

/*!
    \internal
    Removes the header specified by \a key, if present.
*/
void QWebEngineHttpRequestPrivate::unsetHeader(const QByteArray &key)
{
    auto firstEqualsKey = [&key](const HeaderPair &header) {
        return qstricmp(header.first.constData(), key.constData()) == 0;
    };
    headers.erase(std::remove_if(headers.begin(), headers.end(), firstEqualsKey), headers.end());
}

/*!
    \internal
    Sets the internal headers list to match \a list.
*/
void QWebEngineHttpRequestPrivate::setAllHeaders(const Headers &list)
{
    headers = list;
}

/*!
    \internal
    Sets the header specified by \a key to \a value.
    \note key must not be empty. When unsure, use \a setHeader() instead.
*/
void QWebEngineHttpRequestPrivate::setHeaderInternal(const QByteArray &key, const QByteArray &value)
{
    unsetHeader(key);

    if (value.isNull())
        return; // only wanted to erase key

    HeaderPair pair;
    pair.first = key;
    pair.second = value;
    headers.append(pair);
}

QT_END_NAMESPACE