Skip to content

Commit 34de081

Browse files
philnashvictoray
andauthored
fix(runtime-handler): don't check for exact Content-Type matches (#392)
* fix(runtime-handler): don't check for exact Content-Type matches Content-Type headers may have the media type followed by a semicolon, followed by some parameters, for example "charset=UTF-8". This fix ensures that only the start of the Content-Type header matches application/json when stringifying the body to JSON. Fixes #391 * chore: add changeset --------- Co-authored-by: Victor Ayogu <[email protected]>
1 parent 7bebf6f commit 34de081

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@twilio/runtime-handler': patch
3+
---
4+
5+
Don't check for exact Content-Type matches

packages/runtime-handler/__tests__/dev-runtime/internal/response.test.ts

+18
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,21 @@ test('serializes a response with content type set to application/json', () => {
292292
'Set-Cookie': [],
293293
});
294294
});
295+
296+
test('serializes a response with content type set to application/json with a charset', () => {
297+
const response = new Response();
298+
response.setBody({ url: 'https://dkundel.com' });
299+
response.setStatusCode(200);
300+
response.appendHeader('Content-Type', 'application/json; charset=UTF-8');
301+
302+
const serialized = response.serialize();
303+
304+
expect(serialized.body).toEqual(
305+
JSON.stringify({ url: 'https://dkundel.com' })
306+
);
307+
expect(serialized.statusCode).toEqual(200);
308+
expect(serialized.headers).toEqual({
309+
'Content-Type': 'application/json; charset=UTF-8',
310+
'Set-Cookie': [],
311+
});
312+
});

packages/runtime-handler/src/dev-runtime/internal/response.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export class Response implements TwilioResponse {
7979
this.headers[COOKIE_HEADER] = newHeaderValue;
8080
}
8181
} else {
82-
this.headers[COOKIE_HEADER] = Array.isArray(value) ? value: [value];
82+
this.headers[COOKIE_HEADER] = Array.isArray(value) ? value : [value];
8383
}
8484
} else {
8585
const existingValue = this.headers[key];
@@ -133,12 +133,17 @@ export class Response implements TwilioResponse {
133133
}
134134

135135
serialize() {
136+
const contentType = this.headers['Content-Type'];
137+
let body = this.body;
138+
if (
139+
typeof contentType === 'string' &&
140+
contentType.startsWith('application/json')
141+
) {
142+
body = JSON.stringify(body);
143+
}
136144
return {
137145
statusCode: this.statusCode,
138-
body:
139-
this.headers['Content-Type'] === 'application/json'
140-
? JSON.stringify(this.body)
141-
: this.body,
146+
body: body,
142147
headers: this.headers,
143148
};
144149
}

0 commit comments

Comments
 (0)