Claude Code Router自定义headersbody插件
- 内容介绍
- 文章标签
- 相关推荐
在用ccr时,有时会想删一些body参数,或者指定一些header。
于是写了个插件:
插件代码
module.exports = class {
name = "xxx";
constructor(options = {}) {
this.options = options;
}
async transformRequestIn(request) {
// Create a copy of the request to avoid mutating the original
const modifiedRequest = { ...request };
const headers = {};
for (const [key, value] of Object.entries(
this.options?.headers || {},
)) {
if (value === null) {
delete headers[key];
continue;
}
if (typeof value === "string" && value) {
headers[key] = value;
}
}
for (const [key, value] of Object.entries(this.options?.body || {})) {
// 设置为空表示删除指定属性
if (value === null) {
delete modifiedRequest[key];
continue;
}
if (key in modifiedRequest) {
// Deep merge with existing parameter
if (
typeof modifiedRequest[key] === "object" &&
typeof value === "object" &&
!Array.isArray(modifiedRequest[key]) &&
!Array.isArray(value) &&
modifiedRequest[key] !== null &&
value !== null
) {
// Deep merge objects
modifiedRequest[key] = this.deepMergeObjects(
modifiedRequest[key],
value,
);
} else {
// For non-objects, keep existing value (preserve original)
continue;
}
} else {
// Add new parameter
modifiedRequest[key] = this.cloneValue(value);
}
}
return {
body: modifiedRequest,
config: {
headers,
},
};
}
async transformResponseOut(response) {
// Pass through response unchanged
return response;
}
/**
* Deep merge two objects recursively
*/
deepMergeObjects(target, source) {
const result = { ...target };
for (const [key, value] of Object.entries(source)) {
if (value === null) {
delete result[key];
continue;
}
if (
key in result &&
typeof result[key] === "object" &&
typeof value === "object" &&
!Array.isArray(result[key]) &&
!Array.isArray(value) &&
result[key] !== null &&
value !== null
) {
result[key] = this.deepMergeObjects(result[key], value);
} else {
result[key] = this.cloneValue(value);
}
}
return result;
}
/**
* Clone a value to prevent reference issues
*/
cloneValue(value) {
if (value === null || typeof value !== "object") {
return value;
}
if (Array.isArray(value)) {
return value.map((item) => this.cloneValue(item));
}
const cloned = {};
for (const [key, val] of Object.entries(value)) {
cloned[key] = this.cloneValue(val);
}
return cloned;
}
};
两个功能:
- 自定义headers/删除headers
- 自定义body/删除body
示例用法:
1. 自定义headers:
用法:options.headers配置你想增加的header,如果想要删除某个既有的header,值写成null即可。
如:你要增加一个{“key1”: “val1”}的header,并删除一个名为key2的header,可以在.claude-code-router\config.json中增加配置:
{
"transformers": [
{
"path": "你的插件文件路径",
"options": {
"headers": {
"key1": "val1",
"key2": null
}
}
}
]
}
2. 自定义body:
- 参考ccr自带的CustomParamsTransformer,并做了改变:将值设置为null表示删除这个key
- 用法:options.body中配置要新增的body,只做合并。如果设置为null,表示删除该key。支持多层级。
例如你想设置max_tokens,删除reasoning.enabled的值
{
"transformers": [
{
"path": "你的插件文件路径",
"options": {
"body": {
"max_tokens": 20000,
"reasoning": {
"enabled": null
}
}
}
}
]
}
说明:
- 配置是在transformers中,而不是在use中
- 由于配置的内容是对象,不可通过ccr ui配置,只能修改配置文件。ccr ui显示为[object Object]:
image727×185 15.2 KB - headers和body可以同时配置
- ccr如何新增插件,可参考:ccr(Claude Code Router)配置多apikey的插件
--【壹】--:
在用ccr时,有时会想删一些body参数,或者指定一些header。
于是写了个插件:
插件代码
module.exports = class {
name = "xxx";
constructor(options = {}) {
this.options = options;
}
async transformRequestIn(request) {
// Create a copy of the request to avoid mutating the original
const modifiedRequest = { ...request };
const headers = {};
for (const [key, value] of Object.entries(
this.options?.headers || {},
)) {
if (value === null) {
delete headers[key];
continue;
}
if (typeof value === "string" && value) {
headers[key] = value;
}
}
for (const [key, value] of Object.entries(this.options?.body || {})) {
// 设置为空表示删除指定属性
if (value === null) {
delete modifiedRequest[key];
continue;
}
if (key in modifiedRequest) {
// Deep merge with existing parameter
if (
typeof modifiedRequest[key] === "object" &&
typeof value === "object" &&
!Array.isArray(modifiedRequest[key]) &&
!Array.isArray(value) &&
modifiedRequest[key] !== null &&
value !== null
) {
// Deep merge objects
modifiedRequest[key] = this.deepMergeObjects(
modifiedRequest[key],
value,
);
} else {
// For non-objects, keep existing value (preserve original)
continue;
}
} else {
// Add new parameter
modifiedRequest[key] = this.cloneValue(value);
}
}
return {
body: modifiedRequest,
config: {
headers,
},
};
}
async transformResponseOut(response) {
// Pass through response unchanged
return response;
}
/**
* Deep merge two objects recursively
*/
deepMergeObjects(target, source) {
const result = { ...target };
for (const [key, value] of Object.entries(source)) {
if (value === null) {
delete result[key];
continue;
}
if (
key in result &&
typeof result[key] === "object" &&
typeof value === "object" &&
!Array.isArray(result[key]) &&
!Array.isArray(value) &&
result[key] !== null &&
value !== null
) {
result[key] = this.deepMergeObjects(result[key], value);
} else {
result[key] = this.cloneValue(value);
}
}
return result;
}
/**
* Clone a value to prevent reference issues
*/
cloneValue(value) {
if (value === null || typeof value !== "object") {
return value;
}
if (Array.isArray(value)) {
return value.map((item) => this.cloneValue(item));
}
const cloned = {};
for (const [key, val] of Object.entries(value)) {
cloned[key] = this.cloneValue(val);
}
return cloned;
}
};
两个功能:
- 自定义headers/删除headers
- 自定义body/删除body
示例用法:
1. 自定义headers:
用法:options.headers配置你想增加的header,如果想要删除某个既有的header,值写成null即可。
如:你要增加一个{“key1”: “val1”}的header,并删除一个名为key2的header,可以在.claude-code-router\config.json中增加配置:
{
"transformers": [
{
"path": "你的插件文件路径",
"options": {
"headers": {
"key1": "val1",
"key2": null
}
}
}
]
}
2. 自定义body:
- 参考ccr自带的CustomParamsTransformer,并做了改变:将值设置为null表示删除这个key
- 用法:options.body中配置要新增的body,只做合并。如果设置为null,表示删除该key。支持多层级。
例如你想设置max_tokens,删除reasoning.enabled的值
{
"transformers": [
{
"path": "你的插件文件路径",
"options": {
"body": {
"max_tokens": 20000,
"reasoning": {
"enabled": null
}
}
}
}
]
}
说明:
- 配置是在transformers中,而不是在use中
- 由于配置的内容是对象,不可通过ccr ui配置,只能修改配置文件。ccr ui显示为[object Object]:
image727×185 15.2 KB - headers和body可以同时配置
- ccr如何新增插件,可参考:ccr(Claude Code Router)配置多apikey的插件
在用ccr时,有时会想删一些body参数,或者指定一些header。
于是写了个插件:
插件代码
module.exports = class {
name = "xxx";
constructor(options = {}) {
this.options = options;
}
async transformRequestIn(request) {
// Create a copy of the request to avoid mutating the original
const modifiedRequest = { ...request };
const headers = {};
for (const [key, value] of Object.entries(
this.options?.headers || {},
)) {
if (value === null) {
delete headers[key];
continue;
}
if (typeof value === "string" && value) {
headers[key] = value;
}
}
for (const [key, value] of Object.entries(this.options?.body || {})) {
// 设置为空表示删除指定属性
if (value === null) {
delete modifiedRequest[key];
continue;
}
if (key in modifiedRequest) {
// Deep merge with existing parameter
if (
typeof modifiedRequest[key] === "object" &&
typeof value === "object" &&
!Array.isArray(modifiedRequest[key]) &&
!Array.isArray(value) &&
modifiedRequest[key] !== null &&
value !== null
) {
// Deep merge objects
modifiedRequest[key] = this.deepMergeObjects(
modifiedRequest[key],
value,
);
} else {
// For non-objects, keep existing value (preserve original)
continue;
}
} else {
// Add new parameter
modifiedRequest[key] = this.cloneValue(value);
}
}
return {
body: modifiedRequest,
config: {
headers,
},
};
}
async transformResponseOut(response) {
// Pass through response unchanged
return response;
}
/**
* Deep merge two objects recursively
*/
deepMergeObjects(target, source) {
const result = { ...target };
for (const [key, value] of Object.entries(source)) {
if (value === null) {
delete result[key];
continue;
}
if (
key in result &&
typeof result[key] === "object" &&
typeof value === "object" &&
!Array.isArray(result[key]) &&
!Array.isArray(value) &&
result[key] !== null &&
value !== null
) {
result[key] = this.deepMergeObjects(result[key], value);
} else {
result[key] = this.cloneValue(value);
}
}
return result;
}
/**
* Clone a value to prevent reference issues
*/
cloneValue(value) {
if (value === null || typeof value !== "object") {
return value;
}
if (Array.isArray(value)) {
return value.map((item) => this.cloneValue(item));
}
const cloned = {};
for (const [key, val] of Object.entries(value)) {
cloned[key] = this.cloneValue(val);
}
return cloned;
}
};
两个功能:
- 自定义headers/删除headers
- 自定义body/删除body
示例用法:
1. 自定义headers:
用法:options.headers配置你想增加的header,如果想要删除某个既有的header,值写成null即可。
如:你要增加一个{“key1”: “val1”}的header,并删除一个名为key2的header,可以在.claude-code-router\config.json中增加配置:
{
"transformers": [
{
"path": "你的插件文件路径",
"options": {
"headers": {
"key1": "val1",
"key2": null
}
}
}
]
}
2. 自定义body:
- 参考ccr自带的CustomParamsTransformer,并做了改变:将值设置为null表示删除这个key
- 用法:options.body中配置要新增的body,只做合并。如果设置为null,表示删除该key。支持多层级。
例如你想设置max_tokens,删除reasoning.enabled的值
{
"transformers": [
{
"path": "你的插件文件路径",
"options": {
"body": {
"max_tokens": 20000,
"reasoning": {
"enabled": null
}
}
}
}
]
}
说明:
- 配置是在transformers中,而不是在use中
- 由于配置的内容是对象,不可通过ccr ui配置,只能修改配置文件。ccr ui显示为[object Object]:
image727×185 15.2 KB - headers和body可以同时配置
- ccr如何新增插件,可参考:ccr(Claude Code Router)配置多apikey的插件
--【壹】--:
在用ccr时,有时会想删一些body参数,或者指定一些header。
于是写了个插件:
插件代码
module.exports = class {
name = "xxx";
constructor(options = {}) {
this.options = options;
}
async transformRequestIn(request) {
// Create a copy of the request to avoid mutating the original
const modifiedRequest = { ...request };
const headers = {};
for (const [key, value] of Object.entries(
this.options?.headers || {},
)) {
if (value === null) {
delete headers[key];
continue;
}
if (typeof value === "string" && value) {
headers[key] = value;
}
}
for (const [key, value] of Object.entries(this.options?.body || {})) {
// 设置为空表示删除指定属性
if (value === null) {
delete modifiedRequest[key];
continue;
}
if (key in modifiedRequest) {
// Deep merge with existing parameter
if (
typeof modifiedRequest[key] === "object" &&
typeof value === "object" &&
!Array.isArray(modifiedRequest[key]) &&
!Array.isArray(value) &&
modifiedRequest[key] !== null &&
value !== null
) {
// Deep merge objects
modifiedRequest[key] = this.deepMergeObjects(
modifiedRequest[key],
value,
);
} else {
// For non-objects, keep existing value (preserve original)
continue;
}
} else {
// Add new parameter
modifiedRequest[key] = this.cloneValue(value);
}
}
return {
body: modifiedRequest,
config: {
headers,
},
};
}
async transformResponseOut(response) {
// Pass through response unchanged
return response;
}
/**
* Deep merge two objects recursively
*/
deepMergeObjects(target, source) {
const result = { ...target };
for (const [key, value] of Object.entries(source)) {
if (value === null) {
delete result[key];
continue;
}
if (
key in result &&
typeof result[key] === "object" &&
typeof value === "object" &&
!Array.isArray(result[key]) &&
!Array.isArray(value) &&
result[key] !== null &&
value !== null
) {
result[key] = this.deepMergeObjects(result[key], value);
} else {
result[key] = this.cloneValue(value);
}
}
return result;
}
/**
* Clone a value to prevent reference issues
*/
cloneValue(value) {
if (value === null || typeof value !== "object") {
return value;
}
if (Array.isArray(value)) {
return value.map((item) => this.cloneValue(item));
}
const cloned = {};
for (const [key, val] of Object.entries(value)) {
cloned[key] = this.cloneValue(val);
}
return cloned;
}
};
两个功能:
- 自定义headers/删除headers
- 自定义body/删除body
示例用法:
1. 自定义headers:
用法:options.headers配置你想增加的header,如果想要删除某个既有的header,值写成null即可。
如:你要增加一个{“key1”: “val1”}的header,并删除一个名为key2的header,可以在.claude-code-router\config.json中增加配置:
{
"transformers": [
{
"path": "你的插件文件路径",
"options": {
"headers": {
"key1": "val1",
"key2": null
}
}
}
]
}
2. 自定义body:
- 参考ccr自带的CustomParamsTransformer,并做了改变:将值设置为null表示删除这个key
- 用法:options.body中配置要新增的body,只做合并。如果设置为null,表示删除该key。支持多层级。
例如你想设置max_tokens,删除reasoning.enabled的值
{
"transformers": [
{
"path": "你的插件文件路径",
"options": {
"body": {
"max_tokens": 20000,
"reasoning": {
"enabled": null
}
}
}
}
]
}
说明:
- 配置是在transformers中,而不是在use中
- 由于配置的内容是对象,不可通过ccr ui配置,只能修改配置文件。ccr ui显示为[object Object]:
image727×185 15.2 KB - headers和body可以同时配置
- ccr如何新增插件,可参考:ccr(Claude Code Router)配置多apikey的插件

