Implement a simple Koa-like http server with zero dependencies from scratch.
THIS FRAMEWORK HAVE NOT BEEN STRICTLY TESTED, PLEASE DO NOT USE IT IN PRODUCTION ! 许多功能未经严格测试,请勿用于生产目的!
- Lightweight (0 dependency)
- TypeScript friendly
- Built-in body parser middleware
- Built-in response time middleware
If you're looking for the ultimate in minimal packages and high customization, you can install the following subpackages separately.
Of course, they are all included in the main package (@mutoe/koam
).
- Koam core package @mutoe/koam-core
- Router middleware @mutoe/koam-router
- Logger middleware @mutoe/koam-logger
import Koa from '@mutoe/koam'
import Router from '@mutoe/koam-router'
const app = new Koa()
const router = new Router()
router.post('/hello/:name', ctx => {
console.log(ctx.request.body) // You can get json request body directly
ctx.body = `Hello ${ctx.params.name}!`
})
app.use(router.routes())
app.listen(3000, () => console.log(`server is started at 3000...`))
See microsoft/Typescript#34523
app.use(async (ctx: Context, next) => {
// ^^^^^^^
const val: unknown = 1.2345
// ^^^^^^^
ctx.assert(typeof val === 'number', 500)
console.log(val.toFixed(2))
// ^^^ now val is number type
})
If you want to extend some property or method on the context or it's state, you can write the following code to extend it
// extend.d.ts
import User from './src/user'
declare global {
namespace Koa {
export interface State {
user?: User
}
}
}
export {}
// your-code.ts
app.use(ctx => {
console.log(ctx.state.user.name)
})
You can refer the koam-router
extend-koam.d.ts
for more example.
In order to reduce the package size, I don't have built-in cookie-related handling, as this is not required by all apps.
If you want to handle cookies, you can extend the middleware yourself, here is the cookies example steps:
-
install the
cookies
and@types/cookies
npm package -
add
koam.d.ts
in your appimport '@mutoe/koam' import type Cookies from 'cookies' declare module '@mutoe/koam' { interface Context { cookies: Cookies } } declare global { namespace Koa { // Others if you want extend interface State { user?: { id: number, email: string } } } } // Don't forgot this line export {}
-
register the cookies in your app
const app = new Koa() // init cookies before your middleware app.use((ctx, next) => { ctx.cookies = new Cookies(ctx.req, ctx.res, { secure: true }) return next() }) // your middlewares app.use(ctx => { ctx.cookies.set('key', 'value') ctx.cookies.get('key') })
The json body parser middleware is built-in, you can get the parsed body directly from ctx.request.body
.
But if you want to parse other types of body (like multipart/form-data), you can close built-in body parser and use the another middleware like formidable
-
install the
formidable
and@types/formidable
npm package -
add
koam.d.ts
in your appimport '@mutoe/koam' import type Cookies from 'cookies' declare module '@mutoe/koam' { interface Context { body?: any files?: formidable.File[] } interface Request { body?: any files?: formidable.File[] } } // Don't forgot this line export {}
-
register the formidable in your app
import { Fields, Files, formidable } from 'formidable' const app = new Koa({ customBodyParser: false, // this is not nessary, but it's better for performance }) app.use(async (ctx, next) => { const form = formidable() try { const [fields, files] = await form.parse(ctx.req) ctx.request.body = fields ctx.request.files = files } catch (error) { console.error('Cannot parse the request body', { error }) } await next() }) app.use(ctx => { console.log(ctx.request.body as Fields) console.log(ctx.files as Files) })