From 23c976ab07cee6a2ff2dfe1c28cd34c243c59933 Mon Sep 17 00:00:00 2001 From: xmanrui <841206367@qq.com> Date: Tue, 18 Aug 2026 20:35:08 +0800 Subject: [PATCH] docs: serve uncached random readme badge --- .gitignore | 1 + README.en.md | 2 +- README.md | 2 +- test/random-badge-worker.test.mjs | 55 ++++++++++++++++++++++++++++ worker/random-badge.mjs | 61 +++++++++++++++++++++++++++++++ wrangler.jsonc | 8 ++++ 6 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 test/random-badge-worker.test.mjs create mode 100644 worker/random-badge.mjs create mode 100644 wrangler.jsonc diff --git a/.gitignore b/.gitignore index 013b8d8..7f6a831 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules/ +.wrangler/ coverage/ .env .env.* diff --git a/README.en.md b/README.en.md index afb83e7..5550025 100644 --- a/README.en.md +++ b/README.en.md @@ -8,7 +8,7 @@

MIT license DeepSeek Harness - 滑动变祖器:今天是梁子或今天是梁圣(随机) + 滑动变祖器:今天是梁子或今天是梁圣(随机)

简体中文 · English

diff --git a/README.md b/README.md index f28d2a6..2e3497e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@

MIT 许可证 DeepSeek Harness - 滑动变祖器:今天是梁子或今天是梁圣(随机) + 滑动变祖器:今天是梁子或今天是梁圣(随机)

简体中文 · English

diff --git a/test/random-badge-worker.test.mjs b/test/random-badge-worker.test.mjs new file mode 100644 index 0000000..b3cb44b --- /dev/null +++ b/test/random-badge-worker.test.mjs @@ -0,0 +1,55 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; + +import worker, { + createBadgeResponse, + pickBadgeValue, + renderBadge, +} from '../worker/random-badge.mjs'; + +test('random badge selects both supported values at the sample boundary', () => { + assert.equal(pickBadgeValue(() => 0), '今天是梁子'); + assert.equal(pickBadgeValue(() => 0.499999), '今天是梁子'); + assert.equal(pickBadgeValue(() => 0.5), '今天是梁圣'); + assert.equal(pickBadgeValue(() => 0.999999), '今天是梁圣'); +}); + +test('random badge rejects invalid random samples and badge values', () => { + assert.throws(() => pickBadgeValue(() => -0.1), RangeError); + assert.throws(() => pickBadgeValue(() => 1), RangeError); + assert.throws(() => renderBadge('今天是别人'), RangeError); +}); + +test('random badge reproduces the Shields layout for either value', () => { + for (const value of ['今天是梁子', '今天是梁圣']) { + const svg = renderBadge(value); + + assert.match(svg, /width="130" height="20"/); + assert.match(svg, //); + assert.match(svg, //); + assert.match(svg, new RegExp(`滑动变祖器: ${value}`)); + } +}); + +test('worker returns a fresh SVG and explicitly disables every cache layer', async () => { + const response = await worker.fetch(new Request('https://badge.example/')); + const svg = await response.text(); + + assert.equal(response.status, 200); + assert.equal(response.headers.get('content-type'), 'image/svg+xml; charset=utf-8'); + assert.equal(response.headers.get('cache-control'), 'no-store, no-cache, must-revalidate, max-age=0'); + assert.equal(response.headers.get('cdn-cache-control'), 'no-store'); + assert.equal(response.headers.get('cloudflare-cdn-cache-control'), 'no-store'); + assert.equal(response.headers.get('surrogate-control'), 'no-store'); + assert.match(svg, /今天是梁(?:子|圣)/); +}); + +test('worker supports HEAD and rejects state-changing methods', async () => { + const headResponse = createBadgeResponse('HEAD'); + const postResponse = createBadgeResponse('POST'); + + assert.equal(headResponse.status, 200); + assert.equal(await headResponse.text(), ''); + assert.equal(postResponse.status, 405); + assert.equal(postResponse.headers.get('allow'), 'GET, HEAD'); +}); diff --git a/worker/random-badge.mjs b/worker/random-badge.mjs new file mode 100644 index 0000000..aa0013b --- /dev/null +++ b/worker/random-badge.mjs @@ -0,0 +1,61 @@ +const BADGE_LABEL = '滑动变祖器'; +const BADGE_VALUES = Object.freeze(['今天是梁子', '今天是梁圣']); + +function secureRandom() { + const sample = new Uint32Array(1); + crypto.getRandomValues(sample); + return sample[0] / 0x1_0000_0000; +} + +export function pickBadgeValue(random = secureRandom) { + const sample = random(); + + if (!Number.isFinite(sample) || sample < 0 || sample >= 1) { + throw new RangeError('Random samples must be finite numbers from 0 (inclusive) to 1 (exclusive).'); + } + + return BADGE_VALUES[Math.floor(sample * BADGE_VALUES.length)]; +} + +export function renderBadge(value) { + if (!BADGE_VALUES.includes(value)) { + throw new RangeError(`Unsupported badge value: ${value}`); + } + + const accessibleLabel = `${BADGE_LABEL}: ${value}`; + + return `${accessibleLabel}${BADGE_LABEL}${value}`; +} + +const NO_CACHE_HEADERS = { + 'Cache-Control': 'no-store, no-cache, must-revalidate, max-age=0', + 'CDN-Cache-Control': 'no-store', + 'Cloudflare-CDN-Cache-Control': 'no-store', + 'Content-Type': 'image/svg+xml; charset=utf-8', + Expires: '0', + Pragma: 'no-cache', + 'Surrogate-Control': 'no-store', + 'X-Content-Type-Options': 'nosniff', +}; + +export function createBadgeResponse(method = 'GET') { + if (method !== 'GET' && method !== 'HEAD') { + return new Response('Method Not Allowed', { + status: 405, + headers: { + ...NO_CACHE_HEADERS, + Allow: 'GET, HEAD', + 'Content-Type': 'text/plain; charset=utf-8', + }, + }); + } + + const body = method === 'HEAD' ? null : renderBadge(pickBadgeValue()); + return new Response(body, { headers: NO_CACHE_HEADERS }); +} + +export default { + fetch(request) { + return createBadgeResponse(request.method); + }, +}; diff --git a/wrangler.jsonc b/wrangler.jsonc new file mode 100644 index 0000000..b5bcd1d --- /dev/null +++ b/wrangler.jsonc @@ -0,0 +1,8 @@ +{ + "$schema": "https://raw.githubusercontent.com/cloudflare/workers-sdk/main/packages/wrangler/config-schema.json", + "name": "dsh-im-random-badge", + "main": "worker/random-badge.mjs", + "compatibility_date": "2026-08-18", + "workers_dev": true, + "preview_urls": false +}