release: v1.2.3 — 修复简短图片链接在按年/月存储下 404
ci / ci (22, ubuntu-latest) (push) Canceled after 0s
Publish Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Canceled after 0s
Publish Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Canceled after 0s
Publish Docker image / merge (push) Canceled after 0s
GitHub Release / release (push) Canceled after 0s

开启简短链接时纯文件名直链先经 SQLite 索引反查完整 key,不再误解析为扁平 images/文件名路径。
This commit is contained in:
O96u committed 2026-08-30 12:33:33 +08:00
1 parent c9c34515dd
commit 20afda5869
7 files changed
+57 -7

No files matched your search

+24 -3
View File
@@ -1,10 +1,31 @@
import { describe, expect, it } from 'vitest'
import { describe, expect, it, vi, afterEach } from 'vitest'
import { findImageKeyByDatePath, findImageKeyByFilename } from './image-index'
import { requestPathToImageKey } from './serve-image'
vi.mock('./image-index', async (importOriginal) => {
const actual = await importOriginal<typeof import('./image-index')>()
return {
...actual,
findImageKeyByFilename: vi.fn(actual.findImageKeyByFilename),
findImageKeyByDatePath: vi.fn(actual.findImageKeyByDatePath)
}
})
describe('requestPathToImageKey hide folder', () => {
it('resolves bare filename to default folder flat key', () => {
afterEach(() => {
vi.mocked(findImageKeyByFilename).mockReset()
vi.mocked(findImageKeyByDatePath).mockReset()
})
it('resolves bare filename via index when hide folder is enabled', () => {
vi.mocked(findImageKeyByFilename).mockReturnValue('images/2026/08/demo.webp')
expect(requestPathToImageKey('/demo.webp', { hideFolder: true }))
.toBe('images/demo.webp')
.toBe('images/2026/08/demo.webp')
})
it('does not guess flat images/name when hide folder is enabled', () => {
vi.mocked(findImageKeyByFilename).mockReturnValue(null)
expect(requestPathToImageKey('/demo.webp', { hideFolder: true })).toBeNull()
})
it('resolves hidden date path to default folder key', () => {
+8 -1
View File
@@ -8,7 +8,7 @@ import {
} from './env'
import { findImageKeyByDatePath, findImageKeyByFilename } from './image-index'
import { validateImageKey } from './image-key'
import { toStorageKeyFromPublicPath } from './image-public-path'
import { isBareImageFilename, toStorageKeyFromPublicPath } from './image-public-path'
import { buildPublicImageUrl } from './image-response'
import { createImageStream, headImage } from './storage'
import { getBackendRowForKey } from './storage/resolver'
@@ -85,6 +85,13 @@ export function requestPathToImageKey(
if (validateImageKey(raw)) return raw
// 简短链接:纯文件名须先走索引反查,不能猜成 images/文件名(与按年/月存储冲突)
if (options?.hideFolder && isBareImageFilename(raw)) {
const byFilename = findImageKeyByFilename(raw)
if (byFilename && validateImageKey(byFilename)) return byFilename
return null
}
const fromPublic = toStorageKeyFromPublicPath(raw)
if (fromPublic) return fromPublic