request-utils.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. "use strict";
  2. /* eslint-disable mozilla/reject-some-requires */
  3. const { Ci } = require("chrome");
  4. const { KeyCodes } = require("devtools/client/shared/keycodes");
  5. const { Task } = require("devtools/shared/task");
  6. const NetworkHelper = require("devtools/shared/webconsole/network-helper");
  7. /**
  8. * Helper method to get a wrapped function which can be bound to as
  9. * an event listener directly and is executed only when data-key is
  10. * present in event.target.
  11. *
  12. * @param function callback
  13. * Function to execute execute when data-key
  14. * is present in event.target.
  15. * @param bool onlySpaceOrReturn
  16. * Flag to indicate if callback should only be called
  17. when the space or return button is pressed
  18. * @return function
  19. * Wrapped function with the target data-key as the first argument
  20. * and the event as the second argument.
  21. */
  22. exports.getKeyWithEvent = function (callback, onlySpaceOrReturn) {
  23. return function (event) {
  24. let key = event.target.getAttribute("data-key");
  25. let filterKeyboardEvent = !onlySpaceOrReturn ||
  26. event.keyCode === KeyCodes.DOM_VK_SPACE ||
  27. event.keyCode === KeyCodes.DOM_VK_RETURN;
  28. if (key && filterKeyboardEvent) {
  29. callback.call(null, key);
  30. }
  31. };
  32. };
  33. /**
  34. * Extracts any urlencoded form data sections (e.g. "?foo=bar&baz=42") from a
  35. * POST request.
  36. *
  37. * @param object headers
  38. * The "requestHeaders".
  39. * @param object uploadHeaders
  40. * The "requestHeadersFromUploadStream".
  41. * @param object postData
  42. * The "requestPostData".
  43. * @param object getString
  44. Callback to retrieve a string from a LongStringGrip.
  45. * @return array
  46. * A promise that is resolved with the extracted form data.
  47. */
  48. exports.getFormDataSections = Task.async(function* (headers, uploadHeaders, postData,
  49. getString) {
  50. let formDataSections = [];
  51. let { headers: requestHeaders } = headers;
  52. let { headers: payloadHeaders } = uploadHeaders;
  53. let allHeaders = [...payloadHeaders, ...requestHeaders];
  54. let contentTypeHeader = allHeaders.find(e => {
  55. return e.name.toLowerCase() == "content-type";
  56. });
  57. let contentTypeLongString = contentTypeHeader ? contentTypeHeader.value : "";
  58. let contentType = yield getString(contentTypeLongString);
  59. if (contentType.includes("x-www-form-urlencoded")) {
  60. let postDataLongString = postData.postData.text;
  61. let text = yield getString(postDataLongString);
  62. for (let section of text.split(/\r\n|\r|\n/)) {
  63. // Before displaying it, make sure this section of the POST data
  64. // isn't a line containing upload stream headers.
  65. if (payloadHeaders.every(header => !section.startsWith(header.name))) {
  66. formDataSections.push(section);
  67. }
  68. }
  69. }
  70. return formDataSections;
  71. });
  72. /**
  73. * Form a data: URI given a mime type, encoding, and some text.
  74. *
  75. * @param {String} mimeType the mime type
  76. * @param {String} encoding the encoding to use; if not set, the
  77. * text will be base64-encoded.
  78. * @param {String} text the text of the URI.
  79. * @return {String} a data: URI
  80. */
  81. exports.formDataURI = function (mimeType, encoding, text) {
  82. if (!encoding) {
  83. encoding = "base64";
  84. text = btoa(unescape(encodeURIComponent(text)));
  85. }
  86. return "data:" + mimeType + ";" + encoding + "," + text;
  87. };
  88. /**
  89. * Write out a list of headers into a chunk of text
  90. *
  91. * @param array headers
  92. * Array of headers info {name, value}
  93. * @return string text
  94. * List of headers in text format
  95. */
  96. exports.writeHeaderText = function (headers) {
  97. return headers.map(({name, value}) => name + ": " + value).join("\n");
  98. };
  99. /**
  100. * Helper for getting an abbreviated string for a mime type.
  101. *
  102. * @param string mimeType
  103. * @return string
  104. */
  105. exports.getAbbreviatedMimeType = function (mimeType) {
  106. if (!mimeType) {
  107. return "";
  108. }
  109. return (mimeType.split(";")[0].split("/")[1] || "").split("+")[0];
  110. };
  111. /**
  112. * Helpers for getting details about an nsIURL.
  113. *
  114. * @param nsIURL | string url
  115. * @return string
  116. */
  117. exports.getUriNameWithQuery = function (url) {
  118. if (!(url instanceof Ci.nsIURL)) {
  119. url = NetworkHelper.nsIURL(url);
  120. }
  121. let name = NetworkHelper.convertToUnicode(
  122. unescape(url.fileName || url.filePath || "/"));
  123. let query = NetworkHelper.convertToUnicode(unescape(url.query));
  124. return name + (query ? "?" + query : "");
  125. };
  126. exports.getUriHostPort = function (url) {
  127. if (!(url instanceof Ci.nsIURL)) {
  128. url = NetworkHelper.nsIURL(url);
  129. }
  130. return NetworkHelper.convertToUnicode(unescape(url.hostPort));
  131. };
  132. exports.getUriHost = function (url) {
  133. return exports.getUriHostPort(url).replace(/:\d+$/, "");
  134. };
  135. /**
  136. * Convert a nsIContentPolicy constant to a display string
  137. */
  138. const LOAD_CAUSE_STRINGS = {
  139. [Ci.nsIContentPolicy.TYPE_INVALID]: "invalid",
  140. [Ci.nsIContentPolicy.TYPE_OTHER]: "other",
  141. [Ci.nsIContentPolicy.TYPE_SCRIPT]: "script",
  142. [Ci.nsIContentPolicy.TYPE_IMAGE]: "img",
  143. [Ci.nsIContentPolicy.TYPE_STYLESHEET]: "stylesheet",
  144. [Ci.nsIContentPolicy.TYPE_OBJECT]: "object",
  145. [Ci.nsIContentPolicy.TYPE_DOCUMENT]: "document",
  146. [Ci.nsIContentPolicy.TYPE_SUBDOCUMENT]: "subdocument",
  147. [Ci.nsIContentPolicy.TYPE_REFRESH]: "refresh",
  148. [Ci.nsIContentPolicy.TYPE_XBL]: "xbl",
  149. [Ci.nsIContentPolicy.TYPE_PING]: "ping",
  150. [Ci.nsIContentPolicy.TYPE_XMLHTTPREQUEST]: "xhr",
  151. [Ci.nsIContentPolicy.TYPE_OBJECT_SUBREQUEST]: "objectSubdoc",
  152. [Ci.nsIContentPolicy.TYPE_DTD]: "dtd",
  153. [Ci.nsIContentPolicy.TYPE_FONT]: "font",
  154. [Ci.nsIContentPolicy.TYPE_MEDIA]: "media",
  155. [Ci.nsIContentPolicy.TYPE_WEBSOCKET]: "websocket",
  156. [Ci.nsIContentPolicy.TYPE_CSP_REPORT]: "csp",
  157. [Ci.nsIContentPolicy.TYPE_XSLT]: "xslt",
  158. [Ci.nsIContentPolicy.TYPE_BEACON]: "beacon",
  159. [Ci.nsIContentPolicy.TYPE_FETCH]: "fetch",
  160. [Ci.nsIContentPolicy.TYPE_IMAGESET]: "imageset",
  161. [Ci.nsIContentPolicy.TYPE_WEB_MANIFEST]: "webManifest",
  162. [Ci.nsIContentPolicy.TYPE_SAVEAS_DOWNLOAD]: "saveasDownload"
  163. };
  164. exports.loadCauseString = function (causeType) {
  165. return LOAD_CAUSE_STRINGS[causeType] || "unknown";
  166. };