File tree Expand file tree Collapse file tree 5 files changed +50
-11
lines changed Expand file tree Collapse file tree 5 files changed +50
-11
lines changed Original file line number Diff line number Diff line change 11import type { APIGatewayProxyEventHeaders } from 'aws-lambda'
2+ import { parseHeaders } from './parseHeaders.js'
23
34const allowedDomains = [
45 / ^ h t t p s ? : \/ \/ l o c a l h o s t : / ,
56 / ^ h t t p s : \/ \/ h e l l o \. n r f c l o u d \. c o m $ / ,
67]
78const defaultOrigin = 'https://hello.nrfcloud.com'
89const origin = ( event : { headers : APIGatewayProxyEventHeaders } ) : string => {
9- const origin = event . headers . origin ?? defaultOrigin . toString ( )
10+ const origin =
11+ parseHeaders ( event . headers ) . get ( 'origin' ) ?? defaultOrigin . toString ( )
1012
1113 if ( allowedDomains . find ( ( rx ) => rx . test ( origin ) ) !== undefined ) return origin
1214
Original file line number Diff line number Diff line change 1+ import assert from 'assert'
2+ import { describe , it } from 'node:test'
3+ import { parseHeaders } from './parseHeaders.js'
4+
5+ void describe ( 'parseHeaders()' , ( ) => {
6+ void it ( 'should parse both lowercase and uppercase headers' , ( ) => {
7+ const headers = {
8+ 'content-type' : 'application/json' ,
9+ 'Content-Length' : '1234' ,
10+ 'x-custom-header' : 'value' ,
11+ }
12+
13+ const parsedHeaders = parseHeaders ( headers )
14+
15+ assert . deepEqual (
16+ parsedHeaders ,
17+ new Map ( [
18+ [ 'content-type' , 'application/json' ] ,
19+ [ 'content-length' , '1234' ] ,
20+ [ 'x-custom-header' , 'value' ] ,
21+ ] ) ,
22+ )
23+ } )
24+ } )
Original file line number Diff line number Diff line change 1+ /**
2+ * Returns a Map of headers with keys in lowercase.
3+ * This is useful for consistent header handling, especially in environments
4+ * where header keys may be case-insensitive.
5+ */
6+ export const parseHeaders = (
7+ headers : Record < string , string | undefined > ,
8+ ) : Map < string , string | null > => {
9+ return Object . entries ( headers ) . reduce ( ( h , [ key , value ] ) => {
10+ h . set ( key . toLowerCase ( ) , value ?? null )
11+ return h
12+ } , new Map ( ) )
13+ }
Original file line number Diff line number Diff line change @@ -10,6 +10,7 @@ import type {
1010 APIGatewayProxyStructuredResultV2 ,
1111 Context ,
1212} from 'aws-lambda'
13+ import { parseHeaders } from './parseHeaders.js'
1314import { tryAsJSON } from './tryAsJSON.js'
1415
1516export class ValidationFailedError extends Error {
@@ -34,12 +35,10 @@ export const validateInput = <Schema extends TSchema>(
3435 return {
3536 before : async ( req ) => {
3637 let reqBody = { }
37- if (
38- ( req . event . headers ?. [ 'content-type' ] ?? '' ) . includes (
39- 'application/json' ,
40- ) &&
41- parseInt ( req . event . headers ?. [ 'content-length' ] ?? '0' , 10 ) > 0
42- ) {
38+ const headers = parseHeaders ( req . event . headers )
39+ const contentType = headers . get ( 'content-type' ) ?? ''
40+ const contentLength = parseInt ( headers . get ( 'content-length' ) ?? '0' , 10 )
41+ if ( contentType . includes ( 'application/json' ) && contentLength > 0 ) {
4342 reqBody = tryAsJSON ( req . event . body ) ?? { }
4443 }
4544 const input = mapInput ?.( req . event ) ?? {
Original file line number Diff line number Diff line change 55import type middy from '@middy/core'
66import type { TSchema } from '@sinclair/typebox'
77import type { ValueError } from '@sinclair/typebox/errors'
8+ import { parseHeaders } from './parseHeaders.js'
89import { tryAsJSON } from './tryAsJSON.js'
910import { ValidationFailedError } from './validateInput.js'
1011
@@ -25,13 +26,13 @@ export const validateResponse = <ResponseSchema extends TSchema>(
2526 return {
2627 after : async ( req ) => {
2728 const body = req . response ?. body
29+ const headers = parseHeaders ( req . response . headers )
30+ const contentType = headers . get ( 'content-type' ) ?? ''
31+
2832 if ( ( body ?. length ?? 0 ) === 0 ) {
2933 console . debug ( `[validateResponse]` , `Response body is empty` )
3034 }
31- if (
32- ( req . response . headers [ 'content-type' ] ?. includes ( 'application/json' ) ??
33- false ) === false
34- ) {
35+ if ( ( contentType ?. includes ( 'application/json' ) ?? false ) === false ) {
3536 console . debug ( `[validateResponse]` , `Response body is not JSON` )
3637 }
3738 const maybeValid = validator ( tryAsJSON ( req . response . body ) )
You can’t perform that action at this time.
0 commit comments