зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1697421 - store original response headers for 304 and 206 response. r=necko-reviewers,valentin
Differential Revision: https://phabricator.services.mozilla.com/D156795
This commit is contained in:
Родитель
08d3766f45
Коммит
1a9dbcd953
|
@ -231,6 +231,10 @@ void nsHttpHeaderArray::ClearHeader(const nsHttpAtom& header) {
|
|||
}
|
||||
}
|
||||
|
||||
void nsHttpHeaderArray::PurgeHeaderEntries(const nsHttpAtom& header) {
|
||||
mHeaders.RemoveElementsBy(
|
||||
[header](const auto& entry) { return (entry.header == header); });
|
||||
}
|
||||
const char* nsHttpHeaderArray::PeekHeader(const nsHttpAtom& header) const {
|
||||
const nsEntry* entry = nullptr;
|
||||
LookupEntry(header, &entry);
|
||||
|
@ -444,12 +448,16 @@ void nsHttpHeaderArray::FlattenOriginalHeader(nsACString& buf) {
|
|||
}
|
||||
}
|
||||
|
||||
const char* nsHttpHeaderArray::PeekHeaderAt(
|
||||
uint32_t index, nsHttpAtom& header, nsACString& headerNameOriginal) const {
|
||||
const char* nsHttpHeaderArray::PeekHeaderAt(uint32_t index, nsHttpAtom& header,
|
||||
nsACString& headerNameOriginal,
|
||||
HeaderVariety& variety,
|
||||
nsACString& val) const {
|
||||
const nsEntry& entry = mHeaders[index];
|
||||
|
||||
header = entry.header;
|
||||
headerNameOriginal = entry.headerNameOriginal;
|
||||
variety = entry.variety;
|
||||
val = entry.value;
|
||||
return entry.value.get();
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,8 @@ class nsHttpHeaderArray {
|
|||
nsIHttpHeaderVisitor* aVisitor);
|
||||
void ClearHeader(const nsHttpAtom& h);
|
||||
|
||||
void PurgeHeaderEntries(const nsHttpAtom& header);
|
||||
|
||||
// Find the location of the given header value, or null if none exists.
|
||||
const char* FindHeaderValue(const nsHttpAtom& header,
|
||||
const char* value) const {
|
||||
|
@ -117,7 +119,8 @@ class nsHttpHeaderArray {
|
|||
uint32_t Count() const { return mHeaders.Length(); }
|
||||
|
||||
const char* PeekHeaderAt(uint32_t i, nsHttpAtom& header,
|
||||
nsACString& headerNameOriginal) const;
|
||||
nsACString& headerNameOriginal,
|
||||
HeaderVariety& variety, nsACString& val) const;
|
||||
|
||||
void Clear();
|
||||
|
||||
|
|
|
@ -163,12 +163,10 @@ nsresult nsHttpResponseHead::SetHeader(const nsHttpAtom& hdr,
|
|||
return SetHeader_locked(hdr, ""_ns, val, merge);
|
||||
}
|
||||
|
||||
nsresult nsHttpResponseHead::SetHeader_locked(const nsHttpAtom& atom,
|
||||
const nsACString& hdr,
|
||||
const nsACString& val,
|
||||
bool merge) {
|
||||
nsresult rv = mHeaders.SetHeader(atom, hdr, val, merge,
|
||||
nsHttpHeaderArray::eVarietyResponse);
|
||||
nsresult nsHttpResponseHead::SetHeader_locked(
|
||||
const nsHttpAtom& atom, const nsACString& hdr, const nsACString& val,
|
||||
bool merge, const nsHttpHeaderArray::HeaderVariety& variety) {
|
||||
nsresult rv = mHeaders.SetHeader(atom, hdr, val, merge, variety);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// respond to changes in these headers. we need to reparse the entire
|
||||
|
@ -893,48 +891,95 @@ bool nsHttpResponseHead::ExpiresInPast_locked() const {
|
|||
NS_SUCCEEDED(GetDateValue_locked(&dateVal)) && expiresVal < dateVal;
|
||||
}
|
||||
|
||||
void nsHttpResponseHead::UpdateOriginalHeaders(nsHttpResponseHead* aOther) {
|
||||
mRecursiveMutex.AssertCurrentThreadIn();
|
||||
aOther->mRecursiveMutex.AssertCurrentThreadIn();
|
||||
|
||||
uint32_t i, count = aOther->mHeaders.Count();
|
||||
|
||||
// container to maintain a list of entries purged
|
||||
nsTHashSet<nsCString> purgedEntries;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
nsHttpAtom header;
|
||||
nsHttpHeaderArray::HeaderVariety variety;
|
||||
nsAutoCString headerNameOriginal;
|
||||
nsAutoCString val;
|
||||
|
||||
if (!aOther->mHeaders.PeekHeaderAt(i, header, headerNameOriginal, variety,
|
||||
val)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CanIgnoreResponseHeaderTypes(header) ||
|
||||
!IsOriginalResponseHeader(variety)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// remove old response header entries as we have received updated
|
||||
// response headers from 304/206 response
|
||||
if (purgedEntries.EnsureInserted(header.val())) {
|
||||
mHeaders.PurgeHeaderEntries(header);
|
||||
}
|
||||
|
||||
DebugOnly<nsresult> rv =
|
||||
mHeaders.SetHeaderFromNet(header, headerNameOriginal, val, true);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
}
|
||||
|
||||
bool nsHttpResponseHead::CanIgnoreResponseHeaderTypes(
|
||||
const nsHttpAtom& header) const {
|
||||
return (header == nsHttp::Connection || header == nsHttp::Proxy_Connection ||
|
||||
header == nsHttp::Keep_Alive ||
|
||||
header == nsHttp::Proxy_Authenticate ||
|
||||
header == nsHttp::Proxy_Authorization ||
|
||||
// not a response header!
|
||||
header == nsHttp::TE || header == nsHttp::Trailer ||
|
||||
header == nsHttp::Transfer_Encoding || header == nsHttp::Upgrade ||
|
||||
// Ignore any non-modifiable headers...
|
||||
header == nsHttp::Content_Location || header == nsHttp::Content_MD5 ||
|
||||
header == nsHttp::ETag ||
|
||||
// Assume Cache-Control: "no-transform"
|
||||
header == nsHttp::Content_Encoding ||
|
||||
header == nsHttp::Content_Range || header == nsHttp::Content_Type ||
|
||||
// Ignore wacky headers too...
|
||||
// this one is for MS servers that send "Content-Length: 0"
|
||||
// on 304 responses
|
||||
header == nsHttp::Content_Length);
|
||||
}
|
||||
|
||||
void nsHttpResponseHead::UpdateHeaders(nsHttpResponseHead* aOther) {
|
||||
LOG(("nsHttpResponseHead::UpdateHeaders [this=%p]\n", this));
|
||||
|
||||
RecursiveMutexAutoLock monitor(mRecursiveMutex);
|
||||
RecursiveMutexAutoLock monitorOther(aOther->mRecursiveMutex);
|
||||
|
||||
UpdateOriginalHeaders(aOther);
|
||||
|
||||
uint32_t i, count = aOther->mHeaders.Count();
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
nsHttpAtom header;
|
||||
nsAutoCString headerNameOriginal;
|
||||
|
||||
if (!aOther->mHeaders.PeekHeaderAt(i, header, headerNameOriginal)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsHttpHeaderArray::HeaderVariety variety;
|
||||
nsAutoCString val;
|
||||
if (NS_FAILED(aOther->GetHeader(header, val))) {
|
||||
|
||||
if (!aOther->mHeaders.PeekHeaderAt(i, header, headerNameOriginal, variety,
|
||||
val)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore any hop-by-hop headers...
|
||||
if (header == nsHttp::Connection || header == nsHttp::Proxy_Connection ||
|
||||
header == nsHttp::Keep_Alive || header == nsHttp::Proxy_Authenticate ||
|
||||
header == nsHttp::Proxy_Authorization || // not a response header!
|
||||
header == nsHttp::TE || header == nsHttp::Trailer ||
|
||||
header == nsHttp::Transfer_Encoding || header == nsHttp::Upgrade ||
|
||||
// Ignore any non-modifiable headers...
|
||||
header == nsHttp::Content_Location || header == nsHttp::Content_MD5 ||
|
||||
header == nsHttp::ETag ||
|
||||
// Assume Cache-Control: "no-transform"
|
||||
header == nsHttp::Content_Encoding || header == nsHttp::Content_Range ||
|
||||
header == nsHttp::Content_Type ||
|
||||
// Ignore wacky headers too...
|
||||
// this one is for MS servers that send "Content-Length: 0"
|
||||
// on 304 responses
|
||||
header == nsHttp::Content_Length) {
|
||||
if (CanIgnoreResponseHeaderTypes(header)) {
|
||||
LOG(("ignoring response header [%s: %s]\n", header.get(), val.get()));
|
||||
} else {
|
||||
LOG(("new response header [%s: %s]\n", header.get(), val.get()));
|
||||
|
||||
// overwrite the current header value with the new value...
|
||||
if (NS_FAILED(aOther->GetHeader(header, val))) {
|
||||
continue;
|
||||
}
|
||||
DebugOnly<nsresult> rv =
|
||||
// overwrite the current header value with the new value...
|
||||
SetHeader_locked(header, headerNameOriginal, val);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
|
|
@ -147,10 +147,11 @@ class nsHttpResponseHead {
|
|||
bool GetContentTypeOptionsHeader(nsACString& aOutput) const;
|
||||
|
||||
private:
|
||||
[[nodiscard]] nsresult SetHeader_locked(const nsHttpAtom& atom,
|
||||
const nsACString& h,
|
||||
const nsACString& v, bool m = false)
|
||||
MOZ_REQUIRES(mRecursiveMutex);
|
||||
[[nodiscard]] nsresult SetHeader_locked(
|
||||
const nsHttpAtom& atom, const nsACString& h, const nsACString& v,
|
||||
bool m = false,
|
||||
const nsHttpHeaderArray::HeaderVariety& variety =
|
||||
nsHttpHeaderArray::eVarietyResponse) MOZ_REQUIRES(mRecursiveMutex);
|
||||
void AssignDefaultStatusText() MOZ_REQUIRES(mRecursiveMutex);
|
||||
void ParseVersion(const char*) MOZ_REQUIRES(mRecursiveMutex);
|
||||
void ParseCacheControl(const char*) MOZ_REQUIRES(mRecursiveMutex);
|
||||
|
@ -198,6 +199,19 @@ class nsHttpResponseHead {
|
|||
return mHasCacheControl ? mCacheControlNoCache : mPragmaNoCache;
|
||||
}
|
||||
|
||||
// update original response headers
|
||||
void UpdateOriginalHeaders(nsHttpResponseHead* aOther);
|
||||
|
||||
// headers that can be ignored for a 304/206 response
|
||||
bool CanIgnoreResponseHeaderTypes(const nsHttpAtom& header) const;
|
||||
|
||||
bool IsOriginalResponseHeader(
|
||||
const nsHttpHeaderArray::HeaderVariety variety) const {
|
||||
return (
|
||||
(variety == nsHttpHeaderArray::eVarietyResponseNetOriginal) ||
|
||||
(variety == nsHttpHeaderArray::eVarietyResponseNetOriginalAndResponse));
|
||||
}
|
||||
|
||||
private:
|
||||
// All members must be copy-constructable and assignable
|
||||
nsHttpHeaderArray mHeaders MOZ_GUARDED_BY(mRecursiveMutex);
|
||||
|
|
Загрузка…
Ссылка в новой задаче