1- import { Express , Request , Response } from 'express' ;
1+ import { Express } from 'express' ;
2+ import { Writable } from 'stream' ;
23import { Context , Event , ServerlessAdapter } from './types' ;
3- import serverlessHandler from './serverlessHandler' ;
4+ import sendRequest from './sendRequest' ;
5+ import ServerlessRequest from './serverlessRequest' ;
6+ import ServerlessResponse from './serverlessResponse' ;
7+ import { IncomingHttpHeaders } from 'http' ;
48
5- // const CONTEXT_HEADER_NAME = 'x-fc-http-context';
9+ const constructFrameworkContext = ( event : Event , context : Context ) => {
10+ console . log ( 'constructFrameworkContext' , event , context ) ;
11+ const request = new ServerlessRequest ( {
12+ method : event . httpMethod ,
13+ headers : event . headers ,
14+ body : event . body ,
15+ remoteAddress : '' ,
16+ url : event . path ,
17+ isBase64Encoded : event . isBase64Encoded ,
18+ } ) ;
19+ const response = new ServerlessResponse ( request ) ;
20+ return { request, response } ;
21+ } ;
622
7- // const getRequestHeaders = (ctx: { request: Request }) => {
8- // const request = ctx.request;
9- // const headers = { ...request.headers };
10- // return headers;
11- // };
12- //
13- // const getSocketPath = (): string => {
14- // const socketPathSuffix = Math.random().toString(36).substring(2, 15);
15- // if (/^win/.test(process.platform)) {
16- // const path = require('path');
17- // return path.join('\\\\?\\pipe', process.cwd(), `server-${socketPathSuffix}`);
18- // } else {
19- // return `/tmp/server-${socketPathSuffix}.sock`;
20- // }
21- // };
23+ const waitForStreamComplete = ( stream : Writable ) : Promise < Writable > => {
24+ if ( stream . writableFinished || stream . writableEnded ) {
25+ return Promise . resolve ( stream ) ;
26+ }
2227
23- // const getBody = async (request: Request): Promise<string> => {
24- // return new Promise((resolve, reject) => {
25- // if (!request.on) {
26- // resolve('');
27- // }
28- // try {
29- // getRawBody(request).then(resolve, reject);
30- // } catch (e) {
31- // reject(e);
32- // }
33- // });
34- // };
35- //
36- // const makeResolver = (ctx) => {
37- // return data => {
38- // const response = ctx.response;
39- // if (response.setStatusCode) {
40- // response.setStatusCode(data.statusCode);
41- // } else {
42- // response.status = data.statusCode;
43- // response.statusCode = data.statusCode;
44- // }
45- // for (const key in data.headers) {
46- // if (data.headers.hasOwnProperty(key)) {
47- // const value = data.headers[key];
48- // response.setHeader(key, value);
49- // }
50- // }
51- // for (const key in data.multiValueHeaders) {
52- // const value = data.multiValueHeaders[key]
53- // response.setHeader(key, value)
54- // }
55- // if (response.send) {
56- // response.send(data.body);
57- // } else {
58- // response.end(data.body);
59- // }
60- // };
61- // }
62- //
28+ return new Promise ( ( resolve , reject ) => {
29+ stream . once ( 'error' , complete ) ;
30+ stream . once ( 'end' , complete ) ;
31+ stream . once ( 'finish' , complete ) ;
6332
64- const constructFrameworkContext = ( event : Event , context : Context ) => {
65- console . log ( 'constructFrameworkContext' , event , context ) ;
33+ let isComplete = false ;
34+
35+ function complete ( err ?: Error ) {
36+ if ( isComplete ) {
37+ return ;
38+ }
39+
40+ isComplete = true ;
41+
42+ stream . removeListener ( 'error' , complete ) ;
43+ stream . removeListener ( 'end' , complete ) ;
44+ stream . removeListener ( 'finish' , complete ) ;
45+
46+ if ( err ) {
47+ reject ( err ) ;
48+ } else {
49+ resolve ( stream ) ;
50+ }
51+ }
52+ } ) ;
53+ } ;
54+
55+ const buildResponse = ( {
56+ request,
57+ response,
58+ } : {
59+ request : ServerlessRequest ;
60+ response : ServerlessResponse ;
61+ } ) => {
6662 return {
67- request : {
68- ...event ,
69- get : ( name : string ) => event . headers [ name . toLowerCase ( ) ] ,
70- } as unknown as Request ,
71- response : { } as unknown as Response ,
63+ statusCode : response . statusCode ,
64+ body : ServerlessResponse . body ( response ) . toString ( request . isBase64Encoded ? 'base64' : 'utf8' ) ,
65+ headers : response . headers ,
66+ isBase64Encoded : request . isBase64Encoded ,
7267 } ;
7368} ;
7469
@@ -77,18 +72,22 @@ const serverlessAdapter: ServerlessAdapter = (app: Express) => {
7772 const ctx = constructFrameworkContext ( event , context ) ;
7873
7974 try {
80- return ( await serverlessHandler ( app , ctx ) ) as unknown as {
81- statusCode : number ;
82- body : unknown ;
83- } ;
75+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
76+ // @ts -expect-error
77+ await sendRequest ( app , ctx . request , ctx . response ) ;
78+ await waitForStreamComplete ( ctx . response ) ;
79+ return buildResponse ( ctx ) ;
8480 } catch ( err ) {
8581 const errorResponse = { statusCode : 500 , body : ( err as Error ) . message } ;
8682 console . log ( 'Error occurred during request handling:' , err ) ;
87- return errorResponse as unknown as { statusCode : number ; body : unknown } ;
83+ return errorResponse as unknown as {
84+ statusCode : number ;
85+ body : string ;
86+ headers : IncomingHttpHeaders ;
87+ isBase64Encoded : boolean ;
88+ } ;
8889 }
8990 } ;
9091} ;
9192
9293export default serverlessAdapter ;
93-
94- export const hello = ( ) => 'hello' ;
0 commit comments