1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsHttpResponseHead_h__
7 #define nsHttpResponseHead_h__
9 #include "nsHttpHeaderArray.h"
12 #include "mozilla/RecursiveMutex.h"
15 /* Xlib headers insist on this for some reason... Nuke it because
16 it'll override our member name */
17 typedef Status __StatusTmp
;
19 typedef __StatusTmp Status
;
22 class nsIHttpHeaderVisitor
;
24 // This needs to be forward declared here so we can include only this header
25 // without also including PHttpChannelParams.h
34 //-----------------------------------------------------------------------------
35 // nsHttpResponseHead represents the status line and headers from an HTTP
37 //-----------------------------------------------------------------------------
39 class nsHttpResponseHead
{
41 nsHttpResponseHead() = default;
43 nsHttpResponseHead(const nsHttpResponseHead
& aOther
);
44 nsHttpResponseHead
& operator=(const nsHttpResponseHead
& aOther
);
46 void Enter() const MOZ_CAPABILITY_ACQUIRE(mRecursiveMutex
) {
47 mRecursiveMutex
.Lock();
49 void Exit() const MOZ_CAPABILITY_RELEASE(mRecursiveMutex
) {
50 mRecursiveMutex
.Unlock();
52 void AssertMutexOwned() const { mRecursiveMutex
.AssertCurrentThreadIn(); }
54 HttpVersion
Version();
55 uint16_t Status() const;
56 void StatusText(nsACString
& aStatusText
);
57 int64_t ContentLength();
58 void ContentType(nsACString
& aContentType
) const;
59 void ContentCharset(nsACString
& aContentCharset
);
66 * Full length of the entity. For byte-range requests, this may be larger
67 * than ContentLength(), which will only represent the requested part of the
70 int64_t TotalEntitySize();
72 [[nodiscard
]] nsresult
SetHeader(const nsACString
& h
, const nsACString
& v
,
74 [[nodiscard
]] nsresult
SetHeader(const nsHttpAtom
& h
, const nsACString
& v
,
76 [[nodiscard
]] nsresult
GetHeader(const nsHttpAtom
& h
, nsACString
& v
) const;
77 void ClearHeader(const nsHttpAtom
& h
);
79 bool HasHeaderValue(const nsHttpAtom
& h
, const char* v
);
80 bool HasHeader(const nsHttpAtom
& h
) const;
82 void SetContentType(const nsACString
& s
);
83 void SetContentCharset(const nsACString
& s
);
84 void SetContentLength(int64_t);
86 // write out the response status line and headers as a single text block,
87 // optionally pruning out transient headers (ie. headers that only make
88 // sense the first time the response is handled).
89 // Both functions append to the string supplied string.
90 void Flatten(nsACString
&, bool pruneTransients
);
91 void FlattenNetworkOriginalHeaders(nsACString
& buf
);
93 // The next 2 functions parse flattened response head and original net
94 // headers. They are used when we are reading an entry from the cache.
96 // To keep proper order of the original headers we MUST call
97 // ParseCachedOriginalHeaders FIRST and then ParseCachedHead.
99 // block must be null terminated.
100 [[nodiscard
]] nsresult
ParseCachedHead(const char* block
);
101 [[nodiscard
]] nsresult
ParseCachedOriginalHeaders(char* block
);
103 // parse the status line.
104 nsresult
ParseStatusLine(const nsACString
& line
);
106 // parse a header line.
107 [[nodiscard
]] nsresult
ParseHeaderLine(const nsACString
& line
);
109 // cache validation support methods
110 [[nodiscard
]] nsresult
ComputeFreshnessLifetime(uint32_t*);
111 [[nodiscard
]] nsresult
ComputeCurrentAge(uint32_t now
, uint32_t requestTime
,
114 bool MustValidateIfExpired();
116 // return true if the response contains a valid Cache-control:
117 // stale-while-revalidate and |now| is less than or equal |expiration +
118 // stale-while-revalidate|. Otherwise false.
119 bool StaleWhileRevalidate(uint32_t now
, uint32_t expiration
);
121 // returns true if the server appears to support byte range requests.
124 // returns true if the Expires header has a value in the past relative to the
125 // value of the Date header.
126 bool ExpiresInPast();
129 void UpdateHeaders(nsHttpResponseHead
* aOther
);
131 // reset the response head to it's initial state
134 [[nodiscard
]] nsresult
GetLastModifiedValue(uint32_t* result
);
136 bool operator==(const nsHttpResponseHead
& aOther
) const;
138 // Using this function it is possible to itereate through all headers
139 // automatically under one lock.
140 [[nodiscard
]] nsresult
VisitHeaders(nsIHttpHeaderVisitor
* visitor
,
141 nsHttpHeaderArray::VisitorFilter filter
);
142 [[nodiscard
]] nsresult
GetOriginalHeader(const nsHttpAtom
& aHeader
,
143 nsIHttpHeaderVisitor
* aVisitor
);
145 bool HasContentType() const;
146 bool HasContentCharset();
147 bool GetContentTypeOptionsHeader(nsACString
& aOutput
);
150 [[nodiscard
]] nsresult
SetHeader_locked(const nsHttpAtom
& atom
,
152 const nsACString
& v
, bool m
= false)
153 MOZ_REQUIRES(mRecursiveMutex
);
154 void AssignDefaultStatusText() MOZ_REQUIRES(mRecursiveMutex
);
155 void ParseVersion(const char*) MOZ_REQUIRES(mRecursiveMutex
);
156 void ParseCacheControl(const char*) MOZ_REQUIRES(mRecursiveMutex
);
157 void ParsePragma(const char*) MOZ_REQUIRES(mRecursiveMutex
);
158 // Parses a content-length header-value as described in
159 // https://fetch.spec.whatwg.org/#content-length-header
160 nsresult
ParseResponseContentLength(const nsACString
& aHeaderStr
)
161 MOZ_REQUIRES(mRecursiveMutex
);
163 nsresult
ParseStatusLine_locked(const nsACString
& line
)
164 MOZ_REQUIRES(mRecursiveMutex
);
165 [[nodiscard
]] nsresult
ParseHeaderLine_locked(const nsACString
& line
,
166 bool originalFromNetHeaders
)
167 MOZ_REQUIRES(mRecursiveMutex
);
169 // these return failure if the header does not exist.
170 [[nodiscard
]] nsresult
ParseDateHeader(const nsHttpAtom
& header
,
171 uint32_t* result
) const
172 MOZ_REQUIRES(mRecursiveMutex
);
173 [[nodiscard
]] nsresult
GetAgeValue(uint32_t* result
);
174 [[nodiscard
]] nsresult
GetMaxAgeValue(uint32_t* result
);
175 [[nodiscard
]] nsresult
GetStaleWhileRevalidateValue(uint32_t* result
);
176 [[nodiscard
]] nsresult
GetDateValue(uint32_t* result
);
177 [[nodiscard
]] nsresult
GetExpiresValue(uint32_t* result
);
179 bool ExpiresInPast_locked() const MOZ_REQUIRES(mRecursiveMutex
);
180 [[nodiscard
]] nsresult
GetAgeValue_locked(uint32_t* result
) const
181 MOZ_REQUIRES(mRecursiveMutex
);
182 [[nodiscard
]] nsresult
GetExpiresValue_locked(uint32_t* result
) const
183 MOZ_REQUIRES(mRecursiveMutex
);
184 [[nodiscard
]] nsresult
GetMaxAgeValue_locked(uint32_t* result
) const
185 MOZ_REQUIRES(mRecursiveMutex
);
186 [[nodiscard
]] nsresult
GetStaleWhileRevalidateValue_locked(
187 uint32_t* result
) const MOZ_REQUIRES(mRecursiveMutex
);
189 [[nodiscard
]] nsresult
GetDateValue_locked(uint32_t* result
) const
190 MOZ_REQUIRES(mRecursiveMutex
) {
191 return ParseDateHeader(nsHttp::Date
, result
);
194 [[nodiscard
]] nsresult
GetLastModifiedValue_locked(uint32_t* result
) const
195 MOZ_REQUIRES(mRecursiveMutex
) {
196 return ParseDateHeader(nsHttp::Last_Modified
, result
);
199 bool NoCache_locked() const MOZ_REQUIRES(mRecursiveMutex
) {
200 // We ignore Pragma: no-cache if Cache-Control is set.
201 MOZ_ASSERT_IF(mCacheControlNoCache
, mHasCacheControl
);
202 return mHasCacheControl
? mCacheControlNoCache
: mPragmaNoCache
;
206 // All members must be copy-constructable and assignable
207 nsHttpHeaderArray mHeaders
MOZ_GUARDED_BY(mRecursiveMutex
);
208 HttpVersion mVersion
MOZ_GUARDED_BY(mRecursiveMutex
){HttpVersion::v1_1
};
209 uint16_t mStatus
MOZ_GUARDED_BY(mRecursiveMutex
){200};
210 nsCString mStatusText
MOZ_GUARDED_BY(mRecursiveMutex
);
211 int64_t mContentLength
MOZ_GUARDED_BY(mRecursiveMutex
){-1};
212 nsCString mContentType
MOZ_GUARDED_BY(mRecursiveMutex
);
213 nsCString mContentCharset
MOZ_GUARDED_BY(mRecursiveMutex
);
214 bool mHasCacheControl
MOZ_GUARDED_BY(mRecursiveMutex
){false};
215 bool mCacheControlPublic
MOZ_GUARDED_BY(mRecursiveMutex
){false};
216 bool mCacheControlPrivate
MOZ_GUARDED_BY(mRecursiveMutex
){false};
217 bool mCacheControlNoStore
MOZ_GUARDED_BY(mRecursiveMutex
){false};
218 bool mCacheControlNoCache
MOZ_GUARDED_BY(mRecursiveMutex
){false};
219 bool mCacheControlImmutable
MOZ_GUARDED_BY(mRecursiveMutex
){false};
220 bool mCacheControlStaleWhileRevalidateSet
MOZ_GUARDED_BY(mRecursiveMutex
){
222 uint32_t mCacheControlStaleWhileRevalidate
MOZ_GUARDED_BY(mRecursiveMutex
){0};
223 bool mCacheControlMaxAgeSet
MOZ_GUARDED_BY(mRecursiveMutex
){false};
224 uint32_t mCacheControlMaxAge
MOZ_GUARDED_BY(mRecursiveMutex
){0};
225 bool mPragmaNoCache
MOZ_GUARDED_BY(mRecursiveMutex
){false};
227 // We are using RecursiveMutex instead of a Mutex because VisitHeader
228 // function calls nsIHttpHeaderVisitor::VisitHeader while under lock.
229 mutable RecursiveMutex mRecursiveMutex
{"nsHttpResponseHead.mRecursiveMutex"};
230 // During VisitHeader we sould not allow call to SetHeader.
231 bool mInVisitHeaders
MOZ_GUARDED_BY(mRecursiveMutex
){false};
233 friend struct IPC::ParamTraits
<nsHttpResponseHead
>;
237 } // namespace mozilla
239 #endif // nsHttpResponseHead_h__