码桶
发现社区成员的开源项目
speed.js7.9 KB
import { logAudit } from '../../_audit.js';
import { fireWebhook } from '../../_webhook.js';
const SPEED_SETTINGS = ['rocket_loader', 'minify', 'brotli', 'early_hints', 'h2_prioritization', '0rtt', 'fonts', 'polish', 'mirage', 'image_resizing'];
async function cfGet(cfHeaders, zoneId, setting) {
const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/${setting}`, {
headers: {
...cfHeaders,
'Content-Type': 'application/json'
}
});
return res.json();
}
async function cfPatch(cfHeaders, zoneId, setting, value) {
const res = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/${setting}`, {
method: 'PATCH',
headers: {
...cfHeaders,
'Content-Type': 'application/json'
},
body: JSON.stringify({ value })
});
return res.json();
}
export async function onRequestGet(context) {
const { cfHeaders } = context.data;
const { zoneId } = context.params;
try {
const results = await Promise.all(
SPEED_SETTINGS.map(setting => cfGet(cfHeaders, zoneId, setting))
);
const settings = {};
SPEED_SETTINGS.forEach((key, i) => {
const data = results[i];
if (data.success && data.result) {
settings[key] = data.result.value;
} else {
settings[key] = null;
}
});
return new Response(JSON.stringify({
success: true,
settings,
errors: []
}), {
headers: { 'Content-Type': 'application/json' }
});
} catch (e) {
return new Response(JSON.stringify({
success: false,
errors: [{ message: e.message || 'Failed to fetch speed settings' }]
}), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
}
export async function onRequestPost(context) {
const { cfHeaders } = context.data;
const { zoneId } = context.params;
const body = await context.request.json();
const username = context.data.user?.username || 'client';
const kv = context.env.CF_DNS_KV;
const { action } = body;
if (action === 'enable_all') {
const enableValues = {
rocket_loader: 'on',
minify: { js: true, css: true, html: true },
brotli: 'on',
early_hints: 'on',
h2_prioritization: 'on',
'0rtt': 'on',
fonts: 'on',
polish: 'lossless',
mirage: 'on',
image_resizing: 'on'
};
try {
const patchResults = await Promise.all(
SPEED_SETTINGS.map(setting => cfPatch(cfHeaders, zoneId, setting, enableValues[setting]))
);
const results = {};
const errors = [];
SPEED_SETTINGS.forEach((key, i) => {
const data = patchResults[i];
if (data.success && data.result) {
results[key] = data.result.value;
} else {
results[key] = null;
errors.push({ setting: key, message: data.errors?.[0]?.message || 'Failed to enable' });
}
});
await logAudit(kv, username, 'speed.enable_all', `Enabled all speed optimizations (zone: ${zoneId})`);
await fireWebhook(kv, {
type: 'speed.enable_all',
username,
detail: `Enabled all speed optimizations (zone: ${zoneId})`
});
return new Response(JSON.stringify({
success: true,
results,
errors
}), {
headers: { 'Content-Type': 'application/json' }
});
} catch (e) {
return new Response(JSON.stringify({
success: false,
errors: [{ message: e.message || 'Failed to enable all speed settings' }]
}), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
}
if (action === 'disable_all') {
const disableValues = {
rocket_loader: 'off',
minify: { js: false, css: false, html: false },
brotli: 'off',
early_hints: 'off',
h2_prioritization: 'off',
'0rtt': 'off',
fonts: 'off',
polish: 'off',
mirage: 'off',
image_resizing: 'off'
};
try {
const patchResults = await Promise.all(
SPEED_SETTINGS.map(setting => cfPatch(cfHeaders, zoneId, setting, disableValues[setting]))
);
const results = {};
const errors = [];
SPEED_SETTINGS.forEach((key, i) => {
const data = patchResults[i];
if (data.success && data.result) {
results[key] = data.result.value;
} else {
results[key] = null;
errors.push({ setting: key, message: data.errors?.[0]?.message || 'Failed to disable' });
}
});
await logAudit(kv, username, 'speed.disable_all', `Disabled all speed optimizations (zone: ${zoneId})`);
await fireWebhook(kv, {
type: 'speed.disable_all',
username,
detail: `Disabled all speed optimizations (zone: ${zoneId})`
});
return new Response(JSON.stringify({
success: true,
results,
errors
}), {
headers: { 'Content-Type': 'application/json' }
});
} catch (e) {
return new Response(JSON.stringify({
success: false,
errors: [{ message: e.message || 'Failed to disable all speed settings' }]
}), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
}
if (action === 'update') {
const { setting, value } = body;
if (!SPEED_SETTINGS.includes(setting)) {
return new Response(JSON.stringify({
success: false,
errors: [{ message: `Invalid setting: "${setting}". Valid settings: ${SPEED_SETTINGS.join(', ')}` }]
}), { status: 400, headers: { 'Content-Type': 'application/json' } });
}
try {
const data = await cfPatch(cfHeaders, zoneId, setting, value);
if (data.success) {
const valueStr = typeof value === 'object' ? JSON.stringify(value) : value;
await logAudit(kv, username, `speed.${setting}`, `Set ${setting} to ${valueStr} (zone: ${zoneId})`);
await fireWebhook(kv, {
type: `speed.${setting}`,
username,
detail: `Set ${setting} to ${valueStr} (zone: ${zoneId})`
});
}
return new Response(JSON.stringify({
success: data.success,
result: data.result?.value ?? null,
errors: data.errors || []
}), {
status: data.success ? 200 : 400,
headers: { 'Content-Type': 'application/json' }
});
} catch (e) {
return new Response(JSON.stringify({
success: false,
errors: [{ message: e.message || `Failed to update ${setting}` }]
}), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
}
return new Response(JSON.stringify({
success: false,
errors: [{ message: `Unknown action: "${action}". Valid actions: enable_all, disable_all, update` }]
}), { status: 400, headers: { 'Content-Type': 'application/json' } });
}