better api error handling
Massimo Melina committed
Feb 13, 2023 at 10:04 UTC
43c2e779beb1ed1e341dab971ec34436129acce3
4 files changed
+17
-7
frontend/src/api.ts
+3
-3
@@ -15,12 +15,12 @@ export function apiCall(cmd: string, params?: Dict, options: ApiCallOptions={})
15
method: 'POST',
16
headers: { 'content-type': 'application/json' },
17
body: params && JSON.stringify(params),
18
- }).then(res => {
18
+ }).then(async res => {
19
stop?.()
20
if (res.ok)
21
return res.json()
22
- const msg = `Failed API ${cmd}: ${res.statusText}`
23
- console.warn(msg + (params ? ' ' + JSON.stringify(params) : ''))
22
+ const msg = await res.text() || `Failed API ${cmd}: ${res.statusText}`
23
+ console.warn(msg, params ? ' ' + JSON.stringify(params) : '')
24
throw new ApiError(res.status, msg)
25
}, err => {
26
stop?.()
frontend/src/dialog.ts
+1
-1
@@ -60,7 +60,7 @@ export async function alertDialog(msg: ReactElement | string | Error, type:Alert
60
type = 'error'
61
}
62
return new Promise(resolve => newDialog({
63
- className: 'dialog-alert-'+type,
63
+ className: 'dialog-alert dialog-alert-'+type,
64
title: _.capitalize(type),
65
icon: '!',
66
onClose: resolve,
frontend/src/index.scss
+4
@@ -272,6 +272,10 @@ button label {
272
.dialog-content {
273
padding: .2em; /* give space for focus outline */
274
}
275
+.dialog-alert .dialog-content {
276
+ text-Align: center;
277
+ & p { text-Align: left; display: inline-block; }
278
+}
279
280
.dialog {
281
min-width: 10em;
src/apiMiddleware.ts
+9
-3
@@ -28,8 +28,14 @@ export function apiMiddleware(apis: ApiHandlers) : Koa.Middleware {
28
}
29
const csrf = ctx.cookies.get('csrf')
30
// we don't rely on SameSite cookie option because it's https-only
31
- let res = csrf && csrf !== ctx.params.csrf ? new ApiError(HTTP_UNAUTHORIZED, 'csrf')
32
- : await apiFun(ctx.params || {}, ctx)
31
+ let res
32
+ try {
33
+ res = csrf && csrf !== ctx.params.csrf ? new ApiError(HTTP_UNAUTHORIZED, 'csrf')
34
+ : await apiFun(ctx.params || {}, ctx)
35
+ }
36
+ catch(e) {
37
+ res = e
38
+ }
39
if (isAsyncGenerator(res))
40
res = asyncGeneratorToReadable(res)
41
if (res instanceof Readable) { // Readable, we'll go SSE-mode
@@ -44,7 +50,7 @@ export function apiMiddleware(apis: ApiHandlers) : Koa.Middleware {
50
return ctx.status = res.status
51
}
52
if (res instanceof Error) { // generic exception
47
- ctx.body = String(res)
53
+ ctx.body = res.message || String(res)
54
return ctx.status = HTTP_BAD_REQUEST
55
}
56
ctx.body = res