forked from fastify/fastify
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfastify.js
162 lines (133 loc) · 3.72 KB
/
fastify.js
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
'use strict'
const wayfarer = require('wayfarer')
const urlUtil = require('url')
const stripUrl = require('pathname-match')
const jsonParser = require('body/json')
const pluginLoader = require('boot-in-the-arse')
const supportedMethods = ['GET', 'POST', 'PUT']
const validation = require('./lib/validation')
const buildSchema = validation.buildSchema
const validateSchema = validation.validateSchema
const serialize = validation.serialize
function build () {
const router = wayfarer('/404')
const map = new Map()
pluginLoader(fastify, {})
router.on('/404', defaultRoute)
// shorthand methods
fastify.get = get
fastify.post = post
fastify.put = put
// extended route
fastify.route = route
// plugin
fastify.register = fastify.use
return fastify
function fastify (req, res) {
router(stripUrl(req.url), req, res)
}
function get (url, schema, handler) {
return _route('GET', url, schema, handler)
}
function post (url, schema, handler) {
return _route('POST', url, schema, handler)
}
function put (url, schema, handler) {
return _route('PUT', url, schema, handler)
}
function _route (method, url, schema, handler) {
if (!handler && typeof schema === 'function') {
handler = schema
schema = {}
}
return route({ method, url, schema, handler })
}
function route (opts) {
if (supportedMethods.indexOf(opts.method) === -1) {
throw new Error(`${opts.method} method is not supported!`)
}
if (!opts.handler) {
throw new Error(`Missing handler function for ${opts.method}:${opts.url} route.`)
}
buildSchema(opts)
if (map.has(opts.url)) {
if (map.get(opts.url)[opts.method]) {
throw new Error(`${opts.method} already set for ${opts.url}`)
}
map.get(opts.url)[opts.method] = opts
} else {
const node = createNode(opts.url)
node[opts.method] = opts
map.set(opts.url, node)
}
return fastify
}
function bodyParsed (handle, params, req, res) {
function parsed (err, body) {
if (err) {
res.statusCode = 422
res.end()
return
}
handleNode(handle, params, req, res, body, null)
}
return parsed
}
function createNode (url) {
const node = {}
router.on(url, function handle (params, req, res) {
const handle = node[req.method]
if (handle && req.method === 'GET') {
handleNode(handle, params, req, res, null, urlUtil.parse(req.url, true).query)
} else if (handle && (req.method === 'POST' || req.method === 'PUT')) {
if (req.headers['content-type'] === 'application/json') {
jsonParser(req, bodyParsed(handle, params, req, res))
} else {
res.statusCode = 415
res.end()
}
} else {
res.statusCode = 404
res.end()
}
})
return node
}
function handleNode (handle, params, req, res, body, query) {
if (!handle) {
res.statusCode = 404
res.end()
}
const valid = validateSchema(handle, params, body, query)
if (valid !== true) {
res.statusCode = 400
res.end(valid)
return
}
const request = new Request(params, req, body, query)
handle.handler(request, reply)
function reply (err, statusCode, data) {
if (err) {
res.statusCode = 500
res.end()
}
if (!data) {
data = statusCode
statusCode = 200
}
res.statusCode = statusCode
res.end(serialize(handle, data))
}
}
function defaultRoute (params, req, res) {
res.statusCode = 404
res.end()
}
function Request (params, req, body, query) {
this.params = params
this.req = req
this.body = body
this.query = query
}
}
module.exports = build