/** * @brief Set the AWS custom date header. * * If \a request does not already contain an `x-amz-date` header, then this function * will set a custom `x-amz-date` header to the value of \p dateTime formatted like * "Fri, 09 Sep 2011 23:36:00 GMT". * * @param request The network request to add the date header to. * @param dateTime The timestamp (in UTC) to set the date header's value to. */ void AwsSignatureV3Private::setDateHeader(QNetworkRequest &request, const QDateTime &dateTime) const { Q_ASSERT(dateTime.timeSpec() == Qt::UTC); if (!request.hasRawHeader("x-amz-date")) { request.setRawHeader("x-amz-date", dateTime.toString(QLatin1String("ddd, dd MMM yyyy hh:mm:ss 'GMT'")).toUtf8()); } }
/** * @brief Set authorization header on a network request. * * This function will calculate the authorization header value and set it as the `Authorization` * HTTP header on \p request. * * @param[in] credentials The AWS credentials to use to sign the request. * @param[in] operation The HTTP method being used for the request. * @param[in,out] request The network request to add the authorization header to. * @param[in] payload Optional data being submitted in the request (eg for `PUT` and `POST` operations). * * @see http://docs.aws.amazon.com/general/latest/gr/sigV3-signed-request-examples.html * @see authorizationHeaderValue */ void AwsSignatureV3Private::setAuthorizationHeader(const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &payload) const { Q_ASSERT(!request.hasRawHeader("Authorization")); request.setRawHeader("Authorization", authorizationHeaderValue(credentials, operation, request, payload)); }
void DeleteJob::dispatchRequest(QNetworkAccessManager* accessManager, const QNetworkRequest& request, const QByteArray& data, const QString& contentType) { Q_UNUSED(data) Q_UNUSED(contentType) QNetworkRequest r = request; if (!r.hasRawHeader("If-Match")) { r.setRawHeader("If-Match", "*"); } accessManager->deleteResource(r); }
/** * @brief Create an AWS V3 Signature canonical request. * * Note, this function implments both `AWS3` and `AWS3-HTTPS` variants of the * AWS Signature version 3 - which are quite different. * * @param[in] operation The HTTP method being used for the request. * @param[in] request The network request to generate a canonical request for. * @param[in] payload Optional data being submitted in the request (eg for `PUT` and `POST` operations). * @param[out] signedHeaders A semi-colon separated list of the names of all headers * included in the result. * * @return An AWS V3 Signature canonical request. * * @see http://docs.aws.amazon.com/amazonswf/latest/developerguide/HMACAuth-swf.html (AWS3) * @see http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/RESTAuthentication.html (AWS3-HTTPS) */ QByteArray AwsSignatureV3Private::canonicalRequest(const QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &payload, QByteArray * const signedHeaders) const { // AWS3-HTTPS if (isHttps(request)) { Q_ASSERT((request.hasRawHeader("x-amz-date")) || (request.hasRawHeader("Date"))); QByteArray canonicalRequest = request.rawHeader(request.hasRawHeader("x-amz-date") ? "x-amz-date" : "Date"); if (request.hasRawHeader("x-amz-nonce")) { canonicalRequest += request.rawHeader("x-amz-nonce"); } return canonicalRequest; } // AWS3 return httpMethod(operation).toUtf8() + '\n' + canonicalPath(request.url()).toUtf8() + '\n' + canonicalQuery(QUrlQuery(request.url())) + '\n' + canonicalHeaders(request, signedHeaders) + '\n' + payload; }
QNetworkRequest ResourceRequest::toNetworkRequest(QObject* originatingFrame) const { QNetworkRequest request; request.setUrl(url()); request.setOriginatingObject(originatingFrame); const HTTPHeaderMap &headers = httpHeaderFields(); for (HTTPHeaderMap::const_iterator it = headers.begin(), end = headers.end(); it != end; ++it) { QByteArray name = QString(it->first).toAscii(); QByteArray value = QString(it->second).toAscii(); // QNetworkRequest::setRawHeader() would remove the header if the value is null // Make sure to set an empty header instead of null header. if (!value.isNull()) request.setRawHeader(name, value); else request.setRawHeader(name, ""); } // Make sure we always have an Accept header; some sites require this to // serve subresources if (!request.hasRawHeader("Accept")) request.setRawHeader("Accept", "*/*"); switch (cachePolicy()) { case ReloadIgnoringCacheData: request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); break; case ReturnCacheDataElseLoad: request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); break; case ReturnCacheDataDontLoad: request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache); break; case UseProtocolCachePolicy: // QNetworkRequest::PreferNetwork default: break; } if (!allowCookies() || !thirdPartyCookiePolicyPermitsForFrame(originatingFrame, url(), firstPartyForCookies())) { request.setAttribute(QNetworkRequest::CookieSaveControlAttribute, QNetworkRequest::Manual); request.setAttribute(QNetworkRequest::CookieLoadControlAttribute, QNetworkRequest::Manual); } if (!allowCookies()) request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual); return request; }
void AwsSignatureV3::sign(const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &data) const { Q_D(const AwsSignatureV3); // Note, the use of a nonce value with AWS3-HTTPS is undocumented, but done by the // official Java SDK, and worth copying for additional security. if ((d->isHttps(request)) && (!request.hasRawHeader("x-amz-nonce"))) { request.setRawHeader("x-amz-nonce", QUuid::createUuid().toByteArray().mid(1,36)); } d->setDateHeader(request); d->setAuthorizationHeader(credentials, operation, request, data); }
QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart) { // copy the request, we probably need to add some headers QNetworkRequest newRequest(request); // add Content-Type header if not there already if (!request.header(QNetworkRequest::ContentTypeHeader).isValid()) { QByteArray contentType; contentType.reserve(34 + multiPart->d_func()->boundary.count()); contentType += "multipart/"; switch (multiPart->d_func()->contentType) { case QHttpMultiPart::RelatedType: contentType += "related"; break; case QHttpMultiPart::FormDataType: contentType += "form-data"; break; case QHttpMultiPart::AlternativeType: contentType += "alternative"; break; default: contentType += "mixed"; break; } // putting the boundary into quotes, recommended in RFC 2046 section 5.1.1 contentType += "; boundary=\"" + multiPart->d_func()->boundary + "\""; newRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType)); } // add MIME-Version header if not there already (we must include the header // if the message conforms to RFC 2045, see section 4 of that RFC) QByteArray mimeHeader("MIME-Version"); if (!request.hasRawHeader(mimeHeader)) newRequest.setRawHeader(mimeHeader, QByteArray("1.0")); QIODevice *device = multiPart->d_func()->device; if (!device->isReadable()) { if (!device->isOpen()) { if (!device->open(QIODevice::ReadOnly)) qWarning("could not open device for reading"); } else { qWarning("device is not readable"); } } return newRequest; }
void AccessManager::AccessManagerPrivate::setMetaDataForRequest(QNetworkRequest request, KIO::MetaData& metaData) { // Add any meta data specified within request... QVariant userMetaData = request.attribute (static_cast<QNetworkRequest::Attribute>(MetaData)); if (userMetaData.isValid() && userMetaData.type() == QVariant::Map) metaData += userMetaData.toMap(); metaData.insert(QL1S("PropagateHttpHeader"), QL1S("true")); if (request.hasRawHeader("User-Agent")) { metaData.insert(QL1S("UserAgent"), request.rawHeader("User-Agent")); request.setRawHeader("User-Agent", QByteArray()); } if (request.hasRawHeader("Accept")) { metaData.insert(QL1S("accept"), request.rawHeader("Accept")); request.setRawHeader("Accept", QByteArray()); } if (request.hasRawHeader("Accept-Charset")) { metaData.insert(QL1S("Charsets"), request.rawHeader("Accept-Charset")); request.setRawHeader("Accept-Charset", QByteArray()); } if (request.hasRawHeader("Accept-Language")) { metaData.insert(QL1S("Languages"), request.rawHeader("Accept-Language")); request.setRawHeader("Accept-Language", QByteArray()); } if (request.hasRawHeader("Referer")) { metaData.insert(QL1S("referrer"), request.rawHeader("Referer")); request.setRawHeader("Referer", QByteArray()); } if (request.hasRawHeader("Content-Type")) { metaData.insert(QL1S("content-type"), request.rawHeader("Content-Type")); request.setRawHeader("Content-Type", QByteArray()); } if (request.attribute(QNetworkRequest::AuthenticationReuseAttribute) == QNetworkRequest::Manual) { metaData.insert(QL1S("no-preemptive-auth-reuse"), QL1S("true")); } request.setRawHeader("Content-Length", QByteArray()); request.setRawHeader("Connection", QByteArray()); request.setRawHeader("If-None-Match", QByteArray()); request.setRawHeader("If-Modified-Since", QByteArray()); request.setRawHeader("x-kdewebkit-ignore-disposition", QByteArray()); QStringList customHeaders; Q_FOREACH(const QByteArray &key, request.rawHeaderList()) { const QByteArray value = request.rawHeader(key); if (value.length()) customHeaders << (key + QL1S(": ") + value); } if (!customHeaders.isEmpty()) { metaData.insert(QL1S("customHTTPHeader"), customHeaders.join("\r\n")); } // Append per request meta data, if any... if (!requestMetaData.isEmpty()) { metaData += requestMetaData; // Clear per request meta data... requestMetaData.clear(); } // Append per session meta data, if any... if (!sessionMetaData.isEmpty()) { metaData += sessionMetaData; } }
/** * @brief Set the AWS custom date header. * * This function will set a custom `x-amz-date` header to the value of \p dateTime * formatted to AwsSignatureV4Private::DateTimeFormat. * * @note Although Amazon labels this as a "date", it is in fact a full timestamp. * * @param request The network request to add the date header to. * @param dateTime The timestamp to set the date header's value to. * * @return \p dateTime verbatim (just a convenience for some callers). */ QDateTime AwsSignatureV4Private::setDateHeader(QNetworkRequest &request, const QDateTime &dateTime) const { Q_ASSERT(!request.hasRawHeader("x-amz-date")); request.setRawHeader("x-amz-date", dateTime.toString(DateTimeFormat).toUtf8()); return dateTime; }