码桶

发现社区成员的开源项目

cache.js5.2 KB
import { logAudit } from '../../_audit.js';
import { fireWebhook } from '../../_webhook.js';

export async function onRequestGet(context) {
    const { cfHeaders } = context.data;
    const { zoneId } = context.params;

    const response = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/development_mode`, {
        headers: {
            ...cfHeaders,
            'Content-Type': 'application/json'
        }
    });

    const data = await response.json();
    return new Response(JSON.stringify({
        success: data.success,
        development_mode: data.result ? {
            value: data.result.value,
            time_remaining: data.result.time_remaining || 0
        } : null,
        errors: data.errors || []
    }), {
        status: response.status,
        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 === 'toggle_dev_mode') {
        const newValue = body.value === 'on' ? 'on' : 'off';

        const response = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/development_mode`, {
            method: 'PATCH',
            headers: {
                ...cfHeaders,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ value: newValue })
        });

        const data = await response.json();
        if (data.success) {
            await logAudit(kv, username, 'cache.dev_mode', `Development mode set to ${newValue} (zone: ${zoneId})`);
            await fireWebhook(kv, {
                type: 'cache.dev_mode',
                username,
                detail: `Development mode set to ${newValue} (zone: ${zoneId})`
            });
        }
        return new Response(JSON.stringify({
            success: data.success,
            development_mode: data.result ? {
                value: data.result.value,
                time_remaining: data.result.time_remaining || 0
            } : null,
            errors: data.errors || []
        }), {
            status: response.status,
            headers: { 'Content-Type': 'application/json' }
        });
    }

    if (action === 'purge_all') {
        const response = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/purge_cache`, {
            method: 'POST',
            headers: {
                ...cfHeaders,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ purge_everything: true })
        });

        const data = await response.json();
        if (data.success) {
            await logAudit(kv, username, 'cache.purge_all', `Purged all cache (zone: ${zoneId})`);
            await fireWebhook(kv, {
                type: 'cache.purge_all',
                username,
                detail: `Purged all cache (zone: ${zoneId})`
            });
        }
        return new Response(JSON.stringify({
            success: data.success,
            errors: data.errors || []
        }), {
            status: response.status,
            headers: { 'Content-Type': 'application/json' }
        });
    }

    if (action === 'purge_urls') {
        const urls = body.urls;

        if (!Array.isArray(urls) || urls.length === 0) {
            return new Response(JSON.stringify({
                success: false,
                errors: [{ message: 'URLs array is required and must not be empty.' }]
            }), { status: 400, headers: { 'Content-Type': 'application/json' } });
        }

        if (urls.length > 30) {
            return new Response(JSON.stringify({
                success: false,
                errors: [{ message: 'Maximum 30 URLs per request (Cloudflare API limit).' }]
            }), { status: 400, headers: { 'Content-Type': 'application/json' } });
        }

        const response = await fetch(`https://api.cloudflare.com/client/v4/zones/${zoneId}/purge_cache`, {
            method: 'POST',
            headers: {
                ...cfHeaders,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ files: urls })
        });

        const data = await response.json();
        if (data.success) {
            await logAudit(kv, username, 'cache.purge_urls', `Purged ${urls.length} URL(s) (zone: ${zoneId})`);
            await fireWebhook(kv, {
                type: 'cache.purge_urls',
                username,
                detail: `Purged ${urls.length} URL(s) (zone: ${zoneId})`
            });
        }
        return new Response(JSON.stringify({
            success: data.success,
            purged_count: urls.length,
            errors: data.errors || []
        }), {
            status: response.status,
            headers: { 'Content-Type': 'application/json' }
        });
    }

    return new Response(JSON.stringify({
        success: false,
        errors: [{ message: `Unknown action: "${action}". Valid actions: toggle_dev_mode, purge_all, purge_urls` }]
    }), { status: 400, headers: { 'Content-Type': 'application/json' } });
}