summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/nsHttpRequestHead.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/http/nsHttpRequestHead.cpp')
-rw-r--r--netwerk/protocol/http/nsHttpRequestHead.cpp369
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