interrupt directory walking if request was aborted

Massimo Melina committed Dec 28, 2021 at 21:06 UTC e4850d3529b06acfae463ceeb04da8dec693e4d0
2 files changed +9 -7
src/apis.ts
+3 -4
@@ -2,7 +2,7 @@ import Koa from 'koa'
2 import { vfs, VfsNode, walkNode } from './vfs'
3 import { stat } from 'fs/promises'
4 import _ from 'lodash'
5 -import { getCurrentUsername, getCurrentUsernameExpanded, updateAccount, verifyLogin } from './perm'
5 +import { getCurrentUsername, updateAccount, verifyLogin } from './perm'
6 import createSSE from './sse'
7 import { basename } from 'path'
8
@@ -48,8 +48,7 @@ export const frontEndApis: ApiHandlers = {
48 limit = Number(limit)
49 const re = new RegExp(_.escapeRegExp(search),'i')
50 const match = (s?:string) => !s || !search || re.test(s)
51 - const who = await getCurrentUsernameExpanded(ctx) // cache value
52 - const walker = walkNode(node, who, search ? Infinity : 0)
51 + const walker = walkNode(node, ctx, search ? Infinity : 0)
52 const sseSrv = sse ? createSSE(ctx) : null
53 const res = produceEntries()
54 return !sseSrv && { list: await res }
@@ -58,7 +57,7 @@ export const frontEndApis: ApiHandlers = {
57 const list = []
58 const h = sseSrv && setInterval(()=> console.log('WALKING'), 500)
59 for await (const sub of walker) {
61 - if (sseSrv?.stopped) break
60 + if (sseSrv?.stopped || ctx.aborted) break
61 const filename = basename(sub.name||'')
62 if (!match(filename))
63 continue
src/vfs.ts
+6 -3
@@ -99,15 +99,16 @@ export function forbidden(node:VfsNode, users:string[]) {
99 }
100
101
102 -export async function* walkNode(parent:VfsNode, who:string[], depth:number=0, prefixPath:string=''): AsyncIterableIterator<VfsNode> {
102 +export async function* walkNode(parent:VfsNode, ctx: Koa.Context, depth:number=0, prefixPath:string=''): AsyncIterableIterator<VfsNode> {
103 const { children, source } = parent
104 + ctx._who = ctx._who || await getCurrentUsernameExpanded(ctx) // cache value
105 if (children)
106 for (const c of children) {
106 - if (c.hidden || forbidden(c, who))
107 + if (c.hidden || forbidden(c, ctx._who))
108 continue
109 yield prefixPath ? { ...c, name: prefixPath+c.name } : c
110 if (depth > 0 && c)
110 - yield* walkNode(c, who, depth - 1, prefixPath+c.name+'/')
111 + yield* walkNode(c, ctx, depth - 1, prefixPath+c.name+'/')
112 }
113 if (!source)
114 return
@@ -122,6 +123,8 @@ export async function* walkNode(parent:VfsNode, who:string[], depth:number=0, pr
123 ignore,
124 })
125 for await (let path of dirStream) {
126 + if (ctx.req.aborted)
127 + return
128 if (path instanceof Buffer)
129 path = path.toString('utf8')
130 const name = path.slice(base.length)