support for OPTIONS method
Massimo Melina committed
Dec 23, 2021 at 16:32 UTC
7f9c84bc1dd7ca698f2af03d03bb8c729b126cac
4 files changed
+24
-5
src/const.ts
+3
@@ -10,3 +10,6 @@ export const FRONTEND_URI = SPECIAL_URI + 'front/'
10
export const API_URI = SPECIAL_URI + 'api/'
11
12
export const argv = minimist(process.argv.slice(2))
13
+
14
+export const METHOD_NOT_ALLOWED = 405
15
+export const NO_CONTENT = 204
src/index.ts
+2
-2
@@ -37,7 +37,7 @@ srv.use(mount(API_URI, new Koa()
37
const serveFrontendPrefixed = mount(FRONTEND_URI.slice(0,-1), serveFrontend)
38
srv.use(async (ctx, next) => {
39
const { path } = ctx
40
- if (ctx.method !== 'GET' || ctx.body)
40
+ if (ctx.body)
41
return await next()
42
if (path.startsWith(FRONTEND_URI))
43
return await serveFrontendPrefixed(ctx,next)
@@ -48,7 +48,7 @@ srv.use(async (ctx, next) => {
48
if (!source || await isDirectory(source)) { // this folder was requested without the trailing /
49
ctx.set({ server:'HFS '+BUILD_TIMESTAMP })
50
return path.endsWith('/') ? await serveFrontend(ctx, next)
51
- : ctx.redirect(ctx.path + '/')
51
+ : ctx.redirect(path + '/')
52
}
53
if (source)
54
return source.includes('//') ? mount(path,proxy(source,{}))(ctx,next)
src/serveFile.ts
+9
-1
@@ -1,11 +1,19 @@
1
import Koa from 'koa'
2
import { createReadStream } from 'fs'
3
import fs from 'fs/promises'
4
+import { METHOD_NOT_ALLOWED, NO_CONTENT } from './const'
5
6
export function serveFile(source: string) : Koa.Middleware {
7
return async (ctx) => {
8
const { range } = ctx.request.header
9
ctx.set('Accept-Ranges', 'bytes')
10
+ if (ctx.method === 'OPTIONS') {
11
+ ctx.status = NO_CONTENT
12
+ ctx.set({ Allow: 'OPTIONS, GET' })
13
+ return
14
+ }
15
+ if (ctx.method !== 'GET')
16
+ return ctx.status = METHOD_NOT_ALLOWED
17
if (!range)
18
return ctx.body = createReadStream(source)
19
const ranges = range.split('=')[1]
@@ -28,4 +36,4 @@ export function serveFile(source: string) : Koa.Middleware {
36
ctx.set('Content-Range', `bytes ${start}-${end}/${stat.size}`)
37
ctx.body = createReadStream(source, { start, end })
38
}
31
-}
\ No newline at end of file
39
+}
src/serveFrontend.ts
+10
-2
@@ -2,13 +2,14 @@ import proxy from 'koa-better-http-proxy'
2
import Koa from 'koa'
3
import mime from 'mime-types'
4
import { createReadStream, readFile } from 'fs'
5
-import { DEV, FRONTEND_URI } from './const'
5
+import { DEV, FRONTEND_URI, METHOD_NOT_ALLOWED, NO_CONTENT } from './const'
6
7
export const serveFrontend = DEV ? serveProxyFrontend() : serveStaticFrontend()
8
9
function serveProxyFrontend() {
10
console.debug('fronted: proxied')
11
return proxy('localhost:3000', {
12
+ filter: ctx => ctx.method === 'GET' || (ctx.status = METHOD_NOT_ALLOWED) && false,
13
proxyReqPathResolver: (ctx) => ctx.path.endsWith('/') ? '/' : ctx.path,
14
userResDecorator: (res, data, req) => {
15
return req.url.endsWith('/') ? replaceFrontEndRes(data.toString('utf8'))
@@ -20,7 +21,14 @@ function serveProxyFrontend() {
21
function serveStaticFrontend() : Koa.Middleware {
22
const BASE = __dirname + (DEV ? '/../dist' : '') + '/frontend/'
23
return async (ctx, next) => {
23
- let { path } = ctx
24
+ let { path, method } = ctx
25
+ if (method === 'OPTIONS') {
26
+ ctx.status = NO_CONTENT
27
+ ctx.set({ Allow: 'OPTIONS, GET' })
28
+ return
29
+ }
30
+ if (method !== 'GET')
31
+ return ctx.status = METHOD_NOT_ALLOWED
32
if (path.endsWith('/')) {
33
const res = await filePromise(BASE + 'index.html')
34
ctx.body = replaceFrontEndRes(res.toString('utf8'))