fix: logs: bad file name was registered for PUT requests
Massimo Melina committed
Dec 20, 2023 at 16:24 UTC
c0f6678e49ae7e0d186a13c5ce80820d7eddd3df
4 files changed
+18
-10
admin/src/LogsPage.ts
+6
-4
@@ -4,7 +4,7 @@ import { createElement as h, Fragment, useMemo, useState } from 'react';
4
import { Box, Tab, Tabs, Tooltip } from '@mui/material'
5
import { API_URL, useApiList } from './api'
6
import { DataTable } from './DataTable'
7
-import { Dict, formatBytes, HTTP_UNAUTHORIZED, prefix, shortenAgent, tryJson } from '@hfs/shared'
7
+import { Dict, formatBytes, HTTP_UNAUTHORIZED, prefix, shortenAgent, splitAt, tryJson } from '@hfs/shared'
8
import { logLabels } from './OptionsPage'
9
import { Flex, typedKeys, useBreakpoint, usePauseButton, useToggleButton } from './misc';
10
import { GridColDef } from '@mui/x-data-grid'
@@ -49,7 +49,7 @@ function LogFile({ file, pause, showApi }: { file: string, pause?: boolean, show
49
if (extra?.ua && !showAgent)
50
setShowAgent(true)
51
x.notes = extra?.dl ? "fully downloaded"
52
- : extra?.ul ? "uploaded " + formatBytes(extra.size)
52
+ : (x.method === 'PUT' || extra?.ul) ? "uploaded " + formatBytes(extra.size)
53
: x.status === HTTP_UNAUTHORIZED && x.uri?.startsWith(API_URL + 'loginSrp') ? "login failed" + prefix(':\n', extra?.u)
54
: x.notes
55
return x
@@ -162,9 +162,11 @@ function LogFile({ file, pause, showApi }: { file: string, pause?: boolean, show
162
minWidth: 100,
163
mergeRender: { other: 'method', fontSize: 'small' },
164
renderCell: ({ value, row }) => {
165
- if (row.extra?.ul)
166
- return row.extra?.ul
165
value = decodeURIComponent(value)
166
+ const ul = row.extra?.ul
167
+ if (ul)
168
+ return typeof ul === 'string' ? ul // legacy pre-0.51
169
+ : splitAt('?', value)[0] + ul.join(' + ')
170
if (!value.startsWith(API_URL))
171
return value
172
const ofs = API_URL.length
src/log.ts
+1
-1
@@ -107,7 +107,7 @@ export const logMw: Koa.Middleware = async (ctx, next) => {
107
const length = ctx.state.length ?? ctx.length
108
const uri = ctx.originalUrl
109
ctx.logExtra(ctx.state.includesLastByte && ctx.vfsNode && ctx.res.finished && { dl: 1 }
110
- || ctx.state.uploadPath && { ul: ctx.state.uploadPath, size: ctx.state.uploadSize })
110
+ || ctx.state.uploadSize !== undefined && { size: ctx.state.uploadSize, ul: ctx.state.uploads })
111
const conn = getConnection(ctx)
112
if (conn?.country)
113
ctx.logExtra({ country: conn.country })
src/middlewares.ts
+11
-3
@@ -13,7 +13,7 @@ import { zipStreamFromFolder } from './zip'
13
import { serveFile, serveFileNode } from './serveFile'
14
import { serveGuiFiles } from './serveGuiFiles'
15
import mount from 'koa-mount'
16
-import { Readable } from 'stream'
16
+import { Readable, Writable } from 'stream'
17
import { applyBlock } from './block'
18
import { Account, accountCanLogin, getAccount } from './perm'
19
import { socket2connection, updateConnection, normalizeIp, disconnect, Connection } from './connections'
@@ -99,6 +99,7 @@ export const serveGuiAndSharedFiles: Koa.Middleware = async (ctx, next) => {
99
const folder = await urlToNode(dirname(decPath), ctx, vfs, v => rest = v+'/'+rest)
100
if (!folder)
101
return sendErrorPage(ctx, HTTP_NOT_FOUND)
102
+ ctx.state.uploadPath = decPath
103
const dest = uploadWriter(folder, rest, ctx)
104
if (dest) {
105
await pipeline(ctx.req, dest)
@@ -115,11 +116,16 @@ export const serveGuiAndSharedFiles: Koa.Middleware = async (ctx, next) => {
116
if (ctx.request.type !== 'multipart/form-data')
117
return ctx.status = HTTP_BAD_REQUEST
118
ctx.body = {}
119
+ ctx.state.uploads = []
120
const form = formidable({
121
maxFileSize: Infinity,
122
allowEmptyFiles: true,
121
- //@ts-ignore wrong in the .d.ts file
122
- fileWriteStreamHandler: f => uploadWriter(node, f.originalFilename, ctx)
123
+ fileWriteStreamHandler: f => {
124
+ const fn = (f as any).originalFilename
125
+ ctx.state.uploadPath = decodeURI(ctx.path) + fn
126
+ ctx.state.uploads!.push(fn)
127
+ return uploadWriter(node!, fn, ctx) || new Writable()
128
+ }
129
})
130
return new Promise<void>(res => form.parse(ctx.req, err => {
131
if (err) console.error(String(err))
@@ -256,6 +262,8 @@ declare module "koa" {
262
connection: Connection
263
serveApp?: boolean // please, serve the frontend app
264
browsing?: string // for admin/monitoring
265
+ uploadPath?: string // current one
266
+ uploads?: string[] // in case of request with potentially multiple uploads (POST), we register all filenames (no full path)
267
}
268
}
269
export const paramsDecoder: Koa.Middleware = async (ctx, next) => {
src/upload.ts
-2
@@ -132,7 +132,6 @@ export function uploadWriter(base: VfsNode, path: string, ctx: Koa.Context) {
132
const conn = socket2connection(ctx.socket)
133
if (!conn) return ()=>{}
134
const opTotal = reqSize + resume
135
- ctx.state.uploadPath = ctx.path + path
135
ctx.state.uploadSize = opTotal
136
updateConnection(conn, { ctx, op: 'upload', opTotal, opOffset: resume / opTotal })
137
const h = setInterval(() => {
@@ -169,6 +168,5 @@ export function uploadWriter(base: VfsNode, path: string, ctx: Koa.Context) {
168
declare module "koa" {
169
interface DefaultState {
170
uploadSize?: number
172
- uploadPath?: string
171
}
172
}
\ No newline at end of file