read port from config file
Massimo Melina committed
Dec 27, 2021 at 00:01 UTC
d46386166fa46aeb88d0eb7dd4087b6fe6596b9e
6 files changed
+94
-10
config.yaml
new
+1
@@ -0,0 +1 @@
1
+port: 80
src/apis.ts
+1
-1
@@ -107,7 +107,7 @@ export const frontEndApis: ApiHandlers = {
107
async logout({}, ctx) {
108
const sid = ctx.cookies.get(SESSION_COOKIE)
109
if (!sid)
110
- return ctx.status = 404
110
+ return ctx.status = 401
111
if (!sessions.destroy(sid))
112
return ctx.status = 500
113
ctx.status = 200
src/config.ts
new
+30
@@ -0,0 +1,30 @@
1
+import EventEmitter from 'events'
2
+import { watchLoad } from './misc'
3
+
4
+const PATH = 'config.yaml'
5
+
6
+let state:Record<string,any> = {}
7
+const emitter = new EventEmitter()
8
+watchLoad(PATH, data => {
9
+ for (const k in data)
10
+ check(k)
11
+ for (const k in state)
12
+ if (!(k in data))
13
+ check(k)
14
+
15
+ function check(k: string) {
16
+ const oldV = state[k]
17
+ const newV = data[k]
18
+ if (JSON.stringify(newV) === JSON.stringify(oldV)) return
19
+ state[k] = newV
20
+ emitter.emit('new.'+k, newV, oldV)
21
+ }
22
+})
23
+
24
+export function subscribe(k:string, cb:(v:any,was:any)=>void) {
25
+ emitter.on('new.'+k, cb)
26
+}
27
+
28
+export function getConfig(k:string) {
29
+ return state[k]
30
+}
src/index.ts
+31
-8
@@ -9,20 +9,20 @@ import { vfs } from './vfs'
9
import { isDirectory } from './misc'
10
import proxy from 'koa-better-http-proxy'
11
import compress from 'koa-compress'
12
-
13
-const PORT = argv.port || 80
12
+import { Server } from 'http'
13
+import { subscribe } from './config'
14
15
const BUILD_TIMESTAMP = ""
16
17
-const srv = new Koa()
18
-srv.use(async (ctx, next) => {
17
+const app = new Koa()
18
+app.use(async (ctx, next) => {
19
// log all requests
20
console.debug(new Date().toLocaleTimeString(), ctx.request.method, ctx.url)
21
await next()
22
})
23
24
// serve apis
25
-srv.use(mount(API_URI, new Koa()
25
+app.use(mount(API_URI, new Koa()
26
.use(bodyParser())
27
.use(apiMw(frontEndApis))
28
.use(compress({
@@ -35,7 +35,7 @@ srv.use(mount(API_URI, new Koa()
35
36
// serve shared files and front-end files
37
const serveFrontendPrefixed = mount(FRONTEND_URI.slice(0,-1), serveFrontend)
38
-srv.use(async (ctx, next) => {
38
+app.use(async (ctx, next) => {
39
const { path } = ctx
40
if (ctx.body)
41
return await next()
@@ -63,9 +63,32 @@ srv.use(async (ctx, next) => {
63
await next()
64
})
65
66
-srv.on('error', err => {
66
+app.on('error', err => {
67
if (DEV && err.code === 'ENOENT' && err.path.endsWith('sockjs-node')) return // spam out
68
if (err.code === 'ECONNRESET') return // someone interrupted, don't care
69
console.error('server error', err)
70
})
71
-srv.listen(PORT, ()=> console.log('running on port', PORT, DEV, new Date().toLocaleString()))
71
+
72
+let srv: Server
73
+if (argv.port)
74
+ listenOn(argv.port).then()
75
+else
76
+ subscribe('port', port =>
77
+ listenOn(port||80))
78
+
79
+async function listenOn(port: number) {
80
+ await new Promise(resolve => {
81
+ if (!srv)
82
+ return resolve(null)
83
+ srv.close(err => {
84
+ if (err)
85
+ console.debug('failed to stop server', err)
86
+ resolve(err)
87
+ })
88
+ })
89
+ await new Promise(resolve =>
90
+ srv = app.listen(port, () => {
91
+ console.log('running on port', port, DEV, new Date().toLocaleString())
92
+ resolve(null)
93
+ }))
94
+}
src/misc.ts
+31
@@ -1,5 +1,7 @@
1
import fs from 'fs/promises'
2
import { objSameKeys } from './obj'
3
+import { watch } from 'fs'
4
+import yaml from 'yaml'
5
6
export function enforceFinal(sub:string, s:string) {
7
return s.endsWith(sub) ? s : s+sub
@@ -43,3 +45,32 @@ export async function readFileBusy(path: string): Promise<string> {
45
export function wantArray(x:any) {
46
return x == null ? [] : Array.isArray(x) ? x : [x]
47
}
48
+
49
+export function watchLoad(path:string, parser:(data:any)=>void|Promise<void>) {
50
+ let doing = false
51
+ const timer = setInterval(()=>{
52
+ try {
53
+ watch(path, load)
54
+ load().then()
55
+ clearInterval(timer)
56
+ }
57
+ catch(e){
58
+ }
59
+ }, 1000)
60
+
61
+ async function load(){
62
+ if (doing) return
63
+ doing = true
64
+ console.debug('loading', path)
65
+ let data: any
66
+ try {
67
+ data = yaml.parse(await readFileBusy(path))
68
+ } catch (e) {
69
+ doing = false
70
+ console.warn('cannot read', path, String(e))
71
+ return
72
+ }
73
+ await parser(data)
74
+ doing = false
75
+ }
76
+}
todo.md
-1
@@ -3,7 +3,6 @@
3
- folders before?
4
- upload
5
- log file
6
-- config: port
6
- config: mime
7
- node.comment
8
- streamable zip archives (no compression, resumable?)