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

[fix] Expand list of allowed mime types for binary bodies #1687

Merged
merged 21 commits into from
Jul 12, 2021

Conversation

JeanJPNM
Copy link
Contributor

@JeanJPNM JeanJPNM commented Jun 14, 2021

Fixes #1438 by expanding the list of allowed mime types for binary bodies.
This allows an endpoint to return a response body with the most commonly used binary mime types.

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpx changeset and following the prompts

@changeset-bot
Copy link

changeset-bot bot commented Jun 14, 2021

🦋 Changeset detected

Latest commit: e4fac6d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@sveltejs/adapter-cloudflare-workers Patch
@sveltejs/adapter-netlify Patch
@sveltejs/kit Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rmunn
Copy link
Contributor

rmunn commented Jun 15, 2021

I think you need to look at https://github.com/sveltejs/kit/pull/1382/files, which added those checks, and make sure you've thought about all the other changes that PR made and whether they will still work if you remove those checks. For example, #1382 changes packages/adapter-cloudflare-workers/files/entry.js to return a Uint8Array if (and only if) the content type includes "application/octet-stream", and otherwise it returns request.text(). What's going to happen in that function if the content-type is "image/jpeg" and the request body was an image? Is request.text() going to be the right return value, or not? There are many other places where the text "application/octet-stream" appears in #1382's changes. Some of them may not need to be changed if you remove those checks, but some of them might. They definitely all need to be considered.

@JeanJPNM JeanJPNM changed the title Allow binary bodies with any content type Allow binary response bodies with any content type Jun 15, 2021
@JeanJPNM
Copy link
Contributor Author

JeanJPNM commented Jun 15, 2021

I can't think of a better solution, what do you think?

/** @param {string} type */
function isBinaryContentType(type) {
	return (
		type.startsWith('image') ||
		type.startsWith('audio') ||
		type.startsWith('video') ||
		type.includes('application/octet-stream')
	);
}

This would work in most cases, but should this be updated when someone wants to use a different content type header or should they just use application/octet-stream?

@JeanJPNM JeanJPNM changed the title Allow binary response bodies with any content type Allow binary bodies with any content type Jun 15, 2021
@JeanJPNM
Copy link
Contributor Author

Is there a way to share core logic with the adapters?
I was thinking of making a function to make updating the constraints for binary content easier

@benmccann benmccann changed the title Allow binary bodies with any content type [fix] Allow binary bodies with any content type Jul 3, 2021
@@ -63,9 +63,9 @@ export default async function render_route(request, route) {
if (
typeof body === 'object' &&
!(body instanceof Uint8Array) &&
(!type || type === 'application/json')
(!type || type === 'application/json' || type === 'application/json; charset=utf-8')
Copy link
Contributor Author

@JeanJPNM JeanJPNM Jul 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use type.startsWith('application/json') since the presence (or absence) of the encoding does not change the behavior of the code

@JeanJPNM JeanJPNM changed the title [fix] Allow binary bodies with any content type [fix] Expand list of allowed mime types for binary bodies Jul 4, 2021
@benmccann
Copy link
Member

Is there a way to share core logic with the adapters?

Here are some examples where we do that:

import { getRawBody } from '@sveltejs/kit/node'; // eslint-disable-line import/no-unresolved

export { fetch, Response, Request, Headers } from '@sveltejs/kit/install-fetch'; // eslint-disable-line import/no-unresolved

@@ -37,24 +38,27 @@ export default async function render_route(request, route) {
headers = lowercase_keys(headers);
const type = headers['content-type'];

const is_type_binary = isContentTypeBinary(type);
/** @type {import('types/hooks').StrictBody} */
let normalized_body;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move this line back down where it was originally. No reason to declare it higher up since it's not used yet

@benmccann
Copy link
Member

lgtm once the tests are passing. can you add a changeset as well?

@benmccann benmccann merged commit 7faf52f into sveltejs:master Jul 12, 2021
* @param {string} content_type The `content-type` header of a request/response.
* @returns {boolean}
*/
export function isContentTypeBinary(content_type) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic is possibly still too blunt. There are at least a few content types I'd consider common for which I think this would return the wrong result:

  • image/svg+xml
  • application/zip
  • application/pdf

An escape hatch for the developer here might be useful too given all the potential edge cases that the wonderful world of mime types involves.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that's why I made #1829

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sent #1890 to help with this

@JeanJPNM JeanJPNM deleted the allow-any-binary-content branch July 12, 2021 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Serving images from endpoint routes no longer possible
4 participants