gecko-dev/netwerk/protocol/http/nsHttpRequestHead.cpp

390 строки
9.4 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// HttpLog.h should generally be included first
#include "HttpLog.h"
#include "nsHttpRequestHead.h"
#include "nsIHttpHeaderVisitor.h"
//-----------------------------------------------------------------------------
// nsHttpRequestHead
//-----------------------------------------------------------------------------
namespace mozilla {
namespace net {
nsHttpRequestHead::nsHttpRequestHead()
: mMethod(NS_LITERAL_CSTRING("GET"))
, mVersion(NS_HTTP_VERSION_1_1)
, mParsedMethod(kMethod_Get)
, mHTTPS(false)
, mRecursiveMutex("nsHttpRequestHead.mRecursiveMutex")
, mInVisitHeaders(false)
{
MOZ_COUNT_CTOR(nsHttpRequestHead);
}
nsHttpRequestHead::~nsHttpRequestHead()
{
MOZ_COUNT_DTOR(nsHttpRequestHead);
}
// Don't use this function. It is only used by HttpChannelParent to avoid
// copying of request headers!!!
const nsHttpHeaderArray &
nsHttpRequestHead::Headers() const
{
nsHttpRequestHead &curr = const_cast<nsHttpRequestHead&>(*this);
curr.mRecursiveMutex.AssertCurrentThreadIn();
return mHeaders;
}
void
nsHttpRequestHead::SetHeaders(const nsHttpHeaderArray& aHeaders)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
mHeaders = aHeaders;
}
void
nsHttpRequestHead::SetVersion(nsHttpVersion version)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
mVersion = version;
}
void
nsHttpRequestHead::SetRequestURI(const nsACString& s)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
mRequestURI = s;
}
void
nsHttpRequestHead::SetPath(const nsACString& s)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
mPath = s;
}
uint32_t
nsHttpRequestHead::HeaderCount()
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
return mHeaders.Count();
}
nsresult
nsHttpRequestHead::VisitHeaders(nsIHttpHeaderVisitor *visitor,
nsHttpHeaderArray::VisitorFilter filter /* = nsHttpHeaderArray::eFilterAll*/)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
mInVisitHeaders = true;
nsresult rv = mHeaders.VisitHeaders(visitor, filter);
mInVisitHeaders = false;
return rv;
}
void
nsHttpRequestHead::Method(nsACString &aMethod)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
aMethod = mMethod;
}
nsHttpVersion
nsHttpRequestHead::Version()
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
return mVersion;
}
void
nsHttpRequestHead::RequestURI(nsACString &aRequestURI)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
aRequestURI = mRequestURI;
}
void
nsHttpRequestHead::Path(nsACString &aPath)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
aPath = mPath.IsEmpty() ? mRequestURI : mPath;
}
void
nsHttpRequestHead::SetHTTPS(bool val)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
mHTTPS = val;
}
void
nsHttpRequestHead::Origin(nsACString &aOrigin)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
aOrigin = mOrigin;
}
nsresult
nsHttpRequestHead::SetHeader(const nsACString &h, const nsACString &v,
bool m /*= false*/)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
if (mInVisitHeaders) {
return NS_ERROR_FAILURE;
}
return mHeaders.SetHeader(h, v, m,
nsHttpHeaderArray::eVarietyRequestOverride);
}
nsresult
nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v,
bool m /*= false*/)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
if (mInVisitHeaders) {
return NS_ERROR_FAILURE;
}
return mHeaders.SetHeader(h, v, m,
nsHttpHeaderArray::eVarietyRequestOverride);
}
nsresult
nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v, bool m,
nsHttpHeaderArray::HeaderVariety variety)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
if (mInVisitHeaders) {
return NS_ERROR_FAILURE;
}
return mHeaders.SetHeader(h, v, m, variety);
}
nsresult
nsHttpRequestHead::SetEmptyHeader(const nsACString &h)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
if (mInVisitHeaders) {
return NS_ERROR_FAILURE;
}
return mHeaders.SetEmptyHeader(h,
nsHttpHeaderArray::eVarietyRequestOverride);
}
nsresult
nsHttpRequestHead::GetHeader(nsHttpAtom h, nsACString &v)
{
v.Truncate();
RecursiveMutexAutoLock mon(mRecursiveMutex);
return mHeaders.GetHeader(h, v);
}
nsresult
nsHttpRequestHead::ClearHeader(nsHttpAtom h)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
if (mInVisitHeaders) {
return NS_ERROR_FAILURE;
}
mHeaders.ClearHeader(h);
return NS_OK;
}
void
nsHttpRequestHead::ClearHeaders()
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
if (mInVisitHeaders) {
return;
}
mHeaders.Clear();
}
bool
nsHttpRequestHead::HasHeader(nsHttpAtom h)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
return mHeaders.HasHeader(h);
}
bool
nsHttpRequestHead::HasHeaderValue(nsHttpAtom h, const char *v)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
return mHeaders.HasHeaderValue(h, v);
}
nsresult
nsHttpRequestHead::SetHeaderOnce(nsHttpAtom h, const char *v,
bool merge /*= false */)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
if (mInVisitHeaders) {
return NS_ERROR_FAILURE;
}
if (!merge || !mHeaders.HasHeaderValue(h, v)) {
return mHeaders.SetHeader(h, nsDependentCString(v), merge,
nsHttpHeaderArray::eVarietyRequestOverride);
}
return NS_OK;
}
nsHttpRequestHead::ParsedMethodType
nsHttpRequestHead::ParsedMethod()
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
return mParsedMethod;
}
bool
nsHttpRequestHead::EqualsMethod(ParsedMethodType aType)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
return mParsedMethod == aType;
}
void
nsHttpRequestHead::ParseHeaderSet(const char *buffer)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
nsHttpAtom hdr;
nsAutoCString headerNameOriginal;
nsAutoCString val;
while (buffer) {
const char *eof = strchr(buffer, '\r');
if (!eof) {
break;
}
if (NS_SUCCEEDED(nsHttpHeaderArray::ParseHeaderLine(
nsDependentCSubstring(buffer, eof - buffer),
&hdr,
&headerNameOriginal,
&val))) {
DebugOnly<nsresult> rv = mHeaders.SetHeaderFromNet(hdr,
headerNameOriginal,
val,
false);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
buffer = eof + 1;
if (*buffer == '\n') {
buffer++;
}
}
}
bool
nsHttpRequestHead::IsHTTPS()
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
return mHTTPS;
}
void
nsHttpRequestHead::SetMethod(const nsACString &method)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
mParsedMethod = kMethod_Custom;
mMethod = method;
if (!strcmp(mMethod.get(), "GET")) {
mParsedMethod = kMethod_Get;
} else if (!strcmp(mMethod.get(), "POST")) {
mParsedMethod = kMethod_Post;
} else if (!strcmp(mMethod.get(), "OPTIONS")) {
mParsedMethod = kMethod_Options;
} else if (!strcmp(mMethod.get(), "CONNECT")) {
mParsedMethod = kMethod_Connect;
} else if (!strcmp(mMethod.get(), "HEAD")) {
mParsedMethod = kMethod_Head;
} else if (!strcmp(mMethod.get(), "PUT")) {
mParsedMethod = kMethod_Put;
} else if (!strcmp(mMethod.get(), "TRACE")) {
mParsedMethod = kMethod_Trace;
}
}
void
nsHttpRequestHead::SetOrigin(const nsACString &scheme, const nsACString &host,
int32_t port)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
mOrigin.Assign(scheme);
mOrigin.Append(NS_LITERAL_CSTRING("://"));
mOrigin.Append(host);
if (port >= 0) {
mOrigin.Append(NS_LITERAL_CSTRING(":"));
mOrigin.AppendInt(port);
}
}
bool
nsHttpRequestHead::IsSafeMethod()
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
// This code will need to be extended for new safe methods, otherwise
// they'll default to "not safe".
if ((mParsedMethod == kMethod_Get) || (mParsedMethod == kMethod_Head) ||
(mParsedMethod == kMethod_Options) || (mParsedMethod == kMethod_Trace)
) {
return true;
}
if (mParsedMethod != kMethod_Custom) {
return false;
}
return (!strcmp(mMethod.get(), "PROPFIND") ||
!strcmp(mMethod.get(), "REPORT") ||
!strcmp(mMethod.get(), "SEARCH"));
}
void
nsHttpRequestHead::Flatten(nsACString &buf, bool pruneProxyHeaders)
{
RecursiveMutexAutoLock mon(mRecursiveMutex);
// note: the first append is intentional.
buf.Append(mMethod);
buf.Append(' ');
buf.Append(mRequestURI);
buf.AppendLiteral(" HTTP/");
switch (mVersion) {
case NS_HTTP_VERSION_1_1:
buf.AppendLiteral("1.1");
break;
case NS_HTTP_VERSION_0_9:
buf.AppendLiteral("0.9");
break;
default:
buf.AppendLiteral("1.0");
}
buf.AppendLiteral("\r\n");
mHeaders.Flatten(buf, pruneProxyHeaders, false);
}
} // namespace net
} // namespace mozilla