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:
sunil mayya 2022-09-20 11:07:45 +00:00
Родитель 08d3766f45
Коммит 1a9dbcd953
4 изменённых файлов: 106 добавлений и 36 удалений

Просмотреть файл

@ -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);