Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/. */
5 :
6 : // HttpLog.h should generally be included first
7 : #include "HttpLog.h"
8 :
9 : #include "nsHttpRequestHead.h"
10 : #include "nsIHttpHeaderVisitor.h"
11 :
12 : //-----------------------------------------------------------------------------
13 : // nsHttpRequestHead
14 : //-----------------------------------------------------------------------------
15 :
16 : namespace mozilla {
17 : namespace net {
18 :
19 10 : nsHttpRequestHead::nsHttpRequestHead()
20 20 : : mMethod(NS_LITERAL_CSTRING("GET"))
21 : , mVersion(NS_HTTP_VERSION_1_1)
22 : , mParsedMethod(kMethod_Get)
23 : , mHTTPS(false)
24 : , mReentrantMonitor("nsHttpRequestHead.mReentrantMonitor")
25 30 : , mInVisitHeaders(false)
26 : {
27 10 : MOZ_COUNT_CTOR(nsHttpRequestHead);
28 10 : }
29 :
30 14 : nsHttpRequestHead::~nsHttpRequestHead()
31 : {
32 7 : MOZ_COUNT_DTOR(nsHttpRequestHead);
33 7 : }
34 :
35 : // Don't use this function. It is only used by HttpChannelParent to avoid
36 : // copying of request headers!!!
37 : const nsHttpHeaderArray &
38 3 : nsHttpRequestHead::Headers() const
39 : {
40 3 : nsHttpRequestHead &curr = const_cast<nsHttpRequestHead&>(*this);
41 3 : curr.mReentrantMonitor.AssertCurrentThreadIn();
42 3 : return mHeaders;
43 : }
44 :
45 : void
46 3 : nsHttpRequestHead::SetHeaders(const nsHttpHeaderArray& aHeaders)
47 : {
48 6 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
49 3 : mHeaders = aHeaders;
50 3 : }
51 :
52 : void
53 3 : nsHttpRequestHead::SetVersion(nsHttpVersion version)
54 : {
55 6 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
56 3 : mVersion = version;
57 3 : }
58 :
59 : void
60 3 : nsHttpRequestHead::SetRequestURI(const nsACString& s)
61 : {
62 6 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
63 3 : mRequestURI = s;
64 3 : }
65 :
66 : void
67 0 : nsHttpRequestHead::SetPath(const nsACString& s)
68 : {
69 0 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
70 0 : mPath = s;
71 0 : }
72 :
73 : uint32_t
74 0 : nsHttpRequestHead::HeaderCount()
75 : {
76 0 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
77 0 : return mHeaders.Count();
78 : }
79 :
80 : nsresult
81 0 : nsHttpRequestHead::VisitHeaders(nsIHttpHeaderVisitor *visitor,
82 : nsHttpHeaderArray::VisitorFilter filter /* = nsHttpHeaderArray::eFilterAll*/)
83 : {
84 0 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
85 0 : mInVisitHeaders = true;
86 0 : nsresult rv = mHeaders.VisitHeaders(visitor, filter);
87 0 : mInVisitHeaders = false;
88 0 : return rv;
89 : }
90 :
91 : void
92 8 : nsHttpRequestHead::Method(nsACString &aMethod)
93 : {
94 16 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
95 8 : aMethod = mMethod;
96 8 : }
97 :
98 : nsHttpVersion
99 2 : nsHttpRequestHead::Version()
100 : {
101 4 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
102 4 : return mVersion;
103 : }
104 :
105 : void
106 0 : nsHttpRequestHead::RequestURI(nsACString &aRequestURI)
107 : {
108 0 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
109 0 : aRequestURI = mRequestURI;
110 0 : }
111 :
112 : void
113 0 : nsHttpRequestHead::Path(nsACString &aPath)
114 : {
115 0 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
116 0 : aPath = mPath.IsEmpty() ? mRequestURI : mPath;
117 0 : }
118 :
119 : void
120 6 : nsHttpRequestHead::SetHTTPS(bool val)
121 : {
122 12 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
123 6 : mHTTPS = val;
124 6 : }
125 :
126 : void
127 0 : nsHttpRequestHead::Origin(nsACString &aOrigin)
128 : {
129 0 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
130 0 : aOrigin = mOrigin;
131 0 : }
132 :
133 : nsresult
134 25 : nsHttpRequestHead::SetHeader(const nsACString &h, const nsACString &v,
135 : bool m /*= false*/)
136 : {
137 50 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
138 :
139 25 : if (mInVisitHeaders) {
140 0 : return NS_ERROR_FAILURE;
141 : }
142 :
143 25 : return mHeaders.SetHeader(h, v, m,
144 25 : nsHttpHeaderArray::eVarietyRequestOverride);
145 : }
146 :
147 : nsresult
148 18 : nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v,
149 : bool m /*= false*/)
150 : {
151 36 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
152 :
153 18 : if (mInVisitHeaders) {
154 0 : return NS_ERROR_FAILURE;
155 : }
156 :
157 18 : return mHeaders.SetHeader(h, v, m,
158 18 : nsHttpHeaderArray::eVarietyRequestOverride);
159 : }
160 :
161 : nsresult
162 40 : nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v, bool m,
163 : nsHttpHeaderArray::HeaderVariety variety)
164 : {
165 80 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
166 :
167 40 : if (mInVisitHeaders) {
168 0 : return NS_ERROR_FAILURE;
169 : }
170 :
171 40 : return mHeaders.SetHeader(h, v, m, variety);
172 : }
173 :
174 : nsresult
175 0 : nsHttpRequestHead::SetEmptyHeader(const nsACString &h)
176 : {
177 0 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
178 :
179 0 : if (mInVisitHeaders) {
180 0 : return NS_ERROR_FAILURE;
181 : }
182 :
183 0 : return mHeaders.SetEmptyHeader(h,
184 0 : nsHttpHeaderArray::eVarietyRequestOverride);
185 : }
186 :
187 : nsresult
188 42 : nsHttpRequestHead::GetHeader(nsHttpAtom h, nsACString &v)
189 : {
190 42 : v.Truncate();
191 84 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
192 84 : return mHeaders.GetHeader(h, v);
193 : }
194 :
195 : nsresult
196 3 : nsHttpRequestHead::ClearHeader(nsHttpAtom h)
197 : {
198 6 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
199 :
200 3 : if (mInVisitHeaders) {
201 0 : return NS_ERROR_FAILURE;
202 : }
203 :
204 3 : mHeaders.ClearHeader(h);
205 3 : return NS_OK;
206 : }
207 :
208 : void
209 0 : nsHttpRequestHead::ClearHeaders()
210 : {
211 0 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
212 :
213 0 : if (mInVisitHeaders) {
214 0 : return;
215 : }
216 :
217 0 : mHeaders.Clear();
218 : }
219 :
220 : bool
221 35 : nsHttpRequestHead::HasHeader(nsHttpAtom h)
222 : {
223 70 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
224 70 : return mHeaders.HasHeader(h);
225 : }
226 :
227 : bool
228 6 : nsHttpRequestHead::HasHeaderValue(nsHttpAtom h, const char *v)
229 : {
230 12 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
231 12 : return mHeaders.HasHeaderValue(h, v);
232 : }
233 :
234 : nsresult
235 2 : nsHttpRequestHead::SetHeaderOnce(nsHttpAtom h, const char *v,
236 : bool merge /*= false */)
237 : {
238 4 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
239 :
240 2 : if (mInVisitHeaders) {
241 0 : return NS_ERROR_FAILURE;
242 : }
243 :
244 2 : if (!merge || !mHeaders.HasHeaderValue(h, v)) {
245 4 : return mHeaders.SetHeader(h, nsDependentCString(v), merge,
246 2 : nsHttpHeaderArray::eVarietyRequestOverride);
247 : }
248 0 : return NS_OK;
249 : }
250 :
251 : nsHttpRequestHead::ParsedMethodType
252 6 : nsHttpRequestHead::ParsedMethod()
253 : {
254 12 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
255 12 : return mParsedMethod;
256 : }
257 :
258 : bool
259 36 : nsHttpRequestHead::EqualsMethod(ParsedMethodType aType)
260 : {
261 72 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
262 72 : return mParsedMethod == aType;
263 : }
264 :
265 : void
266 0 : nsHttpRequestHead::ParseHeaderSet(const char *buffer)
267 : {
268 0 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
269 : nsHttpAtom hdr;
270 0 : nsAutoCString headerNameOriginal;
271 0 : nsAutoCString val;
272 0 : while (buffer) {
273 0 : const char *eof = strchr(buffer, '\r');
274 0 : if (!eof) {
275 0 : break;
276 : }
277 0 : if (NS_SUCCEEDED(nsHttpHeaderArray::ParseHeaderLine(
278 : nsDependentCSubstring(buffer, eof - buffer),
279 : &hdr,
280 : &headerNameOriginal,
281 : &val))) {
282 :
283 0 : DebugOnly<nsresult> rv = mHeaders.SetHeaderFromNet(hdr,
284 : headerNameOriginal,
285 : val,
286 0 : false);
287 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
288 : }
289 0 : buffer = eof + 1;
290 0 : if (*buffer == '\n') {
291 0 : buffer++;
292 : }
293 : }
294 0 : }
295 :
296 : bool
297 0 : nsHttpRequestHead::IsHTTPS()
298 : {
299 0 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
300 0 : return mHTTPS;
301 : }
302 :
303 : void
304 5 : nsHttpRequestHead::SetMethod(const nsACString &method)
305 : {
306 10 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
307 5 : mParsedMethod = kMethod_Custom;
308 5 : mMethod = method;
309 5 : if (!strcmp(mMethod.get(), "GET")) {
310 3 : mParsedMethod = kMethod_Get;
311 2 : } else if (!strcmp(mMethod.get(), "POST")) {
312 1 : mParsedMethod = kMethod_Post;
313 1 : } else if (!strcmp(mMethod.get(), "OPTIONS")) {
314 0 : mParsedMethod = kMethod_Options;
315 1 : } else if (!strcmp(mMethod.get(), "CONNECT")) {
316 0 : mParsedMethod = kMethod_Connect;
317 1 : } else if (!strcmp(mMethod.get(), "HEAD")) {
318 0 : mParsedMethod = kMethod_Head;
319 1 : } else if (!strcmp(mMethod.get(), "PUT")) {
320 1 : mParsedMethod = kMethod_Put;
321 0 : } else if (!strcmp(mMethod.get(), "TRACE")) {
322 0 : mParsedMethod = kMethod_Trace;
323 : }
324 5 : }
325 :
326 : void
327 6 : nsHttpRequestHead::SetOrigin(const nsACString &scheme, const nsACString &host,
328 : int32_t port)
329 : {
330 12 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
331 6 : mOrigin.Assign(scheme);
332 6 : mOrigin.Append(NS_LITERAL_CSTRING("://"));
333 6 : mOrigin.Append(host);
334 6 : if (port >= 0) {
335 5 : mOrigin.Append(NS_LITERAL_CSTRING(":"));
336 5 : mOrigin.AppendInt(port);
337 : }
338 6 : }
339 :
340 : bool
341 3 : nsHttpRequestHead::IsSafeMethod()
342 : {
343 6 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
344 : // This code will need to be extended for new safe methods, otherwise
345 : // they'll default to "not safe".
346 4 : if ((mParsedMethod == kMethod_Get) || (mParsedMethod == kMethod_Head) ||
347 2 : (mParsedMethod == kMethod_Options) || (mParsedMethod == kMethod_Trace)
348 : ) {
349 2 : return true;
350 : }
351 :
352 1 : if (mParsedMethod != kMethod_Custom) {
353 1 : return false;
354 : }
355 :
356 0 : return (!strcmp(mMethod.get(), "PROPFIND") ||
357 0 : !strcmp(mMethod.get(), "REPORT") ||
358 0 : !strcmp(mMethod.get(), "SEARCH"));
359 : }
360 :
361 : void
362 3 : nsHttpRequestHead::Flatten(nsACString &buf, bool pruneProxyHeaders)
363 : {
364 6 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
365 : // note: the first append is intentional.
366 :
367 3 : buf.Append(mMethod);
368 3 : buf.Append(' ');
369 3 : buf.Append(mRequestURI);
370 3 : buf.AppendLiteral(" HTTP/");
371 :
372 3 : switch (mVersion) {
373 : case NS_HTTP_VERSION_1_1:
374 3 : buf.AppendLiteral("1.1");
375 3 : break;
376 : case NS_HTTP_VERSION_0_9:
377 0 : buf.AppendLiteral("0.9");
378 0 : break;
379 : default:
380 0 : buf.AppendLiteral("1.0");
381 : }
382 :
383 3 : buf.AppendLiteral("\r\n");
384 :
385 3 : mHeaders.Flatten(buf, pruneProxyHeaders, false);
386 3 : }
387 :
388 : } // namespace net
389 : } // namespace mozilla
|