fix: (regression 0.52.6) reverse-proxy with prefix was not working without roots
Massimo Melina committed
May 12, 2024 at 17:04 UTC
4b8a7f4266f687d6e9bce2a662f96d99cd64de7d
1 file changed
+18
-15
src/roots.ts
+18
-15
@@ -1,5 +1,5 @@
1
import { defineConfig } from './config'
2
-import { ADMIN_URI, API_URI, CFG, isLocalHost, makeMatcher, removeStarting, SPECIAL_URI } from './misc'
2
+import { ADMIN_URI, API_URI, Callback, CFG, isLocalHost, makeMatcher, removeStarting, SPECIAL_URI } from './misc'
3
import Koa from 'koa'
4
import { disconnect } from './connections'
5
import _ from 'lodash'
@@ -21,10 +21,11 @@ export const rootsMiddleware: Koa.Middleware = (ctx, next) =>
21
let params: undefined | typeof ctx.state.params | typeof ctx.query // undefined if we are not going to work on api parameters
22
if (ctx.path.startsWith(SPECIAL_URI)) { // special uris should be excluded...
23
if (!ctx.path.startsWith(API_URI)) return // ...unless it's an api
24
+ params = ctx.state.params || ctx.query // for api we'll translate params
25
+ changeUriParams(v => removeStarting(ctx.state.revProxyPath, v)) // removal must be done before adding the root
26
let { referer } = ctx.headers
27
referer &&= new URL(referer).pathname
28
if (referer?.startsWith(ctx.state.revProxyPath + ADMIN_URI)) return // exclude apis for admin-panel
27
- params = ctx.state.params || ctx.query // for api we'll translate params
29
}
30
if (_.isEmpty(roots.get())) return
31
const host2root = roots.compiled()
@@ -36,20 +37,22 @@ export const rootsMiddleware: Koa.Middleware = (ctx, next) =>
37
disconnect(ctx, 'bad-domain')
38
return true // true will avoid calling next
39
}
39
- if (!params) {
40
- ctx.path = join(root, ctx.path, '')
41
- return
42
- }
43
- for (const [k,v] of Object.entries(params))
44
- if (k.startsWith('uri'))
45
- params[k] = Array.isArray(v) ? v.map(x => join(root, x)) : join(root, v)
40
+ changeUriParams(v => join(root, v))
41
+ if (!params)
42
+ ctx.path = join(root, ctx.path)
43
47
- function join(a: string, b: any, removePrefix=ctx.state.revProxyPath) {
48
- return a + (b && b[0] !== '/' ? '/' : '')
49
- + removeStarting(removePrefix, b) // removal must be done before adding the root
44
+ function changeUriParams(cb: Callback<string, string>) {
45
+ if (!params) return
46
+ for (const [k, v] of Object.entries(params))
47
+ if (k.startsWith('uri'))
48
+ params[k] = Array.isArray(v) ? v.map(cb) : cb(v)
49
}
50
})() || next()
51
53
-function join(a: string, b: any) {
54
- return a + (b && b[0] !== '/' ? '/' : '') + b
55
-}
\ No newline at end of file
52
+function join(a: string, b: string, joiner='/') { // similar to path.join but OS independent
53
+ if (!b) return a
54
+ if (!a) return b
55
+ const ends = a.at(-1) === joiner
56
+ const starts = b[0] === joiner
57
+ return a + (!ends && !starts ? joiner + b : ends && starts ? b.slice(1) : b)
58
+}