diff options
Diffstat (limited to 'netwerk/protocol/http/nsHttpRequestHead.cpp')
-rw-r--r-- | netwerk/protocol/http/nsHttpRequestHead.cpp | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/netwerk/protocol/http/nsHttpRequestHead.cpp b/netwerk/protocol/http/nsHttpRequestHead.cpp new file mode 100644 index 000000000..094a79457 --- /dev/null +++ b/netwerk/protocol/http/nsHttpRequestHead.cpp @@ -0,0 +1,369 @@ +/* -*- 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) + , mReentrantMonitor("nsHttpRequestHead.mReentrantMonitor") + , 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.mReentrantMonitor.AssertCurrentThreadIn(); + return mHeaders; +} + +void +nsHttpRequestHead::SetHeaders(const nsHttpHeaderArray& aHeaders) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + mHeaders = aHeaders; +} + +void +nsHttpRequestHead::SetVersion(nsHttpVersion version) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + mVersion = version; +} + +void +nsHttpRequestHead::SetRequestURI(const nsCSubstring &s) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + mRequestURI = s; +} + +void +nsHttpRequestHead::SetPath(const nsCSubstring &s) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + mPath = s; +} + +uint32_t +nsHttpRequestHead::HeaderCount() +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + return mHeaders.Count(); +} + +nsresult +nsHttpRequestHead::VisitHeaders(nsIHttpHeaderVisitor *visitor, + nsHttpHeaderArray::VisitorFilter filter /* = nsHttpHeaderArray::eFilterAll*/) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + mInVisitHeaders = true; + nsresult rv = mHeaders.VisitHeaders(visitor, filter); + mInVisitHeaders = false; + return rv; +} + +void +nsHttpRequestHead::Method(nsACString &aMethod) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + aMethod = mMethod; +} + +nsHttpVersion +nsHttpRequestHead::Version() +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + return mVersion; +} + +void +nsHttpRequestHead::RequestURI(nsACString &aRequestURI) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + aRequestURI = mRequestURI; +} + +void +nsHttpRequestHead::Path(nsACString &aPath) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + aPath = mPath.IsEmpty() ? mRequestURI : mPath; +} + +void +nsHttpRequestHead::SetHTTPS(bool val) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + mHTTPS = val; +} + +void +nsHttpRequestHead::Origin(nsACString &aOrigin) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + aOrigin = mOrigin; +} + +nsresult +nsHttpRequestHead::SetHeader(nsHttpAtom h, const nsACString &v, + bool m /*= false*/) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + + 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) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + + if (mInVisitHeaders) { + return NS_ERROR_FAILURE; + } + + return mHeaders.SetHeader(h, v, m, variety); +} + +nsresult +nsHttpRequestHead::SetEmptyHeader(nsHttpAtom h) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + + if (mInVisitHeaders) { + return NS_ERROR_FAILURE; + } + + return mHeaders.SetEmptyHeader(h, + nsHttpHeaderArray::eVarietyRequestOverride); +} + +nsresult +nsHttpRequestHead::GetHeader(nsHttpAtom h, nsACString &v) +{ + v.Truncate(); + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + return mHeaders.GetHeader(h, v); +} + +nsresult +nsHttpRequestHead::ClearHeader(nsHttpAtom h) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + + if (mInVisitHeaders) { + return NS_ERROR_FAILURE; + } + + mHeaders.ClearHeader(h); + return NS_OK; +} + +void +nsHttpRequestHead::ClearHeaders() +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + + if (mInVisitHeaders) { + return; + } + + mHeaders.Clear(); +} + +bool +nsHttpRequestHead::HasHeader(nsHttpAtom h) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + return mHeaders.HasHeader(h); +} + +bool +nsHttpRequestHead::HasHeaderValue(nsHttpAtom h, const char *v) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + return mHeaders.HasHeaderValue(h, v); +} + +nsresult +nsHttpRequestHead::SetHeaderOnce(nsHttpAtom h, const char *v, + bool merge /*= false */) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + + 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() +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + return mParsedMethod; +} + +bool +nsHttpRequestHead::EqualsMethod(ParsedMethodType aType) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + return mParsedMethod == aType; +} + +void +nsHttpRequestHead::ParseHeaderSet(const char *buffer) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + nsHttpAtom hdr; + nsAutoCString val; + while (buffer) { + const char *eof = strchr(buffer, '\r'); + if (!eof) { + break; + } + if (NS_SUCCEEDED(nsHttpHeaderArray::ParseHeaderLine( + nsDependentCSubstring(buffer, eof - buffer), + &hdr, + &val))) { + + mHeaders.SetHeaderFromNet(hdr, val, false); + } + buffer = eof + 1; + if (*buffer == '\n') { + buffer++; + } + } +} + +bool +nsHttpRequestHead::IsHTTPS() +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + return mHTTPS; +} + +void +nsHttpRequestHead::SetMethod(const nsACString &method) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + 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) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + 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() +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + // 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) +{ + ReentrantMonitorAutoEnter mon(mReentrantMonitor); + // 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 |