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

Add functionality to override http methods (issue #1046) #2989

Merged
merged 11 commits into from
Jan 11, 2022

Conversation

am283721
Copy link
Contributor

@am283721 am283721 commented Dec 6, 2021

See: #1046

In short: Given that the only valid <form> methods are GET and POST, functionality is provided to override this limitation and allow the use of other HTTP verbs. This is particularly helpful when ensuring your application works even when javascript fails or is disabled.

I could see this potentially needing to be an RFC due to either the impact of the change or the differences in opinion about how it should be implemented or what the default config values should be. Let me know if this is the case.

Please don't delete this checklist! 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. All changesets should be patch until SvelteKit 1.0

@changeset-bot
Copy link

changeset-bot bot commented Dec 6, 2021

🦋 Changeset detected

Latest commit: e3cdab5

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

This PR includes changesets to release 2 packages
Name Type
@sveltejs/kit Patch
create-svelte 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

pnpm-lock.yaml Outdated
@@ -30,7 +30,7 @@ importers:
'@sveltejs/eslint-config': github.com/sveltejs/eslint-config/9a7d728e03ac433e5856a6e06775c17ee986d641_d9525e585486a10ae6317f3f61e9597f
Copy link
Member

Choose a reason for hiding this comment

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

you shouldn't need to modify the lockfile. there's a merge conflict since this file is being changed, so it'd be nice to drop it from the PR

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted to the previous lockfile. It appears the build is failing due to the new config options.

Unexpected option config.kit.methodOverride

I'm assuming Netlify is building the create-svelte apps using the version of sveltekit provided by npm, and not this version of the kit? How is this typically handled?

Given that the only valid `<form>` methods are GET and POST, functionality is provided to override this limitation and allow the use of other HTTP verbs. This is particularly helpful when ensuring your application works even when javascript fails or is disabled.

- Disabled by default to prevent unintended behavior for those who don't need it
- For security purposes, the original method on the form must be `POST` and cannot be overridden with `GET`
Copy link
Member

Choose a reason for hiding this comment

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

this is a bit vague. it'd be better if we can say something more specific

Suggested change
- For security purposes, the original method on the form must be `POST` and cannot be overridden with `GET`
- To protect against CSRF attacks, the original method on the form must be `POST` and cannot be overridden with `GET`

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed. Although I'm not sure if this is for CSRF protection or for protection against other attack vectors (cache poisoning was the example given: #1046 (comment)).

Unfortunately I lack expertise in this field. Maybe @Prinzhorn could approve your suggestion or provide a more detailed/accurate statement?

Choose a reason for hiding this comment

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

I don't think we need to be that specific and it's also not just a security thing. GET has vastly different semantics from POST, PUT etc. We should focus on why the feature exist, what problem it solves. I don't see any problem being solved by changing the method from/to GET.

I'd shorten the paragraph and the two bullet points to something like:


In contrast to fetch the only valid methods for a <form> are GET and POST. Svelte allows you to override the <form> method to workaround this limitation if you need to. That way your application can transparently work when JavaScript fails or is disabled by using fetch and <form> interchangeably with the same endpoint.

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 like your version of why this feature exists but I'm unsure about removing those 2 bullet points. It should be pointed out that the feature needs to be enabled by the user. The defaults are noted later in the configuration section but they might not notice that. And explaining that the form method must be POST and cannot be overridden with GET will prevent users from using this feature incorrectly and forcing them to figure out what is wrong when they receive build errors or their app doesn't function as expected.

Choose a reason for hiding this comment

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

I agree about documenting everything. But for me docs are a last resort (the actual text, anything beyond skimming through code examples) when things already went wrong and I need to figure out why. But we can do much better. During dev when we see _method and methodOverride is disabled we can tell the developer that it needs to be enabled. Same if we see _method with something other than POST. Same for all other cases that are currently silently ignored. If the method is not in allowedMethods arguable it should even return a 400 in production. Or at the very least during dev it should tell you. We have the knowledge, let's not make the user run into unexpected behavior (e.g. silently ignoring _method for GET). Instead let's fail as loud as possible so they don't need to open their browser to actually read the docs or search though /issues. Let them stay in the zone and be like "oh, I need to set enabled: true, gotcha, thanks friendly error message".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed. Can anyone tell me how compile/build warnings are generated in Sveltekit?

And I'm on the fence regarding returning a 400 if the method isn't in allowed methods, but I agree silently ignoring it is probably not the correct action. I'd like to handle it similar to other scenarios in Sveltekit.

documentation/docs/14-configuration.md Outdated Show resolved Hide resolved
packages/kit/src/runtime/server/index.js Outdated Show resolved Hide resolved
packages/kit/src/runtime/server/index.js Outdated Show resolved Hide resolved
Given that the only valid `<form>` methods are GET and POST, functionality is provided to override this limitation and allow the use of other HTTP verbs. This is particularly helpful when ensuring your application works even when javascript fails or is disabled.

- Disabled by default to prevent unintended behavior for those who don't need it
- For security purposes, the original method on the form must be `POST` and cannot be overridden with `GET`

Choose a reason for hiding this comment

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

I don't think we need to be that specific and it's also not just a security thing. GET has vastly different semantics from POST, PUT etc. We should focus on why the feature exist, what problem it solves. I don't see any problem being solved by changing the method from/to GET.

I'd shorten the paragraph and the two bullet points to something like:


In contrast to fetch the only valid methods for a <form> are GET and POST. Svelte allows you to override the <form> method to workaround this limitation if you need to. That way your application can transparently work when JavaScript fails or is disabled by using fetch and <form> interchangeably with the same endpoint.

documentation/docs/01-routing.md Outdated Show resolved Hide resolved
documentation/docs/01-routing.md Outdated Show resolved Hide resolved
@netlify
Copy link

netlify bot commented Jan 7, 2022

❌ Deploy Preview for kit-demo failed.

🔨 Explore the source changes: 4c3b054

🔍 Inspect the deploy log: https://app.netlify.com/sites/kit-demo/deploys/61db386281b2450007c38c32

Copy link
Member

@Rich-Harris Rich-Harris left a comment

Choose a reason for hiding this comment

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

Thanks, this is great.

It's always a good idea to avoid things like 'both', since it's not future-proof — if we decided we wanted to support method overrides via headers, for example (which is sometimes used to get around firewalls that disallow non-GET/POST requests), then 'both' would need to become 'all', which would be a breaking change.

If we implement #70 (comment), we'll no longer be able to read form data before selecting a handler, which means that the hidden input method won't work in future.

What I'd suggest, therefore, is something like the following defaults...

methodOverride: {
  allowed: [],
  header: null,
  parameter: '_method'
}

...which would typically be used like so:

methodOverride: {
  allowed: ['put', 'delete']
}

// or
methodOverride: {
  allowed: ['put', 'delete'],
  header: 'x-http-method-override'
}

enabled is unused here because it's arguably redundant — it's enabled if you specify allowed methods, disabled otherwise.

packages/kit/src/runtime/server/index.js Outdated Show resolved Hide resolved
@netlify
Copy link

netlify bot commented Jan 11, 2022

❌ Deploy Preview for kit-demo failed.

🔨 Explore the source changes: e3cdab5

🔍 Inspect the deploy log: https://app.netlify.com/sites/kit-demo/deploys/61dd01a8c38474000773170b

@Rich-Harris Rich-Harris merged commit 3523d38 into sveltejs:master Jan 11, 2022
@Rich-Harris
Copy link
Member

Wonderful, thank you!

@brandonleboeuf
Copy link

I see that this change has been made in the repo, but they are not present when npm init svelte@next is run.

Getting these errors still
Screen_Shot_2022-01-15_at_4 57 05_PM

@am283721
Copy link
Contributor Author

am283721 commented Jan 16, 2022

@Rich-Harris @benmccann @ignatiusmb

Edit: Thanks @geoffrich, probably related to the svelt.config.js file in the shared folder

The changeset for this PR includes both the @sveltejs/kit and create-svelte packages, but it looks like the changes to the create-svelte template aren't included when scaffolding a new project a thus the new config settings aren't copied over.

Specifically this file: packages/create-svelte/templates/default/svelte.config.js

I'm new to using changesets, so it may have been something I did wrong. Could you help take a look at this?

@geoffrich
Copy link
Member

@am283721 Thanks for the report, I don't think this is related to the changeset. See the issue I opened above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants