Commit bc40f64e authored by Ilia Demianenko's avatar Ilia Demianenko Committed by Commit Bot

DevTools: Add "Copy as PowerShell" option for network requests

PowerShell is a powerful command-line shell which is preinstalled on all
Windows 7+ machines and is capable of issuing arbitrary network
requests. This change adds two options to the network request context
menu on Windows systems: "Copy as PowerShell" and "Copy all as
PowerShell".

Testing done: strings from the old curl-command.html and the Big List of
Naughty Strings (https://github.com/minimaxir/big-list-of-naughty-strings)
were submitted as request URL and bodies. Requests then were copied,
submitted from PowerShell and cURL (bash) and compared on the server side.
All requests got byte-for-byte match.

Bug: 787693
Change-Id: I1a404e0a127cc27f154ad965661fb227232a0b08
Reviewed-on: https://chromium-review.googlesource.com/784770Reviewed-by: default avatarPavel Feldman <pfeldman@chromium.org>
Reviewed-by: default avatarBlaise Bruer <allada@chromium.org>
Commit-Queue: Will Chen <chenwilliam@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521141}
parent 1bfa5903
......@@ -315,6 +315,7 @@ Hyunki Baik <hyunki.baik@samsung.com>
Ian Cullinan <cullinan@amazon.com>
Ian Scott <ian.scott@arteris.com>
Ibrar Ahmed <ibrar.ahmad@gmail.com>
Ilia Demianenko <ilia.demianenko@gmail.com>
Ilia K <ki.stfu@gmail.com>
Ilya Konstantinov <ilya.konstantinov@gmail.com>
Ion Rosca <rosca@adobe.com>
......
......@@ -1168,16 +1168,19 @@ Network.NetworkLogView = class extends UI.VBox {
}
if (Host.isWin()) {
footerSection.appendItem(
Common.UIString('Copy as PowerShell'), this._copyPowerShellCommand.bind(this, request));
footerSection.appendItem(
Common.UIString('Copy as cURL (cmd)'), this._copyCurlCommand.bind(this, request, 'win'));
footerSection.appendItem(
Common.UIString('Copy as cURL (bash)'), this._copyCurlCommand.bind(this, request, 'unix'));
footerSection.appendItem(Common.UIString('Copy All as cURL (cmd)'), this._copyAllCurlCommand.bind(this, 'win'));
footerSection.appendItem(Common.UIString('Copy all as PowerShell'), this._copyAllPowerShellCommand.bind(this));
footerSection.appendItem(Common.UIString('Copy all as cURL (cmd)'), this._copyAllCurlCommand.bind(this, 'win'));
footerSection.appendItem(
Common.UIString('Copy All as cURL (bash)'), this._copyAllCurlCommand.bind(this, 'unix'));
Common.UIString('Copy all as cURL (bash)'), this._copyAllCurlCommand.bind(this, 'unix'));
} else {
footerSection.appendItem(Common.UIString('Copy as cURL'), this._copyCurlCommand.bind(this, request, 'unix'));
footerSection.appendItem(Common.UIString('Copy All as cURL'), this._copyAllCurlCommand.bind(this, 'unix'));
footerSection.appendItem(Common.UIString('Copy all as cURL'), this._copyAllCurlCommand.bind(this, 'unix'));
}
} else {
copyMenu = contextMenu.clipboardSection().appendSubMenuItem(Common.UIString('Copy'));
......@@ -1273,6 +1276,19 @@ Network.NetworkLogView = class extends UI.VBox {
InspectorFrontendHost.copyText(commands.join(' ;\n'));
}
/**
* @param {!SDK.NetworkRequest} request
*/
_copyPowerShellCommand(request) {
InspectorFrontendHost.copyText(this._generatePowerShellCommand(request));
}
_copyAllPowerShellCommand() {
var requests = NetworkLog.networkLog.requests();
var commands = requests.map(this._generatePowerShellCommand.bind(this));
InspectorFrontendHost.copyText(commands.join(';\r\n'));
}
async _exportAll() {
var url = SDK.targetManager.mainTarget().inspectedURL();
var parsedURL = url.asParsedURL();
......@@ -1739,6 +1755,56 @@ Network.NetworkLogView = class extends UI.VBox {
command.push('--insecure');
return command.join(' ');
}
/**
* @param {!SDK.NetworkRequest} request
* @return {string}
*/
_generatePowerShellCommand(request) {
var command = ['Invoke-WebRequest'];
var ignoredHeaders = new Set(['host', 'connection', 'proxy-connection', 'content-length', 'expect', 'range']);
/**
* @param {string} str
* @return {string}
*/
function escapeString(str) {
return '"' +
str.replace(/[`\$"]/g, '`$&').replace(/[^\x20-\x7E]/g, char => '$([char]' + char.charCodeAt(0) + ')') + '"';
}
command.push('-Uri');
command.push(escapeString(request.url()));
if (request.requestMethod !== 'GET') {
command.push('-Method');
command.push(escapeString(request.requestMethod));
}
var requestHeaders = request.requestHeaders();
var headerNameValuePairs = [];
for (var header of requestHeaders) {
var name = header.name.replace(/^:/, ''); // Translate h2 headers to HTTP headers.
if (ignoredHeaders.has(name.toLowerCase()))
continue;
headerNameValuePairs.push(escapeString(name) + '=' + escapeString(header.value));
}
if (headerNameValuePairs.length) {
command.push('-Headers');
command.push('@{' + headerNameValuePairs.join('; ') + '}');
}
if (request.requestFormData) {
command.push('-Body');
var body = escapeString(request.requestFormData);
if (/[^\x20-\x7E]/.test(request.requestFormData))
command.push('([System.Text.Encoding]::UTF8.GetBytes(' + body + '))');
else
command.push(body);
}
return command.join(' ');
}
};
Network.NetworkLogView._isFilteredOutSymbol = Symbol('isFilteredOut');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment