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