Skip to content

Commit

Permalink
✨ Add express middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
smoliji committed May 5, 2024
1 parent 4a57a6e commit acf9f57
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## [Unreleased]

### Added
- Express.js middleware

## [2.0.0-rc.2] 2024-05-04

### Added
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ curl http://localhost:46461/healthz --verbose | jq

### Guides

- [How to use with ExpressJS](./demo/express.ts)
- [How to use as ExpressJS middleware](./demo/express-mw.ts)
- [How to use Core with ExpressJS](./demo/express.ts)
31 changes: 31 additions & 0 deletions demo/express-mw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// To run demo: npx ts-node demo/express-mw.ts

import express from 'express'
import * as healthz from '../dist/index'

const app = express()

app.use((req, res, next) => {
healthz.express({
// Define checks
checks: [
{
id: 'PostgreSQL',
required: true,
fn: async () => new Promise((resolve) => setTimeout(resolve, 1000)),
},
{
id: 'Redis',
fn: async () => new Promise((resolve) => setTimeout(resolve, 10)),
},
],
// Make timeout configurable from the outside
timeout: parseInt(String(req.query.timeout)) || undefined,
// Modify the result if needed
transformResult: (x) => (console.log(x), x),
})(req, res, next)
})

const running = app.listen(process.env.PORT ?? 0)
const port = (running.address() as any).port
console.log(`Express app running on http://localhost:${port}/healthz`)
2 changes: 1 addition & 1 deletion demo/express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ app.use('/healthz', async (req, res, next) => {

const running = app.listen(process.env.PORT ?? 0)
const port = (running.address() as any).port
console.log(`Express app running on http://localhost:${port}`)
console.log(`Express app running on http://localhost:${port}/healthz`)
26 changes: 26 additions & 0 deletions src/express.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import test, { describe } from 'node:test'
import express from 'express'
import { middleware } from './express'
import { equal } from 'node:assert'
import { Result } from './healthz'
import { AddressInfo } from 'node:net'

describe('Express integration', () => {
test('Middleware', async () => {
const app = express()
app.use(middleware({
checks: [
{
id: 'a',
fn: async () => 1,
}
]
}))
const started = app.listen(0)
const response = await fetch(`http://localhost:${(started.address() as AddressInfo).port}/healthz`)
equal(response.status, 200)
started.close()
const body: Result = await response.json()
equal(body.status, 'OK')
})
})
50 changes: 50 additions & 0 deletions src/express.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { status } from '.'
import { check, Option as HOption, Result } from './healthz'
import { htmlResult, jsonResult } from './http'

export interface Option extends HOption {
transformResult?: (result: Result) => Result
}

type Request = {
header: (arg: string) => string | undefined
query: Record<string, any>
path: string
}

type Response = {
status: (status: number) => Response
type: (t: string) => any
end: (t: string) => any
json: (t: any) => any
}

export function middleware<Req extends Request, Res extends Response>(
option?: Option,
) {
const transformResult: Option['transformResult'] =
option?.transformResult ?? ((x) => x)
return async function healthzmw(req: Req, res: Res, next: any) {
try {
if (req.path !== '/healthz') {
return next()
}
const health = transformResult(
await check({
checks: option?.checks,
timeout: option?.timeout,
}),
)

res.status(status(health))
if (req.header('accept')?.includes('html')) {
res.type('html')
res.end(htmlResult(health))
} else {
res.json(jsonResult(health))
}
} catch (error) {
next(error)
}
}
}
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ export {
jsonResult as json,
resultStatusCode as status,
} from './http'
export {
middleware as express
} from './express'

0 comments on commit acf9f57

Please sign in to comment.