Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

base64-encode binary responses #5048

Merged
merged 2 commits into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lovely-flies-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/adapter-netlify': patch
---

Encode binary responses as base64
33 changes: 26 additions & 7 deletions packages/adapter-netlify/src/serverless.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,32 @@ export function init(manifest) {
const server = new Server(manifest);

return async (event, context) => {
const rendered = await server.respond(to_request(event), {
const response = await server.respond(to_request(event), {
platform: { context },
getClientAddress() {
return event.headers['x-nf-client-connection-ip'];
}
});

const partial_response = {
statusCode: rendered.status,
...split_headers(rendered.headers)
statusCode: response.status,
...split_headers(response.headers)
};

// TODO this is probably wrong now?
if (rendered.body instanceof Uint8Array) {
if (!is_text(response.headers.get('content-type'))) {
// Function responses should be strings (or undefined), and responses with binary
// content should be base64 encoded and set isBase64Encoded to true.
// https://github.com/netlify/functions/blob/main/src/function/response.ts
return {
...partial_response,
isBase64Encoded: true,
body: Buffer.from(rendered.body).toString('base64')
body: Buffer.from(await response.arrayBuffer()).toString('base64')
};
}

return {
...partial_response,
body: await rendered.text()
body: await response.text()
};
};
}
Expand All @@ -61,3 +60,23 @@ function to_request(event) {

return new Request(rawUrl, init);
}

const text_types = new Set([
'application/xml',
'application/json',
'application/x-www-form-urlencoded',
'multipart/form-data'
]);

/**
* Decides how the body should be parsed based on its mime type
*
* @param {string | undefined | null} content_type The `content-type` header of a request/response.
* @returns {boolean}
*/
function is_text(content_type) {
if (!content_type) return true; // defaults to json
const type = content_type.split(';')[0].toLowerCase(); // get the mime type

return type.startsWith('text/') || type.endsWith('+xml') || text_types.has(type);
}
2 changes: 1 addition & 1 deletion packages/kit/src/runtime/server/endpoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const text_types = new Set([
]);

/**
* Decides how the body should be parsed based on its mime type. Should match what's in parse_body
* Decides how the body should be parsed based on its mime type
*
* @param {string | undefined | null} content_type The `content-type` header of a request/response.
* @returns {boolean}
Expand Down