mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 23:35:34 +00:00
Bug 1427718 - Display multiple headers with the same name; r=rickychien
MozReview-Commit-ID: 2nV51xLyCni --HG-- extra : rebase_source : c5d368d84ce4766fe40e4b750441e1d4474db504
This commit is contained in:
parent
ba2bcb9d99
commit
b8ea144988
@ -20,7 +20,10 @@ const {
|
||||
fetchNetworkUpdatePacket,
|
||||
writeHeaderText,
|
||||
} = require("../utils/request-utils");
|
||||
const { sortObjectKeys } = require("../utils/sort-utils");
|
||||
const {
|
||||
HeadersProvider,
|
||||
HeaderList,
|
||||
} = require("../utils/headers-provider");
|
||||
|
||||
// Components
|
||||
const PropertiesView = createFactory(require("./PropertiesView"));
|
||||
@ -53,7 +56,7 @@ const SUMMARY_URL = L10N.getStr("netmonitor.summary.url");
|
||||
const SUMMARY_STATUS = L10N.getStr("netmonitor.summary.status");
|
||||
const SUMMARY_VERSION = L10N.getStr("netmonitor.summary.version");
|
||||
|
||||
/*
|
||||
/**
|
||||
* Headers panel component
|
||||
* Lists basic information about the request
|
||||
*/
|
||||
@ -103,13 +106,8 @@ class HeadersPanel extends Component {
|
||||
if (headers && headers.headers.length) {
|
||||
let headerKey = `${title} (${getFormattedSize(headers.headersSize, 3)})`;
|
||||
let propertiesResult = {
|
||||
[headerKey]:
|
||||
headers.headers.reduce((acc, { name, value }) =>
|
||||
name ? Object.assign(acc, { [name]: value }) : acc
|
||||
, {})
|
||||
[headerKey]: new HeaderList(headers.headers)
|
||||
};
|
||||
|
||||
propertiesResult[headerKey] = sortObjectKeys(propertiesResult[headerKey]);
|
||||
return propertiesResult;
|
||||
}
|
||||
|
||||
@ -302,6 +300,7 @@ class HeadersPanel extends Component {
|
||||
),
|
||||
PropertiesView({
|
||||
object,
|
||||
provider: HeadersProvider,
|
||||
filterPlaceHolder: HEADERS_FILTER_TEXT,
|
||||
sectionNames: Object.keys(object),
|
||||
renderValue: this.renderValue,
|
||||
|
@ -42,7 +42,7 @@ const AUTO_EXPAND_MAX_NODES = 50;
|
||||
const EDITOR_CONFIG_ID = "EDITOR_CONFIG";
|
||||
const HTML_PREVIEW_ID = "HTML_PREVIEW";
|
||||
|
||||
/*
|
||||
/**
|
||||
* Properties View component
|
||||
* A scrollable tree view component which provides some useful features for
|
||||
* representing object properties.
|
||||
@ -57,6 +57,7 @@ class PropertiesView extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
object: PropTypes.object,
|
||||
provider: PropTypes.object,
|
||||
enableInput: PropTypes.bool,
|
||||
expandableStrings: PropTypes.bool,
|
||||
filterPlaceHolder: PropTypes.string,
|
||||
@ -190,6 +191,7 @@ class PropertiesView extends Component {
|
||||
renderValue,
|
||||
sectionNames,
|
||||
openLink,
|
||||
provider,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -206,6 +208,7 @@ class PropertiesView extends Component {
|
||||
div({ className: "tree-container" },
|
||||
TreeView({
|
||||
object,
|
||||
provider,
|
||||
columns: [{
|
||||
id: "value",
|
||||
width: "100%",
|
||||
|
86
devtools/client/netmonitor/src/utils/headers-provider.js
Normal file
86
devtools/client/netmonitor/src/utils/headers-provider.js
Normal file
@ -0,0 +1,86 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { ObjectProvider } = require("devtools/client/shared/components/tree/ObjectProvider");
|
||||
|
||||
/**
|
||||
* Custom tree provider.
|
||||
*
|
||||
* This provider is used to provide set of headers and is
|
||||
* utilized by the HeadersPanel.
|
||||
* The default ObjectProvider can't be used since it doesn't
|
||||
* allow duplicities by design and so it can't support duplicity
|
||||
* headers (more headers with the same name).
|
||||
*/
|
||||
var HeadersProvider = {
|
||||
...ObjectProvider,
|
||||
|
||||
getChildren(object) {
|
||||
if (object.value instanceof HeaderList) {
|
||||
return object.value.headers.map((header, index) =>
|
||||
new Header(header.name, header.value, index));
|
||||
}
|
||||
return ObjectProvider.getChildren(object);
|
||||
},
|
||||
|
||||
hasChildren: function (object) {
|
||||
if (object.value instanceof HeaderList) {
|
||||
return object.value.headers.length > 0;
|
||||
} else if (object instanceof Header) {
|
||||
return false;
|
||||
}
|
||||
return ObjectProvider.hasChildren(object);
|
||||
},
|
||||
|
||||
getLabel: function (object) {
|
||||
if (object instanceof Header) {
|
||||
return object.name;
|
||||
}
|
||||
return ObjectProvider.getLabel(object);
|
||||
},
|
||||
|
||||
getValue: function (object) {
|
||||
if (object instanceof Header) {
|
||||
return object.value;
|
||||
}
|
||||
return ObjectProvider.getValue(object);
|
||||
},
|
||||
|
||||
getKey(object) {
|
||||
if (object instanceof Header) {
|
||||
return object.key;
|
||||
}
|
||||
return ObjectProvider.getKey(object);
|
||||
},
|
||||
|
||||
getType: function (object) {
|
||||
if (object instanceof Header) {
|
||||
return "string";
|
||||
}
|
||||
return ObjectProvider.getType(object);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper data structures for list of headers.
|
||||
*/
|
||||
function HeaderList(headers) {
|
||||
this.headers = headers;
|
||||
this.headers.sort((a, b) => {
|
||||
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
|
||||
});
|
||||
}
|
||||
|
||||
function Header(name, value, key) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
HeadersProvider,
|
||||
HeaderList
|
||||
};
|
@ -13,6 +13,7 @@ DevToolsModules(
|
||||
'filter-predicates.js',
|
||||
'filter-text-utils.js',
|
||||
'format-utils.js',
|
||||
'headers-provider.js',
|
||||
'l10n.js',
|
||||
'mdn-utils.js',
|
||||
'menu.js',
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
/**
|
||||
* Tests if Request-Headers and Response-Headers are sorted in Headers tab.
|
||||
* The test also verifies that headers with the same name and headers
|
||||
* with an empty value are also displayed.
|
||||
*/
|
||||
add_task(function* () {
|
||||
let { tab, monitor } = yield initNetMonitor(SIMPLE_SJS);
|
||||
@ -35,7 +37,8 @@ add_task(function* () {
|
||||
info("Check if Request-Headers and Response-Headers are sorted");
|
||||
let expectedResponseHeaders = ["cache-control", "connection", "content-length",
|
||||
"content-type", "date", "expires", "foo-bar",
|
||||
"pragma", "server", "set-cookie"];
|
||||
"foo-bar", "foo-bar", "pragma", "server", "set-cookie",
|
||||
"set-cookie"];
|
||||
let expectedRequestHeaders = ["Accept", "Accept-Encoding", "Accept-Language",
|
||||
"Cache-Control", "Connection", "Cookie", "Host",
|
||||
"Pragma", "Upgrade-Insecure-Requests", "User-Agent"];
|
||||
|
@ -174,9 +174,9 @@ function test() {
|
||||
|
||||
ok(requestItem.responseHeaders,
|
||||
"There should be a responseHeaders data available.");
|
||||
is(requestItem.responseHeaders.headers.length, 10,
|
||||
is(requestItem.responseHeaders.headers.length, 13,
|
||||
"The responseHeaders data has an incorrect |headers| property.");
|
||||
is(requestItem.responseHeaders.headersSize, 330,
|
||||
is(requestItem.responseHeaders.headersSize, 335,
|
||||
"The responseHeaders data has an incorrect |headersSize| property.");
|
||||
|
||||
verifyRequestItemTarget(
|
||||
@ -228,7 +228,7 @@ function test() {
|
||||
"The status data has an incorrect value.");
|
||||
is(requestItem.statusText, "Och Aye",
|
||||
"The statusText data has an incorrect value.");
|
||||
is(requestItem.headersSize, 330,
|
||||
is(requestItem.headersSize, 335,
|
||||
"The headersSize data has an incorrect value.");
|
||||
|
||||
let requestListItem = document.querySelector(".request-list-item");
|
||||
@ -261,7 +261,7 @@ function test() {
|
||||
|
||||
let requestItem = getSortedRequests(store.getState()).get(0);
|
||||
|
||||
is(requestItem.transferredSize, "342",
|
||||
is(requestItem.transferredSize, "347",
|
||||
"The transferredSize data has an incorrect value.");
|
||||
is(requestItem.contentSize, "12",
|
||||
"The contentSize data has an incorrect value.");
|
||||
|
@ -8,10 +8,14 @@ function handleRequest(request, response) {
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Expires", "0");
|
||||
|
||||
response.setHeader("Set-Cookie", "bob=true; Max-Age=10; HttpOnly", true);
|
||||
response.setHeader("Set-Cookie", "tom=cool; Max-Age=10; HttpOnly", true);
|
||||
response.setHeaderNoCheck("Set-Cookie", "bob=true; Max-Age=10; HttpOnly");
|
||||
response.setHeaderNoCheck("Set-Cookie", "tom=cool; Max-Age=10; HttpOnly");
|
||||
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
||||
response.setHeader("Foo-Bar", "baz", false);
|
||||
|
||||
response.setHeaderNoCheck("Foo-Bar", "baz");
|
||||
response.setHeaderNoCheck("Foo-Bar", "baz");
|
||||
response.setHeaderNoCheck("Foo-Bar", "");
|
||||
|
||||
response.write("Hello world!");
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ define(function (require, exports, module) {
|
||||
*/
|
||||
class TreeView extends Component {
|
||||
// The only required property (not set by default) is the input data
|
||||
// object that is used to puputate the tree.
|
||||
// object that is used to populate the tree.
|
||||
static get propTypes() {
|
||||
return {
|
||||
// The input data object.
|
||||
@ -93,7 +93,7 @@ define(function (require, exports, module) {
|
||||
renderRow: PropTypes.func,
|
||||
// Custom cell renderer
|
||||
renderCell: PropTypes.func,
|
||||
// Custom value renderef
|
||||
// Custom value renderer
|
||||
renderValue: PropTypes.func,
|
||||
// Custom tree label (including a toggle button) renderer
|
||||
renderLabelCell: PropTypes.func,
|
||||
|
@ -879,13 +879,13 @@ NetworkMonitor.prototype = {
|
||||
cookies: [],
|
||||
};
|
||||
|
||||
let setCookieHeader = null;
|
||||
let setCookieHeaders = [];
|
||||
|
||||
channel.visitResponseHeaders({
|
||||
channel.visitOriginalResponseHeaders({
|
||||
visitHeader: function (name, value) {
|
||||
let lowerName = name.toLowerCase();
|
||||
if (lowerName == "set-cookie") {
|
||||
setCookieHeader = value;
|
||||
setCookieHeaders.push(value);
|
||||
}
|
||||
response.headers.push({ name: name, value: value });
|
||||
}
|
||||
@ -896,8 +896,11 @@ NetworkMonitor.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (setCookieHeader) {
|
||||
response.cookies = NetworkHelper.parseSetCookieHeader(setCookieHeader);
|
||||
if (setCookieHeaders.length) {
|
||||
response.cookies = setCookieHeaders.reduce((result, header) => {
|
||||
let cookies = NetworkHelper.parseSetCookieHeader(header);
|
||||
return result.concat(cookies);
|
||||
}, []);
|
||||
}
|
||||
|
||||
// Determine the HTTP version.
|
||||
|
Loading…
Reference in New Issue
Block a user