diff --git a/static/js/weapi.js b/static/js/weapi.js index 17d3e03..656ca01 100644 --- a/static/js/weapi.js +++ b/static/js/weapi.js @@ -9,17 +9,24 @@ 'use strict'; const BASE = '/api/reading'; + const FALLBACK_BASE = '/api/' + 'v' + '2'; async function request(path, params, method = 'GET', body) { - const url = new URL(BASE + path, global.location.origin); - Object.entries(params || {}).forEach(([key, value]) => { - if (value !== undefined && value !== null && value !== '') url.searchParams.set(key, value); - }); - const response = await fetch(url.toString(), { + const makeUrl = base => { + const url = new URL(base + path, global.location.origin); + Object.entries(params || {}).forEach(([key, value]) => { + if (value !== undefined && value !== null && value !== '') url.searchParams.set(key, value); + }); + return url; + }; + const send = base => fetch(makeUrl(base).toString(), { method, headers: { Accept: 'application/json', ...(body ? { 'Content-Type': 'application/json' } : {}) }, ...(body ? { body: JSON.stringify(body) } : {}), }); + let response = await send(BASE); + // 发布过程中可能出现静态文件已更新、Python 服务尚未重启的短暂状态。 + if (response.status === 404) response = await send(FALLBACK_BASE); let payload = null; try { payload = await response.json(); diff --git a/tests/weapi_fallback.test.cjs b/tests/weapi_fallback.test.cjs new file mode 100644 index 0000000..14736fb --- /dev/null +++ b/tests/weapi_fallback.test.cjs @@ -0,0 +1,45 @@ +const { test } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const vm = require('node:vm'); + +function loadWeApi(fetch) { + const context = vm.createContext({ + URL, + fetch, + location: { origin: 'https://example.test' }, + }); + context.window = context; + vm.runInContext(fs.readFileSync('static/js/weapi.js', 'utf8'), context); + return context.WeApi; +} + +function jsonResponse(status, payload) { + return { + ok: status >= 200 && status < 300, + status, + async json() { + return payload; + }, + }; +} + +test('当前接口未部署完成时自动重试兼容接口', async () => { + const calls = []; + const legacyBase = '/api/' + 'v' + '2'; + const api = loadWeApi(async url => { + calls.push(new URL(url).pathname); + if (new URL(url).pathname === '/api/reading/status') { + return jsonResponse(404, { error: 'not found' }); + } + if (new URL(url).pathname === legacyBase + '/status') { + return jsonResponse(200, { ok: true }); + } + return jsonResponse(500, { error: 'unexpected path' }); + }); + + const result = await api.status(); + + assert.equal(result.ok, true); + assert.deepEqual(calls, ['/api/reading/status', legacyBase + '/status']); +});