Coverage Report

Created: 2018-09-25 14:53

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