1 |
|
2 | 'use strict'
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | const Boom = require('boom')
|
19 | const Hapi = require('hapi')
|
20 | const pify = require('pify')
|
21 |
|
22 | const apis = require('./apis.js')
|
23 | const handlers = require('./handlers.js')
|
24 | const values = require('./values.js')
|
25 | const wrapper = require('./wrapper.js')
|
26 |
|
27 | function normaliseHapiCors (
|
28 | cors /* : CorsConfiguration | false */
|
29 | ) /* : HapiCorsConfiguration | false */ {
|
30 | if (!cors) {
|
31 | return false
|
32 | }
|
33 | return {
|
34 | credentials: cors.credentials,
|
35 | exposedHeaders: cors.exposedHeaders,
|
36 | headers: cors.headers,
|
37 | maxAge: cors.maxAge,
|
38 | origin: cors.origins
|
39 | }
|
40 | }
|
41 |
|
42 |
|
43 | function normaliseHapiRequest (
|
44 | request /* : any */,
|
45 | params /* : { [id:string]: string } */
|
46 | ) /* : BmRequest */ {
|
47 | const urlInfo = Object.assign({}, request.url, {
|
48 | host: request.info.host,
|
49 | hostname: request.info.hostname,
|
50 | params,
|
51 | protocol: wrapper.protocolFromHeaders(request.headers)
|
52 | })
|
53 | delete urlInfo.auth
|
54 | delete urlInfo.hash
|
55 | delete urlInfo.href
|
56 | delete urlInfo.path
|
57 | delete urlInfo.port
|
58 | delete urlInfo.search
|
59 | delete urlInfo.slashes
|
60 | return {
|
61 | body: request.payload,
|
62 | headers: request.headers,
|
63 | method: request.method,
|
64 | route: '',
|
65 | url: urlInfo
|
66 | }
|
67 | }
|
68 |
|
69 | function startServer (
|
70 | logger/* : typeof console */,
|
71 | options /* : {
|
72 | cors: CorsConfiguration | false,
|
73 | cwd: string,
|
74 | port: string | number
|
75 | } */
|
76 | ) {
|
77 | options = options || {}
|
78 | const server = new Hapi.Server()
|
79 | server.connection({ port: options.port })
|
80 |
|
81 | server.route({
|
82 | config: {
|
83 | cors: normaliseHapiCors(options.cors)
|
84 | },
|
85 | handler (request, reply) {
|
86 |
|
87 | const cwd = options.cwd
|
88 | const route = request.params.route
|
89 | if (!route) {
|
90 | reply(Boom.notImplemented('Must supply a route'))
|
91 | return
|
92 | }
|
93 |
|
94 | apis.getRouteConfig(cwd, route)
|
95 | .catch((err) => Promise.reject(Boom.wrap(err, 404)))
|
96 | .then((routeConfig) => {
|
97 | return apis.getHandlerConfig(routeConfig, request.method)
|
98 | .then((handlerConfig) => {
|
99 | const handler = handlerConfig.handler
|
100 | if (typeof handler !== 'function') {
|
101 | reply(Boom.methodNotAllowed(`${request.method.toUpperCase()} method has not been implemented`))
|
102 | return
|
103 | }
|
104 | const bmRequest = normaliseHapiRequest(request, handlerConfig.params)
|
105 | bmRequest.route = routeConfig.route
|
106 | return handlers.executeHandler(handler, bmRequest)
|
107 | .then((bmResponse) => {
|
108 | const jsonResult = JSON.stringify(bmResponse.payload, null, 2)
|
109 | const response = reply(null, jsonResult)
|
110 | .code(bmResponse.statusCode)
|
111 | .type('application/json')
|
112 | Object.keys(bmResponse.headers).forEach((key) => response.header(key, bmResponse.headers[key]))
|
113 | })
|
114 | })
|
115 | })
|
116 | .catch((err) => {
|
117 | if (!err || !err.isBoom) {
|
118 | err = Boom.wrap(err, 500)
|
119 | }
|
120 |
|
121 |
|
122 | err.output.payload.message = err.message
|
123 |
|
124 | logger.error(err.stack)
|
125 | if (err.data) {
|
126 | logger.error('Boom Data:', JSON.stringify(err.data, null, 2))
|
127 | }
|
128 | reply(err)
|
129 | })
|
130 | },
|
131 |
|
132 | method: values.METHODS.filter((method) => method !== 'OPTIONS'),
|
133 | path: '/{route*}'
|
134 | })
|
135 |
|
136 | return server.register({
|
137 | register: require('good'),
|
138 | options: {
|
139 | ops: false,
|
140 | reporters: {
|
141 | console: [{
|
142 | module: 'good-console'
|
143 | }, 'stdout']
|
144 | }
|
145 | }
|
146 | })
|
147 | .then(() => pify(server.start.bind(server))())
|
148 | .then(() => server)
|
149 | }
|
150 |
|
151 | module.exports = {
|
152 | normaliseHapiCors,
|
153 | normaliseHapiRequest,
|
154 | startServer
|
155 | }
|