20
20
// - ANY (all methods) '/*' for executing functions (only for servers handling
21
21
// functions with HTTP trigger).
22
22
23
- import * as bodyParser from 'body-parser' ;
24
23
// eslint-disable-next-line node/no-deprecated-api
25
24
import * as domain from 'domain' ;
26
25
import * as express from 'express' ;
27
26
import * as http from 'http' ;
28
- import * as onFinished from 'on-finished' ;
29
-
30
27
import { FUNCTION_STATUS_HEADER_FIELD } from './types' ;
31
28
import { sendCrashResponse } from './logger' ;
32
29
import { isBinaryCloudEvent , getBinaryCloudEventContext } from './cloudevents' ;
@@ -36,7 +33,6 @@ import {
36
33
EventFunctionWithCallback ,
37
34
CloudEventFunction ,
38
35
CloudEventFunctionWithCallback ,
39
- HandlerFunction ,
40
36
} from './functions' ;
41
37
42
38
// We optionally annotate the express Request with a rawBody field.
@@ -50,14 +46,14 @@ declare global {
50
46
}
51
47
}
52
48
53
- export enum SignatureType {
54
- HTTP = 'http' ,
55
- EVENT = 'event' ,
56
- CLOUDEVENT = 'cloudevent' ,
57
- }
58
-
59
- // Response object for the most recent request.
49
+ /**
50
+ * Response object for the most recent request.
51
+ * Used for sending errors to the user.
52
+ */
60
53
let latestRes : express . Response | null = null ;
54
+ export const setLatestRes = ( res : express . Response ) => {
55
+ latestRes = res ;
56
+ } ;
61
57
62
58
/**
63
59
* Sends back a response to the incoming request.
@@ -102,7 +98,7 @@ function sendResponse(result: any, err: Error | null, res: express.Response) {
102
98
* @param execute Runs user's function.
103
99
* @return An Express handler function.
104
100
*/
105
- function makeHttpHandler ( execute : HttpFunction ) : express . RequestHandler {
101
+ export function makeHttpHandler ( execute : HttpFunction ) : express . RequestHandler {
106
102
return ( req : express . Request , res : express . Response ) => {
107
103
const d = domain . create ( ) ;
108
104
// Catch unhandled errors originating from this request.
@@ -128,7 +124,7 @@ function makeHttpHandler(execute: HttpFunction): express.RequestHandler {
128
124
* @param userFunction User's function.
129
125
* @return HTTP function which wraps the provided event function.
130
126
*/
131
- function wrapCloudEventFunction (
127
+ export function wrapCloudEventFunction (
132
128
userFunction : CloudEventFunction | CloudEventFunctionWithCallback
133
129
) : HttpFunction {
134
130
return ( req : express . Request , res : express . Response ) => {
@@ -180,7 +176,7 @@ function wrapCloudEventFunction(
180
176
* @param userFunction User's function.
181
177
* @return HTTP function which wraps the provided event function.
182
178
*/
183
- function wrapEventFunction (
179
+ export function wrapEventFunction (
184
180
userFunction : EventFunction | EventFunctionWithCallback
185
181
) : HttpFunction {
186
182
return ( req : express . Request , res : express . Response ) => {
@@ -239,54 +235,6 @@ function wrapEventFunction(
239
235
} ;
240
236
}
241
237
242
- /**
243
- * Registers handler functions for route paths.
244
- * @param app Express application object.
245
- * @param userFunction User's function.
246
- * @param functionSignatureType Type of user's function signature.
247
- */
248
- function registerFunctionRoutes (
249
- app : express . Application ,
250
- userFunction : HandlerFunction ,
251
- functionSignatureType : SignatureType
252
- ) {
253
- if ( functionSignatureType === SignatureType . HTTP ) {
254
- app . use ( '/favicon.ico|/robots.txt' , ( req , res ) => {
255
- // Neither crawlers nor browsers attempting to pull the icon find the body
256
- // contents particularly useful, so we send nothing in the response body.
257
- res . status ( 404 ) . send ( null ) ;
258
- } ) ;
259
-
260
- app . use ( '/*' , ( req , res , next ) => {
261
- onFinished ( res , ( err , res ) => {
262
- res . locals . functionExecutionFinished = true ;
263
- } ) ;
264
- next ( ) ;
265
- } ) ;
266
-
267
- app . all ( '/*' , ( req , res , next ) => {
268
- const handler = makeHttpHandler ( userFunction as HttpFunction ) ;
269
- handler ( req , res , next ) ;
270
- } ) ;
271
- } else if ( functionSignatureType === SignatureType . EVENT ) {
272
- app . post ( '/*' , ( req , res , next ) => {
273
- const wrappedUserFunction = wrapEventFunction (
274
- userFunction as EventFunction | EventFunctionWithCallback
275
- ) ;
276
- const handler = makeHttpHandler ( wrappedUserFunction ) ;
277
- handler ( req , res , next ) ;
278
- } ) ;
279
- } else {
280
- app . post ( '/*' , ( req , res , next ) => {
281
- const wrappedUserFunction = wrapCloudEventFunction (
282
- userFunction as CloudEventFunction | CloudEventFunctionWithCallback
283
- ) ;
284
- const handler = makeHttpHandler ( wrappedUserFunction ) ;
285
- handler ( req , res , next ) ;
286
- } ) ;
287
- }
288
- }
289
-
290
238
// Use an exit code which is unused by Node.js:
291
239
// https://nodejs.org/api/process.html#process_exit_codes
292
240
const killInstance = process . exit . bind ( process , 16 ) ;
@@ -333,81 +281,3 @@ export class ErrorHandler {
333
281
} ) ;
334
282
}
335
283
}
336
-
337
- /**
338
- * Creates and configures an Express application and returns an HTTP server
339
- * which will run it.
340
- * @param userFunction User's function.
341
- * @param functionSignatureType Type of user's function signature.
342
- * @return HTTP server.
343
- */
344
- export function getServer (
345
- userFunction : HandlerFunction ,
346
- functionSignatureType : SignatureType
347
- ) : http . Server {
348
- // App to use for function executions.
349
- const app = express ( ) ;
350
-
351
- // Express middleware
352
-
353
- // Set request-specific values in the very first middleware.
354
- app . use ( '/*' , ( req , res , next ) => {
355
- latestRes = res ;
356
- res . locals . functionExecutionFinished = false ;
357
- next ( ) ;
358
- } ) ;
359
-
360
- /**
361
- * Retains a reference to the raw body buffer to allow access to the raw body
362
- * for things like request signature validation. This is used as the "verify"
363
- * function in body-parser options.
364
- * @param req Express request object.
365
- * @param res Express response object.
366
- * @param buf Buffer to be saved.
367
- */
368
- function rawBodySaver (
369
- req : express . Request ,
370
- res : express . Response ,
371
- buf : Buffer
372
- ) {
373
- req . rawBody = buf ;
374
- }
375
-
376
- // Set limit to a value larger than 32MB, which is maximum limit of higher
377
- // level layers anyway.
378
- const requestLimit = '1024mb' ;
379
- const defaultBodySavingOptions = {
380
- limit : requestLimit ,
381
- verify : rawBodySaver ,
382
- } ;
383
- const cloudEventsBodySavingOptions = {
384
- type : 'application/cloudevents+json' ,
385
- limit : requestLimit ,
386
- verify : rawBodySaver ,
387
- } ;
388
- const rawBodySavingOptions = {
389
- limit : requestLimit ,
390
- verify : rawBodySaver ,
391
- type : '*/*' ,
392
- } ;
393
-
394
- // Use extended query string parsing for URL-encoded bodies.
395
- const urlEncodedOptions = {
396
- limit : requestLimit ,
397
- verify : rawBodySaver ,
398
- extended : true ,
399
- } ;
400
-
401
- // Apply middleware
402
- app . use ( bodyParser . json ( cloudEventsBodySavingOptions ) ) ;
403
- app . use ( bodyParser . json ( defaultBodySavingOptions ) ) ;
404
- app . use ( bodyParser . text ( defaultBodySavingOptions ) ) ;
405
- app . use ( bodyParser . urlencoded ( urlEncodedOptions ) ) ;
406
- // The parser will process ALL content types so MUST come last.
407
- // Subsequent parsers will be skipped when one is matched.
408
- app . use ( bodyParser . raw ( rawBodySavingOptions ) ) ;
409
- app . enable ( 'trust proxy' ) ; // To respect X-Forwarded-For header.
410
-
411
- registerFunctionRoutes ( app , userFunction , functionSignatureType ) ;
412
- return http . createServer ( app ) ;
413
- }
0 commit comments