@@ -12,10 +12,10 @@ import {
1212 SecurityConfig ,
1313} from "./types-and-interfaces" ;
1414import { authorizeRoute } from "./authorization-helper" ;
15- import {
16- loadSecurityConfig ,
17- generateCorsHeaders ,
18- generateJwtRotationHeaders
15+ import {
16+ loadSecurityConfig ,
17+ generateCorsHeaders ,
18+ generateJwtRotationHeaders
1919} from "./security-config-loader" ;
2020
2121const getRouteConfigEntry = (
@@ -139,141 +139,147 @@ export function getRouteConfigByPath(
139139
140140export const lambdaRouteProxyEntryHandler =
141141 ( config : RouteConfig , availableRouteModules : { [ key : string ] : any } ) =>
142- async (
143- event : APIGatewayProxyEventV2 | APIGatewayProxyEvent | APIGatewayEvent
144- ) => {
145- // Load security configuration
146- const securityConfig = config . security || loadSecurityConfig ( ) ;
147- console . log ( `Event Data: ${ JSON . stringify ( event ) } ` ) ;
148- const isV2 = ( event as APIGatewayProxyEventV2 ) . version === "2.0" ;
142+ async (
143+ event : APIGatewayProxyEventV2 | APIGatewayProxyEvent | APIGatewayEvent
144+ ) => {
145+ // Load security configuration
146+ const securityConfig = config . security || loadSecurityConfig ( ) ;
147+ console . log ( `Event Data: ${ JSON . stringify ( event ) } ` ) ;
148+ const isV2 = ( event as APIGatewayProxyEventV2 ) . version === "2.0" ;
149149
150- const isProxied = ! isV2 && event . hasOwnProperty ( "requestContext" ) ;
150+ const isProxied = ! isV2 && event . hasOwnProperty ( "requestContext" ) ;
151151
152- const newEvent = isV2
153- ? v2ApiGatewayEvent ( event as APIGatewayProxyEventV2 )
154- : v1ApiGatewayEvent ( event as APIGatewayProxyEvent , config ) ;
152+ const newEvent = isV2
153+ ? v2ApiGatewayEvent ( event as APIGatewayProxyEventV2 )
154+ : v1ApiGatewayEvent ( event as APIGatewayProxyEvent , config ) ;
155155
156- const {
157- routeKey,
158- queryStringParameters,
159- pathParameters,
160- body,
161- isBase64Encoded,
162- } = newEvent ;
156+ const {
157+ routeKey,
158+ queryStringParameters,
159+ pathParameters,
160+ body,
161+ isBase64Encoded,
162+ } = newEvent ;
163163
164- let retVal : any = { } ;
165- try {
166- const [ method = "" , path = "" ] = routeKey . split ( " " ) ;
167- if (
168- shouldAuthorizeRoute ( config , getRouteConfigEntry ( config , method , path ) )
169- ) {
170- await authorizeRoute ( event ) ;
171- }
164+ let retVal : any = { } ;
165+ try {
166+ const [ method = "" , path = "" ] = routeKey . split ( " " ) ;
167+ if (
168+ shouldAuthorizeRoute ( config , getRouteConfigEntry ( config , method , path ) )
169+ ) {
170+ await authorizeRoute ( event ) ;
171+ }
172172
173- const routeModule = getRouteModule (
174- config ,
175- method ,
176- path ,
177- availableRouteModules
178- ) ;
173+ const routeModule = getRouteModule (
174+ config ,
175+ method ,
176+ path ,
177+ availableRouteModules
178+ ) ;
179179
180- console . log ( `isBase64Encoded: ${ isBase64Encoded } ` ) ;
181- console . log ( `body: ${ body } ` ) ;
182- const decodedBody = isBase64Encoded
183- ? Buffer . from ( body ! , "base64" ) . toString ( "utf-8" )
184- : undefined ;
185- console . log ( `decodedBody:
180+ console . log ( `isBase64Encoded: ${ isBase64Encoded } ` ) ;
181+ console . log ( `body: ${ body } ` ) ;
182+ const decodedBody = isBase64Encoded
183+ ? Buffer . from ( body ! , "base64" ) . toString ( "utf-8" )
184+ : undefined ;
185+ console . log ( `decodedBody:
186186 ${ decodedBody } ` ) ;
187187
188- const routeArgs : RouteArguments = {
189- query : queryStringParameters ,
190- params : pathParameters ,
191- body : body ? decodedBody || JSON . parse ( body ) : undefined ,
192- rawEvent : event ,
193- } ;
194-
195- retVal = await getRouteModuleResult ( routeModule , routeArgs ) ;
188+ const routeArgs : RouteArguments = {
189+ query : queryStringParameters ,
190+ params : pathParameters ,
191+ body : body ? decodedBody || JSON . parse ( body ) : undefined ,
192+ rawEvent : event ,
193+ } ;
196194
197- if ( isProxied ) {
198- if ( retVal . statusCode && ! retVal . body ) {
199- console . log ( "body must be included when status code is set" , retVal ) ;
200- throw new CustomError ( "No body found" , 500 ) ;
201- } else if ( retVal . statusCode && retVal . body ) {
202- // Generate secure headers based on configuration
203- const requestOrigin = event . headers ?. origin || event . headers ?. Origin ;
204- const corsHeaders = generateCorsHeaders ( securityConfig , requestOrigin ) ;
205- const jwtRotationHeaders = generateJwtRotationHeaders ( securityConfig , routeArgs . routeData ) ;
206-
207- retVal = {
208- ...retVal ,
209- isBase64Encoded : false ,
210- headers : {
211- "Content-Type" : "application/json" ,
212- // 1. Default security headers from config (lowest priority)
213- ...securityConfig . defaultHeaders ,
214- // 2. CORS headers (only if origin is allowed)
215- ...corsHeaders ,
216- // 3. JWT rotation headers (if needed)
217- ...jwtRotationHeaders ,
218- // 4. Middleware-provided headers (higher priority)
219- ...( routeArgs . responseHeaders ?? { } ) ,
220- // 5. Handler-provided headers (highest priority - can override everything)
221- ...( retVal . headers ?? { } ) ,
222- } ,
223- body :
224- typeof retVal . body === "object"
225- ? JSON . stringify ( retVal . body )
226- : retVal . body ,
227- } ;
195+ retVal = await getRouteModuleResult ( routeModule , routeArgs ) ;
196+
197+ if ( isProxied ) {
198+ if ( retVal . statusCode && ! retVal . body ) {
199+ console . log ( "body must be included when status code is set" , retVal ) ;
200+ throw new CustomError ( "No body found" , 500 ) ;
201+ } else if ( retVal . statusCode && retVal . statusCode !== 200 ) {
202+ retVal = retVal ;
203+ } else if ( retVal . statusCode && retVal . body ) {
204+ // Generate secure headers based on configuration
205+ const requestOrigin = event . headers ?. origin || event . headers ?. Origin ;
206+ const corsHeaders = generateCorsHeaders ( securityConfig , requestOrigin ) ;
207+ const jwtRotationHeaders = generateJwtRotationHeaders ( securityConfig , routeArgs . routeData ) ;
208+
209+ retVal = {
210+ ...retVal ,
211+ isBase64Encoded : false ,
212+ headers : {
213+ "Content-Type" : "application/json" ,
214+ // 1. Default security headers from config (lowest priority)
215+ ...securityConfig . defaultHeaders ,
216+ // 2. CORS headers (only if origin is allowed)
217+ ...corsHeaders ,
218+ // 3. JWT rotation headers (if needed)
219+ ...jwtRotationHeaders ,
220+ // 4. Middleware-provided headers (higher priority)
221+ ...( routeArgs . responseHeaders ?? { } ) ,
222+ // 5. Handler-provided headers (highest priority - can override everything)
223+ ...( retVal . headers ?? { } ) ,
224+ } ,
225+ body :
226+ typeof retVal . body === "object"
227+ ? JSON . stringify ( retVal . body )
228+ : retVal . body ,
229+ } ;
230+ }
231+ } else {
232+ if ( retVal . statusCode && retVal . statusCode !== 200 ) {
233+ retVal = retVal ;
234+ } else {
235+ retVal = {
236+ statusCode : 200 ,
237+ body : JSON . stringify ( retVal ) ,
238+ headers : {
239+ "Content-Type" : "application/json" ,
240+ } ,
241+ } ;
242+ }
228243 }
229- } else {
230- retVal = {
231- statusCode : 200 ,
232- body : JSON . stringify ( retVal ) ,
233- headers : {
234- "Content-Type" : "application/json" ,
235- } ,
236- } ;
237- }
238- } catch ( error : any ) {
239- console . error ( JSON . stringify ( { error, stack : error . stack } ) ) ;
240- let headers = {
241- "Content-Type" : "application/json" ,
242- } as Record < string , string > ;
244+ } catch ( error : any ) {
245+ console . error ( JSON . stringify ( { error, stack : error . stack } ) ) ;
246+ let headers = {
247+ "Content-Type" : "application/json" ,
248+ } as Record < string , string > ;
243249
244- let statusCode = 500 ;
250+ let statusCode = 500 ;
245251
246- if ( isProxied ) {
247- const isOptions =
248- ( event . requestContext as any ) . httpMethod === "OPTIONS" ;
249- if ( isOptions ) {
250- statusCode = 200 ;
252+ if ( isProxied ) {
253+ const isOptions =
254+ ( event . requestContext as any ) . httpMethod === "OPTIONS" ;
255+ if ( isOptions ) {
256+ statusCode = 200 ;
257+ } else {
258+ statusCode = error . httpStatusCode || 500 ;
259+ }
260+ headers = {
261+ ...headers ,
262+ "Access-Control-Allow-Origin" : "*" ,
263+ "Access-Control-Allow-Methods" :
264+ "GET, POST, PUT, DELETE, PATCH, OPTIONS" ,
265+ "Access-Control-Allow-Headers" :
266+ "Content-Type, Authorization, X-Amz-Date, X-Api-Key, X-Amz-Security-Token" ,
267+ "Access-Control-Allow-Credentials" : "true" ,
268+ } ;
269+ }
270+ if ( error instanceof CustomError ) {
271+ retVal = {
272+ statusCode,
273+ headers,
274+ body : error . message ,
275+ } ;
251276 } else {
252- statusCode = error . httpStatusCode || 500 ;
277+ retVal = {
278+ statusCode,
279+ headers,
280+ body : error . message || JSON . stringify ( error ) ,
281+ } ;
253282 }
254- headers = {
255- ...headers ,
256- "Access-Control-Allow-Origin" : "*" ,
257- "Access-Control-Allow-Methods" :
258- "GET, POST, PUT, DELETE, PATCH, OPTIONS" ,
259- "Access-Control-Allow-Headers" :
260- "Content-Type, Authorization, X-Amz-Date, X-Api-Key, X-Amz-Security-Token" ,
261- "Access-Control-Allow-Credentials" : "true" ,
262- } ;
263283 }
264- if ( error instanceof CustomError ) {
265- retVal = {
266- statusCode,
267- headers,
268- body : error . message ,
269- } ;
270- } else {
271- retVal = {
272- statusCode,
273- headers,
274- body : error . message || JSON . stringify ( error ) ,
275- } ;
276- }
277- }
278- return retVal ;
279- } ;
284+ return retVal ;
285+ } ;
0 commit comments