要创建一个可以灵活修改HTTP请求头的Chrome扩展,包括一个用户界面来动态设置头部名称和值,可以按照以下步骤进行。我们会用到 chrome.storage API 来保存用户的设置,并在后台脚本中使用这些设置来修改请求头。
文件结构
my_chrome_extension/
│
├── icons/
│ ├── icon16.png
│ ├── icon48.png
│ └── icon128.png
│
├── background.js
├── manifest.json
├── options.html
├── options.js
├── popup.html
├── popup.js
├── popup.css
├── options.css
manifest.json
{
"manifest_version": 2,
"name": "Flexible HTTP Headers Modifier",
"version": "1.0",
"description": "A Chrome extension to modify HTTP headers with user-defined values",
"permissions": [
"storage",
"webRequest",
"webRequestBlocking",
"<all_urls>"
],
"background": {
"scripts": ["background.js"]
},
"options_page": "options.html",
"browser_action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
}
background.js
let customHeaders = {};
let urlPattern = '';
chrome.runtime.onInstalled.addListener(() => {
chrome.storage.sync.get(['urlPattern', 'headers', 'values'], function(result) {
if (result.urlPattern) {
urlPattern = result.urlPattern;
}
if (result.headers && result.values) {
for (let i = 0; i < result.headers.length; i++) {
customHeaders[result.headers[i]] = result.values[i];
}
}
});
});
chrome.webRequest.onBeforeSendHeaders.addListener(
function(details) {
if (details.url.match(new RegExp(urlPattern))) {
for (const [name, value] of Object.entries(customHeaders)) {
let headerExists = false;
for (let header of details.requestHeaders) {
if (header.name.toLowerCase() === name.toLowerCase()) {
header.value = value;
headerExists = true;
break;
}
}
if (!headerExists) {
details.requestHeaders.push({ name: name, value: value });
}
}
}
return { requestHeaders: details.requestHeaders };
},
{ urls: ["<all_urls>"] },
["blocking", "requestHeaders"]
);
chrome.storage.onChanged.addListener(function(changes, namespace) {
if (namespace === 'sync') {
if (changes.urlPattern) {
urlPattern = changes.urlPattern.newValue;
}
if (changes.headers && changes.values) {
customHeaders = {};
for (let i = 0; i < changes.headers.newValue.length; i++) {
customHeaders[changes.headers.newValue[i]] = changes.values.newValue[i];
}
}
}
});
options.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Extension Options</title>
<link rel="stylesheet" href="options.css">
</head>
<body>
<div class="container">
<h1>Modify HTTP Headers</h1>
<div class="url-pattern">
<label for="url-pattern-input">URL Pattern:</label>
<input type="text" id="url-pattern-input" placeholder="URL Pattern">
</div>
<table id="headers-table">
<thead>
<tr>
<th>Header Name</th>
<th>Header Value</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="headers-container">
<!-- Header entries will be dynamically added here -->
</tbody>
</table>
<div class="buttons">
<button id="add-header">Add Header</button>
<button id="save-headers">Save Headers</button>
</div>
</div>
<script src="options.js"></script>
</body>
</html>
options.js
document.addEventListener('DOMContentLoaded', function() {
const headersContainer = document.getElementById('headers-container');
const addHeaderButton = document.getElementById('add-header');
const saveHeadersButton = document.getElementById('save-headers');
addHeaderButton.addEventListener('click', function() {
const headerEntry = document.createElement('tr');
headerEntry.className = 'header-entry';
headerEntry.innerHTML = `
<td><input type="text" placeholder="Header Name" class="header-name"></td>
<td><input type="text" placeholder="Header Value" class="header-value"></td>
<td><button class="remove-header">Remove</button></td>
`;
headerEntry.querySelector('.remove-header').addEventListener('click', function() {
headerEntry.remove();
});
headersContainer.appendChild(headerEntry);
});
saveHeadersButton.addEventListener('click', function() {
const headers = [];
const values = [];
document.querySelectorAll('.header-entry').forEach(entry => {
const name = entry.querySelector('.header-name').value;
const value = entry.querySelector('.header-value').value;
if (name && value) {
headers.push(name);
values.push(value);
}
});
const urlPattern = document.getElementById('url-pattern-input').value;
chrome.storage.sync.set({urlPattern: urlPattern, headers: headers, values: values}, function() {
alert('Headers saved');
});
});
chrome.storage.sync.get(['urlPattern', 'headers', 'values'], function(result) {
if (result.urlPattern) {
document.getElementById('url-pattern-input').value = result.urlPattern;
}
if (result.headers && result.values) {
for (let i = 0; i < result.headers.length; i++) {
const headerEntry = document.createElement('tr');
headerEntry.className = 'header-entry';
headerEntry.innerHTML = `
<td><input type="text" value="${result.headers[i]}" class="header-name"></td>
<td><input type="text" value="${result.values[i]}" class="header-value"></td>
<td><button class="remove-header">Remove</button></td>
`;
headerEntry.querySelector('.remove-header').addEventListener('click', function() {
headerEntry.remove();
});
headersContainer.appendChild(headerEntry);
}
}
});
});
popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Popup</title>
<link rel="stylesheet" href="popup.css">
</head>
<body>
<h1>Modify HTTP Headers</h1>
<button id="open-options">Open Options</button>
<script src="popup.js"></script>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('open-options').addEventListener('click', function() {
chrome.runtime.openOptionsPage();
});
});
popup.css
body {
width: 200px;
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
box-sizing: border-box;
}
h1 {
font-size: 16px;
margin: 0 0 20px;
text-align: center;
}
button {
display: block;
width: 100%;
margin: 10px 0;
padding: 10px;
font-size: 14px;
cursor: pointer;
}
#open-options {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
options.css
.container {
width: 800px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 20px;
margin-bottom: 20px;
text-align: center;
}
.url-pattern {
margin-bottom: 20px;
}
.url-pattern label {
margin-right: 10px;
}
input[type="text"] {
width: 96%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
#headers-table {
width: 100%;
border-collapse: collapse;
border: none; /* 移除表格的边框 */
}
#headers-table th, #headers-table td {
border: 1px solid #ccc;
padding: 10px;
text-align: center;
}
#headers-table th {
background-color: #f2f2f2; /* 添加表头背景色 */
}
#headers-table td input[type="text"] {
width: calc(100% - 20px); /* 考虑到内边距,调整输入框的宽度 */
padding: 8px;
margin: 0;
border: none; /* 移除输入框的边框 */
border-radius: 5px;
box-sizing: border-box;
}
.buttons {
margin-top: 20px;
text-align: center;
}
.buttons button {
margin: 0 10px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
border: none;
border-radius: 5px;
background-color: #4CAF50;
color: white;
}
.buttons button:hover {
background-color: #45a049;
}
加载和测试扩展
- 打开 Chrome 浏览器。
- 进入
chrome://extensions/
页面。 - 打开右上角的“开发者模式”。
- 点击“加载已解压的扩展程序”按钮。
- 选择你的扩展所在的目录
my_chrome_extension
。
现在,你可以通过扩展的图标打开选项页面,添加或移除请求头。保存后,这些头会在所有的HTTP请求(包括AJAX请求)中被修改。
你可以写一段简单的说明,介绍用户如何使用 url-pattern,并提供一些示例。以下是一个可能的写作方式:
URL 匹配模式说明
URL 匹配模式允许您指定哪些 URL 将受到您自定义的 HTTP 标头的影响。这些模式采用简单的通配符形式,允许您根据需要指定匹配的 URL。
基本语法:
*
:匹配任意字符序列(包括空字符)?
:匹配单个字符
示例:
example.com
:匹配http://example.com/
和https://example.com/
等*.example.com
:匹配http://sub.example.com/
、https://www.example.com/
等https://example.com/*
:仅匹配以https://example.com/
开头的 URL,包括其所有子路径
注意事项:
- 匹配模式将应用于所有 HTTP 请求,包括页面加载、AJAX 请求等。
- 要确保匹配模式的准确性和有效性,请测试您的规则并进行必要的调整。
你可以根据实际需要调整和扩展这个说明。