Liste eines Ordners, mit Token -- fuer Aufrufer, die die Namen nicht kennen
GET /api/liste?ordner=clothing nennt alle Pfade darin (mit Unterordnern). /api/fehlende braucht die Namen, und die kennt beim Fotostudio nur der Spiel-Client -- die Kleidungsnamen entstehen dort aus Natives. Statt 8.000 Namen ueber ein Netzereignis zum Server zu schicken, holt der Server die Liste, und das Studio prueft selbst. Schreibweise genau (substr statt LIKE, das in SQLite fuer ASCII schreibweisenblind ist). Ohne Ordnerfessel wie /exists. Gekappt bei 100.000 mit `gekappt: true` daneben. Geprueft gegen eine DB-Kopie im eigenen Container: 401 ohne Token, 400 ohne ordner und mit ../, clothing 2591 Pfade und deckungsgleich mit /api/fehlende, 'Clothing' (gross) leer, items enthaelt items/WEAPON_PISTOL.png. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6677b559f2
commit
c8080fb2eb
2 files changed
+66
No files matched your search
@@ -144,6 +144,7 @@ uploadRoutes.use('/media/*', requireToken)
|
||||
// soll.
|
||||
uploadRoutes.use('/zugang', requireToken)
|
||||
uploadRoutes.use('/fehlende', requireToken)
|
||||
uploadRoutes.use('/liste', requireToken)
|
||||
uploadRoutes.use('/exists', requireToken)
|
||||
uploadRoutes.use('/exists/*', requireToken)
|
||||
|
||||
@@ -489,6 +490,53 @@ uploadRoutes.get('/zugang', (c) => {
|
||||
* Kein .webp/.png am Ende der Adresse -- die Proxy-Falle von /exists/<pfad>
|
||||
* (siehe unten) kann hier nicht zuschnappen.
|
||||
*/
|
||||
/** Was liegt in einem Ordner -- die Liste, nicht die Frage nach Namen.
|
||||
*
|
||||
* WOZU, ergaenzt am 03.10.2026. /api/fehlende braucht die NAMEN, und die
|
||||
* kennt beim Fotostudio nur der Spiel-Client: die Kleidungsnamen entstehen
|
||||
* dort aus Natives, je Textur eines. Sie zum Server zu schicken hiesse rund
|
||||
* 8.000 Namen ueber ein Netzereignis. Umgekehrt ist es eine Anfrage: der
|
||||
* Dienst sagt, was liegt, und das Studio prueft jeden Namen selbst.
|
||||
*
|
||||
* SCHREIBWEISE GENAU, wie ueberall: `substr(...) = ?` und nicht LIKE --
|
||||
* LIKE ist in SQLite fuer ASCII schreibweisenblind und naehme
|
||||
* `Clothing/...` mit in `clothing/`.
|
||||
*
|
||||
* Mit Unterordnern (felgen/<radtyp>/<nummer> wird einer sein). Ohne
|
||||
* Ordnerfessel, wie /exists: alles hier ist ueber /f/ ohnehin abrufbar.
|
||||
*
|
||||
* GEKAPPT bei LISTE_HOECHSTENS, und dann steht `gekappt: true` daneben --
|
||||
* eine abgeschnittene Liste darf nicht als vollstaendige durchgehen, sonst
|
||||
* meldet der Aufrufer alles dahinter als fehlend.
|
||||
*/
|
||||
const LISTE_HOECHSTENS = 100_000
|
||||
|
||||
uploadRoutes.get('/liste', (c) => {
|
||||
const roh = (c.req.query('ordner') ?? '').trim().replace(/^\/+|\/+$/g, '')
|
||||
if (!roh) return c.json({ error: 'Abfrage "ordner" fehlt, z. B. ?ordner=clothing' }, 400)
|
||||
let ordner: string
|
||||
try {
|
||||
ordner = checkPath(roh)
|
||||
} catch (err) {
|
||||
return c.json({ error: err instanceof PathError ? err.message : 'Ordner unbrauchbar' }, 400)
|
||||
}
|
||||
const praefix = ordner + '/'
|
||||
const gesamt = (
|
||||
db
|
||||
.prepare('SELECT count(*) AS n FROM media WHERE substr(path, 1, ?) = ?')
|
||||
.get(praefix.length, praefix) as { n: number }
|
||||
).n
|
||||
const pfade = (
|
||||
db
|
||||
.prepare(
|
||||
'SELECT path FROM media WHERE substr(path, 1, ?) = ? ORDER BY path LIMIT ?',
|
||||
)
|
||||
.all(praefix.length, praefix, LISTE_HOECHSTENS) as { path: string }[]
|
||||
).map((z) => z.path)
|
||||
|
||||
return c.json({ ordner, gesamt, gekappt: pfade.length < gesamt, pfade })
|
||||
})
|
||||
|
||||
uploadRoutes.post('/fehlende', async (c) => {
|
||||
let body: { muster?: unknown; namen?: unknown } | null = null
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user