зеркало из https://github.com/mozilla/gecko-dev.git
390 строки
9.4 KiB
C++
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
|