-
Notifications
You must be signed in to change notification settings - Fork 18
/
json-middleware.ts
63 lines (54 loc) · 1.57 KB
/
json-middleware.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import * as express from 'express'
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
import * as t from 'io-ts'
import { failure } from 'io-ts/PathReporter'
import * as H from '../src'
import * as M from '../src/Middleware'
import { fromRequestHandler, toRequestHandler } from '../src/express'
// Express middleware
const json = express.json()
const jsonMiddleware = fromRequestHandler(
json,
() => E.right(undefined),
(err) => String(err)
)
const Body = t.strict({
name: t.string,
})
const bodyDecoder = pipe(
jsonMiddleware,
M.ichain(() =>
M.decodeBody((u) =>
pipe(
Body.decode(u),
E.mapLeft((errors) => `invalid body: ${failure(errors).join('\n')}`)
)
)
)
)
function badRequest(message: string): M.Middleware<H.StatusOpen, H.ResponseEnded, never, void> {
return pipe(
M.status(H.Status.BadRequest),
M.ichain(() => M.closeHeaders()),
M.ichain(() => M.send(message))
)
}
const hello = pipe(
bodyDecoder,
M.ichain(({ name }) =>
pipe(
M.status<string>(H.Status.OK),
M.ichain(() => M.closeHeaders()),
M.ichain(() => M.send(`Hello ${name}!`))
)
),
M.orElse(badRequest)
)
const app = express()
app
.post('/', toRequestHandler(hello))
// tslint:disable-next-line: no-console
.listen(3000, () => console.log('Express listening on port 3000. Use: POST /'))
// curl --request POST --silent --header 'Content-Type: application/json' --data '{"name":"bob"}' "localhost:3000/"
// curl --request POST --silent --header 'Content-Type: application/json' --data '{}' "localhost:3000/"