1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4//#define QNETWORKACCESSCACHEBACKEND_DEBUG
5
6#include "qnetworkaccesscachebackend_p.h"
7#include "qabstractnetworkcache.h"
8#include "qfileinfo.h"
9#include "qdir.h"
10#include "qcoreapplication.h"
11#include "qhash.h"
12
13QT_BEGIN_NAMESPACE
14
15using namespace Qt::StringLiterals;
16
17QNetworkAccessCacheBackend::QNetworkAccessCacheBackend()
18 : QNetworkAccessBackend(QNetworkAccessBackend::TargetType::Local)
19{
20}
21
22QNetworkAccessCacheBackend::~QNetworkAccessCacheBackend()
23{
24}
25
26void QNetworkAccessCacheBackend::open()
27{
28 if (operation() != QNetworkAccessManager::GetOperation || !sendCacheContents()) {
29 QString msg = QCoreApplication::translate(context: "QNetworkAccessCacheBackend", key: "Error opening %1")
30 .arg(a: this->url().toString());
31 error(code: QNetworkReply::ContentNotFoundError, errorString: msg);
32 } else {
33 setAttribute(attribute: QNetworkRequest::SourceIsFromCacheAttribute, value: true);
34 }
35 finished();
36}
37
38bool QNetworkAccessCacheBackend::sendCacheContents()
39{
40 setCachingEnabled(false);
41 QAbstractNetworkCache *nc = networkCache();
42 if (!nc)
43 return false;
44
45 QNetworkCacheMetaData item = nc->metaData(url: url());
46 if (!item.isValid())
47 return false;
48
49 QNetworkCacheMetaData::AttributesMap attributes = item.attributes();
50 setAttribute(attribute: QNetworkRequest::HttpStatusCodeAttribute,
51 value: attributes.value(key: QNetworkRequest::HttpStatusCodeAttribute));
52 setAttribute(attribute: QNetworkRequest::HttpReasonPhraseAttribute,
53 value: attributes.value(key: QNetworkRequest::HttpReasonPhraseAttribute));
54
55 // set the headers
56 auto headers = item.headers();
57 const auto cacheControlValue = QLatin1StringView(
58 headers.value(name: QHttpHeaders::WellKnownHeader::CacheControl));
59 // RFC 9111 Section 5.2 Cache Control
60 if (cacheControlValue.contains(s: "must-revalidate"_L1, cs: Qt::CaseInsensitive)
61 || cacheControlValue.contains(s: "no-cache"_L1, cs: Qt::CaseInsensitive)) {
62 return false;
63 }
64 setHeaders(std::move(headers));
65
66 // handle a possible redirect
67 QVariant redirectionTarget = attributes.value(key: QNetworkRequest::RedirectionTargetAttribute);
68 if (redirectionTarget.isValid()) {
69 setAttribute(attribute: QNetworkRequest::RedirectionTargetAttribute, value: redirectionTarget);
70 redirectionRequested(destination: redirectionTarget.toUrl());
71 }
72
73 // signal we're open
74 metaDataChanged();
75
76 if (operation() == QNetworkAccessManager::GetOperation) {
77 device = nc->data(url: url());
78 if (!device)
79 return false;
80 device->setParent(this);
81 readyRead();
82 }
83
84#if defined(QNETWORKACCESSCACHEBACKEND_DEBUG)
85 qDebug() << "Successfully sent cache:" << url();
86#endif
87 return true;
88}
89
90bool QNetworkAccessCacheBackend::start()
91{
92 open();
93 return true;
94}
95
96void QNetworkAccessCacheBackend::close() { }
97
98qint64 QNetworkAccessCacheBackend::bytesAvailable() const
99{
100 return device ? device->bytesAvailable() : qint64(0);
101}
102
103qint64 QNetworkAccessCacheBackend::read(char *data, qint64 maxlen)
104{
105 return device ? device->read(data, maxlen) : qint64(0);
106}
107
108QT_END_NAMESPACE
109
110

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtbase/src/network/access/qnetworkaccesscachebackend.cpp