Skip to content

Commit

Permalink
Default body parsing to binary
Browse files Browse the repository at this point in the history
  • Loading branch information
benmccann committed Jul 12, 2021
1 parent a12843c commit 88e7639
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 77 deletions.
8 changes: 4 additions & 4 deletions packages/adapter-cloudflare-workers/files/entry.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// TODO hardcoding the relative location makes this brittle
import { init, render } from '../output/server/app.js'; // eslint-disable-line import/no-unresolved
import { getAssetFromKV, NotFoundError } from '@cloudflare/kv-asset-handler'; // eslint-disable-line import/no-unresolved
import { isContentTypeBinary } from '@sveltejs/kit/adapter-utils'; // eslint-disable-line import/no-unresolved
import { isContentTypeTextual } from '@sveltejs/kit/adapter-utils'; // eslint-disable-line import/no-unresolved

init();

Expand Down Expand Up @@ -58,9 +58,9 @@ async function handle(event) {
/** @param {Request} request */
async function read(request) {
const type = request.headers.get('content-type') || '';
if (isContentTypeBinary(type)) {
return new Uint8Array(await request.arrayBuffer());
if (isContentTypeTextual(type)) {
return request.text();
}

return request.text();
return new Uint8Array(await request.arrayBuffer());
}
12 changes: 6 additions & 6 deletions packages/adapter-netlify/files/entry.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// TODO hardcoding the relative location makes this brittle
import { init, render } from '../output/server/app.js'; // eslint-disable-line import/no-unresolved
import { isContentTypeBinary } from '@sveltejs/kit/adapter-utils'; // eslint-disable-line import/no-unresolved
import { isContentTypeTextual } from '@sveltejs/kit/adapter-utils'; // eslint-disable-line import/no-unresolved

init();

Expand All @@ -11,11 +11,11 @@ export async function handler(event) {

const type = headers['content-type'];
const rawBody =
type && isContentTypeBinary(type)
? new TextEncoder('base64').encode(body)
: isBase64Encoded
? Buffer.from(body, 'base64').toString()
: body;
type && isContentTypeTextual(type)
? isBase64Encoded
? Buffer.from(body, 'base64').toString()
: body
: new TextEncoder('base64').encode(body);

const rendered = await render({
method: httpMethod,
Expand Down
13 changes: 7 additions & 6 deletions packages/kit/src/core/adapter-utils.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
/**
* Decides how the body should be parsed based on its mime type.
* Decides how the body should be parsed based on its mime type. Should match what's in parse_body
*
* This is intended to be used with both requests and responses, to have a consistent body parsing across adapters.
*
* @param {string} content_type The `content-type` header of a request/response.
* @returns {boolean}
*/
export function isContentTypeBinary(content_type) {
export function isContentTypeTextual(content_type) {
return (
content_type.startsWith('image/') ||
content_type.startsWith('audio/') ||
content_type.startsWith('video/') ||
content_type.startsWith('application/octet-stream')
!content_type || // defaults to json
content_type === 'text/plain' ||
content_type === 'application/json' ||
content_type === 'application/x-www-form-urlencoded' ||
content_type === 'multipart/form-data'
);
}
10 changes: 5 additions & 5 deletions packages/kit/src/core/node/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isContentTypeBinary } from '../adapter-utils.js';
import { isContentTypeTextual } from '../adapter-utils.js';

/**
* @param {import('http').IncomingMessage} req
Expand Down Expand Up @@ -50,12 +50,12 @@ export function getRawBody(req) {
req.on('end', () => {
const [type] = h['content-type'].split(/;\s*/);

if (isContentTypeBinary(type)) {
return fulfil(data);
if (isContentTypeTextual(type)) {
const encoding = h['content-encoding'] || 'utf-8';
fulfil(new TextDecoder(encoding).decode(data));
}

const encoding = h['content-encoding'] || 'utf-8';
fulfil(new TextDecoder(encoding).decode(data));
return fulfil(data);
});
});
}
14 changes: 4 additions & 10 deletions packages/kit/src/runtime/server/endpoint.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isContentTypeBinary } from '../../core/adapter-utils.js';
import { isContentTypeTextual } from '../../core/adapter-utils.js';
import { lowercase_keys } from './utils.js';

/** @param {string} body */
Expand Down Expand Up @@ -38,18 +38,12 @@ export default async function render_route(request, route) {
headers = lowercase_keys(headers);
const type = headers['content-type'];

const is_type_binary = type && isContentTypeBinary(type);
const is_type_textual = isContentTypeTextual(type);

// validation
if (is_type_binary && !(body instanceof Uint8Array)) {
if (!is_type_textual && !(body instanceof Uint8Array)) {
return error(
`${preface}: body must be an instance of Uint8Array if content type is image/*, audio/*, video/* or application/octet-stream`
);
}

if (body instanceof Uint8Array && !is_type_binary) {
return error(
`${preface}: Uint8Array body must have content-type header of image/*, audio/*, video/* or application/octet-stream`
`${preface}: body must be an instance of Uint8Array if content-type is not a supported textual content-type`
);
}

Expand Down
58 changes: 12 additions & 46 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 88e7639

Please sign in to comment.