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

Form Submission: Fix the "Double Submit problem" at the spec level #5312

Open
bramus opened this issue Feb 25, 2020 · 5 comments
Open

Form Submission: Fix the "Double Submit problem" at the spec level #5312

bramus opened this issue Feb 25, 2020 · 5 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: forms

Comments

@bramus
Copy link

bramus commented Feb 25, 2020

The other day I wondered: Why is it that browsers don't prevent double form submissions by default? Some users (mistakingly) double click on submit buttons, or re-click a submit button when a request takes up a long time. This way the backend might process certain transactions twice (or more, if the user submitted multiple times).

To work around this on the client we have to rely on JavaScript (which might not be available):

document.querySelectorAll('form').forEach((form) => {
	form.addEventListener('submit', (e) => {
		if (form.classList.contains('is-submitting')) {
			e.preventDefault();
			e.stopPropagation();
			return false;	
		};

		form.classList.add('is-submitting');
	});
});

An attribute on <form> to tweak this behavior – instead of having to rely on JavaScript – would come in handy and form a nice addition to the spec.

I see two options to go forward:

  1. Browsers/the standard keeps the current behavior and allow multiple submits. Developers must opt-in to prevent multiple submissions using a preventmultiplesubmits attribute.
  2. Browsers/the standard adjust the current behavior to only submit forms once. Developers must opt-in to allow multiple submissions using a allowmultiplesubmits attribute.

My personal preference goes to the second option, as it's a safe default and a courteous thing for browsers to do:

  • I can't immediately think of good reasons of why one would allow multiple successive form submits — an area that might require some additional research.
  • Operating systems also work that way: for example, pressing a confirmation button twice won't confirm it twice but only once.

If you search for "Double Submit problem" on a search engine you'll find lots of posts regarding this topic — it's an active problem that lives with developers. The post https://ma.ttias.be/double-clicking-on-the-web/ stood out to me, as it also involves user behavior.

@annevk
Copy link
Member

annevk commented Feb 25, 2020

To be clear, even if this were added the backend would still have to account for double submissions as network conditions might also yield multiple POSTs. Adding this might in fact lead to less robustness as it's no longer as frequently observed.

@annevk annevk added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: forms labels Feb 25, 2020
@bramus
Copy link
Author

bramus commented Feb 25, 2020

Serverside/backend validation and checking is always necessary, as requests can also originate from outside of the browser (e.g. curl). This proposal/request isn't meant to replace serverside validation (which it can't) but only to try and prevent the user from doing wrong things (which they do).

I like to compare it with input type="email" and the like: this input type pushes the user in a certain direction and prevents them from entering wrong input (or at least warns them about it). This however doesn't mean a developer can therefore omit the verification part on the backend, as user-input can never be trusted.

@Yay295
Copy link
Contributor

Yay295 commented Feb 26, 2020

I can't see option 2 being accepted. Adding a new feature is one thing, but changing the default behavior, especially of a very old feature, is a much bigger deal.

Working off the first suggestion then: I think it should have multiple values instead of just is it there or not. For example preventMultipleSubmits="ignore" could work like what you described, while preventMultipleSubmits="disable" would instead disable the form. Other options could be added as well like preventMultipleSubmits="disableSubmit" which only disables the submit button instead of the entire form.

Also, how long until the form can be submitted again? Until the request response arrives, after a certain amount of time, until the page is reloaded, until a new session is started?

@bramus
Copy link
Author

bramus commented Nov 5, 2020

Adding to the log here that yesterday this issue sparked up again with some devs. I've collected the thoughts expressed both here and on Twitter in a blogpost over at https://www.bram.us/2020/11/04/preventing-double-form-submissions/

@tigt
Copy link

tigt commented Jan 17, 2021

I personally fix this problem in the HTML layer with some sort of timestamp or nonce in a hidden input, so the action’s handler can ignore any duplicate submissions if it’s seen them before:

<form method=post>
  <input type=hidden value={{resubmitSentinel}}>
  <!---->
</form>

It’s a little annoying to set up (the hard part is figuring out how to generate resubmitSentinel), but it accounts for both users repeatedly submitting forms and @annevk’s aforementioned network-caused resubmissions.

Maybe this proposed attribute could automatically attach a browser-provided nonce? Something similar to the magic _charset_ input name? Browsers could reuse the code for generating unique multipart/form-data boundaries, I imagine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: forms
Development

No branches or pull requests

4 participants