Skip to content

Commit 64a99dc

Browse files
committed
feat: auto-detect binary response and add binarySettings
binaryMimeTypes now deprecated
1 parent e361f70 commit 64a99dc

File tree

11 files changed

+101
-48
lines changed

11 files changed

+101
-48
lines changed

examples/basic-starter-api-gateway-v2/src/lambda.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,4 @@ require('source-map-support/register')
22
const serverlessExpress = require('@vendia/serverless-express')
33
const app = require('./app')
44

5-
// NOTE: If you get ERR_CONTENT_DECODING_FAILED in your browser, this is likely
6-
// due to a compressed response (e.g. gzip) which has not been handled correctly
7-
// by serverless-express and/or API Gateway. Add the necessary MIME types to
8-
// binaryMimeTypes below, then redeploy (`npm run package-deploy`)
9-
const binaryMimeTypes = [
10-
'*/*'
11-
]
12-
13-
exports.handler = serverlessExpress({
14-
app,
15-
binaryMimeTypes
16-
}).handler
5+
exports.handler = serverlessExpress({ app }).handler

package-lock.json

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,9 @@
137137
"lint": "eslint src examples",
138138
"install-example-dependencies": "cd examples && npm install --prefix basic-starter-api-gateway-v1 basic-starter-api-gateway-v1 && cd .."
139139
},
140-
"dependencies": {
141-
"type-is": "^1.6.16"
142-
},
143140
"config": {
144141
"commitizen": {
145142
"path": "cz-conventional-changelog"
146143
}
147144
}
148-
}
145+
}

src/configure.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import ProxyParams from "./proxy"
55

66
interface ConfigureParams {
77
app: RequestListener,
8-
binaryMimeTypes?: string[]
8+
binaryMimeTypes?: string[],
9+
binarySettings: BinarySettings
10+
}
11+
12+
interface BinarySettings {
13+
isBinary?: Function | boolean,
14+
contentTypes: string[]
915
}
1016

1117
interface ConfigureResult {

src/configure.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ const proxy = require('./proxy')
55
function configure ({
66
app: configureApp,
77
framework: configureFramework = getFramework({ app: configureApp }),
8-
binaryMimeTypes: configureBinaryMimeTypes = [],
8+
binaryMimeTypes: configureBinaryMimeTypes,
9+
binarySettings: configureBinarySettings,
910
resolutionMode: configureResolutionMode = 'PROMISE',
1011
eventSourceName: configureEventSourceName,
1112
eventSource: configureEventFns,
@@ -20,6 +21,7 @@ function configure ({
2021
callback,
2122
eventSourceName = configureEventSourceName,
2223
binaryMimeTypes = configureBinaryMimeTypes,
24+
binarySettings = configureBinarySettings,
2325
eventSource = configureEventFns,
2426
log = configureLogger,
2527
respondWithErrors = configureRespondWithErrors
@@ -32,6 +34,7 @@ function configure ({
3234
callback,
3335
eventSourceName,
3436
binaryMimeTypes,
37+
binarySettings,
3538
eventSource,
3639
log,
3740
respondWithErrors

src/is-binary.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// ATTRIBUTION: https://github.com/dougmoscrop/serverless-http
2+
3+
function isContentEncodingBinary ({ headers, binaryEncodingTypes }) {
4+
const contentEncoding = headers['content-encoding']
5+
6+
if (typeof contentEncoding !== 'string') return false
7+
8+
return contentEncoding
9+
.split(',')
10+
.some(value => binaryEncodingTypes.some(binaryEncoding => value.includes(binaryEncoding)))
11+
}
12+
13+
function getContentType ({ headers }) {
14+
const contentTypeHeader = headers['content-type'] || ''
15+
16+
// only compare mime type; ignore encoding part
17+
return contentTypeHeader.split(';')[0]
18+
}
19+
20+
function isContentTypeBinary ({ headers, binaryContentTypes }) {
21+
if (!binaryContentTypes || !Array.isArray(binaryContentTypes)) return false
22+
23+
const binaryContentTypesRegexes = binaryContentTypes.map(binaryContentType => new RegExp(`^${binaryContentType.replace(/\*/g, '.*')}$`))
24+
const contentType = getContentType({ headers })
25+
26+
if (!contentType) return false
27+
28+
return binaryContentTypesRegexes.some(binaryContentType => binaryContentType.test(contentType))
29+
}
30+
31+
module.exports = function isBinary ({ headers, binarySettings }) {
32+
if (binarySettings.isBinary === false) {
33+
return false
34+
}
35+
36+
if (typeof binarySettings.isBinary === 'function') {
37+
return binarySettings.isBinary({ headers })
38+
}
39+
40+
return isContentEncodingBinary({ headers, binaryEncodingTypes: binarySettings.contentEncodings }) ||
41+
isContentTypeBinary({ headers, binaryContentTypes: binarySettings.contentTypes })
42+
}

src/proxy.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@ import { RequestListener } from "http"
22

33
interface ProxyParams {
44
app: RequestListener,
5-
binaryMimeTypes?: string[]
5+
binaryMimeTypes?: string[],
6+
binarySettings: BinarySettings
7+
}
8+
9+
interface BinarySettings {
10+
isBinary?: Function | boolean,
11+
contentTypes: string[]
612
}
713

814
declare function proxy(proxyParams: ProxyParams): Promise<any>

src/proxy.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ const { getFramework } = require('./frameworks')
55
const makeResolver = require('./make-resolver')
66
const { forwardRequestToNodeServer, respondToEventSourceWithError } = require('./transport')
77

8+
const DEFAULT_BINARY_ENCODINGS = ['gzip', 'deflate', 'br']
9+
const DEFAULT_BINARY_CONTENT_TYPES = ['image/*']
10+
11+
function getDefaultBinarySettings (deprecatedBinaryMimeTypes) {
12+
return {
13+
contentTypes: deprecatedBinaryMimeTypes || DEFAULT_BINARY_CONTENT_TYPES,
14+
contentEncodings: DEFAULT_BINARY_ENCODINGS
15+
}
16+
}
17+
818
function proxy ({
919
app,
1020
framework = getFramework({ app }),
@@ -14,6 +24,7 @@ function proxy ({
1424
resolutionMode = 'PROMISE',
1525
eventSourceName = getEventSourceNameBasedOnEvent({ event }),
1626
binaryMimeTypes,
27+
binarySettings = getDefaultBinarySettings(binaryMimeTypes),
1728
eventSource = getEventSource({ eventSourceName }),
1829
log,
1930
respondWithErrors
@@ -23,9 +34,14 @@ function proxy ({
2334
context,
2435
resolutionMode,
2536
eventSourceName,
26-
binaryMimeTypes,
37+
binarySettings,
2738
respondWithErrors
2839
})
40+
41+
if (binaryMimeTypes) {
42+
console.warn('{ binaryMimeTypes: [] } is deprecated. base64 encoding is now automatically determined based on response content-type and content-encoding. If you need to manually set binary content types, instead, use { binarySettings: { contentTypes: [] } }')
43+
}
44+
2945
setCurrentInvoke({ event, context })
3046
return new Promise((resolve, reject) => {
3147
const promise = {
@@ -47,7 +63,7 @@ function proxy ({
4763
context,
4864
resolver,
4965
eventSourceName,
50-
binaryMimeTypes,
66+
binarySettings,
5167
eventSource,
5268
log
5369
})

src/request.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
'use strict'
21
// ATTRIBUTION: https://github.com/dougmoscrop/serverless-http
32

43
const http = require('http')

src/response.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
'use strict'
21
// ATTRIBUTION: https://github.com/dougmoscrop/serverless-http
32

43
const http = require('http')

0 commit comments

Comments
 (0)