Skip to content

Commit 3e6cea7

Browse files
committed
Enable multiple headers with same name
1 parent 0bde506 commit 3e6cea7

File tree

4 files changed

+65
-7
lines changed

4 files changed

+65
-7
lines changed

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"dist/"
99
],
1010
"scripts": {
11-
"lint": "tslint \"src/**/*.ts\"",
11+
"lint": "tslint \"src/**/*.ts\" --type-check --project tsconfig.json",
1212
"build": "rimraf dist && tsc",
1313
"specs": "jest --coverage",
1414
"test": "npm run -s lint && npm run -s build && npm run -s specs",
@@ -39,12 +39,13 @@
3939
"devDependencies": {
4040
"jest": "^19.0.0",
4141
"rimraf": "^2.5.4",
42-
"tslint": "^5.0.0",
43-
"tslint-config-standard": "^4.0.0",
42+
"tslint": "^5.1.0",
43+
"tslint-config-standard": "^5.0.2",
4444
"typescript": "^2.2.1",
4545
"typings": "^2.1.0"
4646
},
4747
"dependencies": {
48+
"bit-string-mask": "^1.0.0",
4849
"servie": "^0.2.0",
4950
"servie-errorhandler": "^0.1.0",
5051
"servie-finalhandler": "^0.1.0"

src/index.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,35 @@ describe('servie-lambda', () => {
7777
})
7878
})
7979

80+
it('should support multiple headers of the same key', (done) => {
81+
const handler = createHandler(() => {
82+
return new Response({
83+
headers: {
84+
'Set-Cookie': ['a=a', 'b=b', 'c=c']
85+
}
86+
})
87+
})
88+
89+
return handler(event, context, (err: Error | null, res: Result) => {
90+
if (err) {
91+
return done(err)
92+
}
93+
94+
expect(res).toEqual({
95+
statusCode: undefined,
96+
body: undefined,
97+
headers: {
98+
'set-cookie': 'a=a',
99+
'Set-cookie': 'b=b',
100+
'sEt-cookie': 'c=c'
101+
},
102+
isBase64Encoded: false
103+
})
104+
105+
return done()
106+
})
107+
})
108+
80109
it('should log and rewrite errors', (done) => {
81110
const logError = jest.fn()
82111
const handler = createHandler(() => Promise.reject(new Error('boom')), { logError })

src/index.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { format } from 'url'
2-
import { Request, Response } from 'servie'
2+
import { Request, Response, Headers } from 'servie'
33
import { errorhandler } from 'servie-errorhandler'
44
import { finalhandler } from 'servie-finalhandler'
5+
import { mask } from 'bit-string-mask'
56

6-
export type App = (req: Request, next: () => Promise<Response>) => Promise<Response>
7+
export type App = (req: Request, next: () => Promise<Response>) => Response | Promise<Response>
78

89
/**
910
* AWS Lambda event object.
@@ -104,14 +105,14 @@ export function createHandler (fn: App, options: Options = {}) {
104105

105106
returned = true
106107

107-
// Mark the response as finished when buffering is done.
108+
// Mark the response as finished when buffering is complete.
108109
res.finished = true
109110
res.bytesTransferred = body ? body.length : 0
110111

111112
return cb(null, {
112113
statusCode: res.status,
113114
body: body ? (isBase64Encoded ? body.toString('base64') : body.toString('utf8')) : undefined,
114-
headers: res.headers.object(),
115+
headers: getHeaders(res.headers),
115116
isBase64Encoded
116117
})
117118
})
@@ -134,3 +135,28 @@ export function createHandler (fn: App, options: Options = {}) {
134135
)
135136
}
136137
}
138+
139+
/**
140+
* Return a lambda compatible object of headers.
141+
*/
142+
function getHeaders (headers: Headers) {
143+
const result = Object.create(null)
144+
145+
if (headers.raw.length) {
146+
const obj = headers.object()
147+
148+
for (const key of Object.keys(obj)) {
149+
const val = obj[key]
150+
151+
if (Array.isArray(val)) {
152+
for (let i = 0; i < val.length; i++) {
153+
result[mask(key, i)] = val[i]
154+
}
155+
} else {
156+
result[key] = val
157+
}
158+
}
159+
}
160+
161+
return result
162+
}

tsconfig.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
"module": "commonjs",
1010
"moduleResolution": "node",
1111
"declaration": true,
12+
"alwaysStrict": true,
13+
"strictNullChecks": true,
1214
"noImplicitAny": true,
1315
"noImplicitThis": true,
1416
"noImplicitReturns": true,

0 commit comments

Comments
 (0)