nsHttpRequestHead.cpp 9.4 KB

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