|
19 | 19 | // with non-HTTP trigger). |
20 | 20 | // - ANY (all methods) '/*' for executing functions (only for servers handling |
21 | 21 | // functions with HTTP trigger). |
22 | | - |
23 | | -// eslint-disable-next-line node/no-deprecated-api |
24 | | -import * as domain from 'domain'; |
25 | 22 | import * as express from 'express'; |
26 | 23 | import * as http from 'http'; |
27 | 24 | import {FUNCTION_STATUS_HEADER_FIELD} from './types'; |
28 | 25 | import {sendCrashResponse} from './logger'; |
29 | | -import {isBinaryCloudEvent, getBinaryCloudEventContext} from './cloudevents'; |
30 | | -import { |
31 | | - HttpFunction, |
32 | | - EventFunction, |
33 | | - EventFunctionWithCallback, |
34 | | - CloudEventFunction, |
35 | | - CloudEventFunctionWithCallback, |
36 | | -} from './functions'; |
37 | 26 |
|
38 | 27 | // We optionally annotate the express Request with a rawBody field. |
39 | 28 | // Express leaves the Express namespace open to allow merging of new fields. |
@@ -61,8 +50,13 @@ export const setLatestRes = (res: express.Response) => { |
61 | 50 | * @param err Error from function execution. |
62 | 51 | * @param res Express response object. |
63 | 52 | */ |
64 | | -// eslint-disable-next-line @typescript-eslint/no-explicit-any |
65 | | -function sendResponse(result: any, err: Error | null, res: express.Response) { |
| 53 | + |
| 54 | +export function sendResponse( |
| 55 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 56 | + result: any, |
| 57 | + err: Error | null, |
| 58 | + res: express.Response |
| 59 | +) { |
66 | 60 | if (err) { |
67 | 61 | res.set(FUNCTION_STATUS_HEADER_FIELD, 'error'); |
68 | 62 | // Sending error message back is fine for Pub/Sub-based functions as they do |
@@ -92,144 +86,6 @@ function sendResponse(result: any, err: Error | null, res: express.Response) { |
92 | 86 | } |
93 | 87 | } |
94 | 88 |
|
95 | | -/** |
96 | | - * Wraps the provided function into an Express handler function with additional |
97 | | - * instrumentation logic. |
98 | | - * @param execute Runs user's function. |
99 | | - * @return An Express handler function. |
100 | | - */ |
101 | | -export function makeHttpHandler(execute: HttpFunction): express.RequestHandler { |
102 | | - return (req: express.Request, res: express.Response) => { |
103 | | - const d = domain.create(); |
104 | | - // Catch unhandled errors originating from this request. |
105 | | - d.on('error', err => { |
106 | | - if (res.locals.functionExecutionFinished) { |
107 | | - console.error(`Exception from a finished function: ${err}`); |
108 | | - } else { |
109 | | - res.locals.functionExecutionFinished = true; |
110 | | - sendCrashResponse({err, res}); |
111 | | - } |
112 | | - }); |
113 | | - d.run(() => { |
114 | | - process.nextTick(() => { |
115 | | - execute(req, res); |
116 | | - }); |
117 | | - }); |
118 | | - }; |
119 | | -} |
120 | | - |
121 | | -/** |
122 | | - * Wraps cloudevent function (or cloudevent function with callback) in HTTP |
123 | | - * function signature. |
124 | | - * @param userFunction User's function. |
125 | | - * @return HTTP function which wraps the provided event function. |
126 | | - */ |
127 | | -export function wrapCloudEventFunction( |
128 | | - userFunction: CloudEventFunction | CloudEventFunctionWithCallback |
129 | | -): HttpFunction { |
130 | | - return (req: express.Request, res: express.Response) => { |
131 | | - const callback = process.domain.bind( |
132 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
133 | | - (err: Error | null, result: any) => { |
134 | | - if (res.locals.functionExecutionFinished) { |
135 | | - console.log('Ignoring extra callback call'); |
136 | | - } else { |
137 | | - res.locals.functionExecutionFinished = true; |
138 | | - if (err) { |
139 | | - console.error(err.stack); |
140 | | - } |
141 | | - sendResponse(result, err, res); |
142 | | - } |
143 | | - } |
144 | | - ); |
145 | | - let cloudevent = req.body; |
146 | | - if (isBinaryCloudEvent(req)) { |
147 | | - cloudevent = getBinaryCloudEventContext(req); |
148 | | - cloudevent.data = req.body; |
149 | | - } |
150 | | - // Callback style if user function has more than 1 argument. |
151 | | - if (userFunction!.length > 1) { |
152 | | - const fn = userFunction as CloudEventFunctionWithCallback; |
153 | | - return fn(cloudevent, callback); |
154 | | - } |
155 | | - |
156 | | - const fn = userFunction as CloudEventFunction; |
157 | | - Promise.resolve() |
158 | | - .then(() => { |
159 | | - const result = fn(cloudevent); |
160 | | - return result; |
161 | | - }) |
162 | | - .then( |
163 | | - result => { |
164 | | - callback(null, result); |
165 | | - }, |
166 | | - err => { |
167 | | - callback(err, undefined); |
168 | | - } |
169 | | - ); |
170 | | - }; |
171 | | -} |
172 | | - |
173 | | -/** |
174 | | - * Wraps event function (or event function with callback) in HTTP function |
175 | | - * signature. |
176 | | - * @param userFunction User's function. |
177 | | - * @return HTTP function which wraps the provided event function. |
178 | | - */ |
179 | | -export function wrapEventFunction( |
180 | | - userFunction: EventFunction | EventFunctionWithCallback |
181 | | -): HttpFunction { |
182 | | - return (req: express.Request, res: express.Response) => { |
183 | | - const event = req.body; |
184 | | - const callback = process.domain.bind( |
185 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
186 | | - (err: Error | null, result: any) => { |
187 | | - if (res.locals.functionExecutionFinished) { |
188 | | - console.log('Ignoring extra callback call'); |
189 | | - } else { |
190 | | - res.locals.functionExecutionFinished = true; |
191 | | - if (err) { |
192 | | - console.error(err.stack); |
193 | | - } |
194 | | - sendResponse(result, err, res); |
195 | | - } |
196 | | - } |
197 | | - ); |
198 | | - const data = event.data; |
199 | | - let context = event.context; |
200 | | - if (context === undefined) { |
201 | | - // Support legacy events and CloudEvents in structured content mode, with |
202 | | - // context properties represented as event top-level properties. |
203 | | - // Context is everything but data. |
204 | | - context = event; |
205 | | - // Clear the property before removing field so the data object |
206 | | - // is not deleted. |
207 | | - context.data = undefined; |
208 | | - delete context.data; |
209 | | - } |
210 | | - // Callback style if user function has more than 2 arguments. |
211 | | - if (userFunction!.length > 2) { |
212 | | - const fn = userFunction as EventFunctionWithCallback; |
213 | | - return fn(data, context, callback); |
214 | | - } |
215 | | - |
216 | | - const fn = userFunction as EventFunction; |
217 | | - Promise.resolve() |
218 | | - .then(() => { |
219 | | - const result = fn(data, context); |
220 | | - return result; |
221 | | - }) |
222 | | - .then( |
223 | | - result => { |
224 | | - callback(null, result); |
225 | | - }, |
226 | | - err => { |
227 | | - callback(err, undefined); |
228 | | - } |
229 | | - ); |
230 | | - }; |
231 | | -} |
232 | | - |
233 | 89 | // Use an exit code which is unused by Node.js: |
234 | 90 | // https://nodejs.org/api/process.html#process_exit_codes |
235 | 91 | const killInstance = process.exit.bind(process, 16); |
|
0 commit comments