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

HTML forms do not support the PUT, PATCH and DELETE methods #3577

Open
ericandrewlewis opened this issue Mar 18, 2018 · 28 comments
Open

HTML forms do not support the PUT, PATCH and DELETE methods #3577

ericandrewlewis opened this issue Mar 18, 2018 · 28 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: forms

Comments

@ericandrewlewis
Copy link

Hi! This is my first issue in this repository, I'm sorry if I'm opening this discussion in the wrong place. I searched the mailing list archives and issues for this topic but couldn't find a relevant discussion.

The spec says that the <form> method attribute assumes one of three values: get, post, and dialog.

Can we add support for the put, patch, and delete methods for this attribute?

@annevk
Copy link
Member

annevk commented Mar 19, 2018

Probably not as that would complicate the processing model for <form> quite significantly. In particular, the same origin policy exceptions <form> has today do not allow for these methods. Either we have to forbid them in cross-origin requests or require CORS somehow. Both of those restrictions would be a first for navigations and rather risky.

@js-choi
Copy link

js-choi commented Mar 21, 2018

As a developer, I would love this feature. Those of us who are still interested in this sort of feature may want to make a new thread in the WICG Discourse forum and post their use cases there.

@annevk
Copy link
Member

annevk commented Mar 22, 2018

Just know it's been attempted several times in the past and implementers have rejected it.

@annevk
Copy link
Member

annevk commented Mar 22, 2018

(It even used to be part of Web Forms 2.0.)

@js-choi
Copy link

js-choi commented Mar 22, 2018

Indeed—if I recall, Hickson said long ago that there weren’t clear use cases for them…or was that for JSON form data? Well, either way, that’s why any chance of this happening would require assembling compelling use cases for them and marshaling both coordinated community support and a reasonable specification for the vendors. A tall order, but less likely things have happened…

@annevk
Copy link
Member

annevk commented Mar 22, 2018

I am pretty sure that the main reason implementers have rejected it is complexity.

@ericandrewlewis
Copy link
Author

@annevk thanks for the context, I suspected this would have came up previously. Where would discussion from the previous attempts have taken place? They would be interesting to read.

@annevk
Copy link
Member

annevk commented Mar 22, 2018

https://www.w3.org/Bugs/Public/show_bug.cgi?id=10671 seems to have a lot of it, though not as much the implementer angle.

@zcorpan zcorpan added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: forms labels Sep 1, 2018
@annevk
Copy link
Member

annevk commented May 7, 2020

As an update, #3577 (comment) still applies. We cannot bypass the same-origin policy and enforcing CORS is theoretically possible, but would require integration of that to some extent with navigation, which is completely new ground. Maybe if something like https://wicg.github.io/cors-rfc1918/ motivated adding such complexity to navigation this would become more feasible. But until that happens this isn't worth the significant cost unfortunately.

@lpd-au
Copy link

lpd-au commented May 8, 2020

In particular, the same origin policy exceptions <form> has today do not allow for these methods.

Thanks for your comments @annevk. Can you point me in the direction of where these exceptions are specified? Between GET and POST, they seem to have every property of PUT and DELETE covered; request body, idempotency, navigation, etc... does it raise a fresh security concern or is this a legacy issue where the specification that defines the exceptions repeats only the HTML 4 form methods by name?

Either we have to forbid them in cross-origin requests or require CORS somehow. Both of those restrictions would be a first for navigations and rather risky.

To me, implementing PUT and DELETE with a same-origin policy seems like a sensible minimum viable product, which would at least allow web developers to create html clients for their own REST services. Implementer interest permitting, this could later be extended with CORS support for both PUT and DELETE methods (opt-out) and GET and POST methods (opt-in). Could you also please elaborate on why you previously considered a same-origin policy for PUT and DELETE forms to be 'risky', and whether you still believe this to be the case? How does this compare to, for example:

  1. POSTing to a cross-origin HTTPS resource with an invalid TLS certificate configuration, or
  2. GETting a resource when the network is disconnected/offline, or
  3. POSTing from a HTTPS form to a HTTP resource?

@annevk
Copy link
Member

annevk commented May 8, 2020

HTML defines part of it and so does https://fetch.spec.whatwg.org/. And yes, what HTML forms can do are basically the enshrined exception.

A same-origin mode would similarly be risky (and unclear) as navigation does not have that primitive. So you'd have to define what happens if you get a cross-origin redirect and how that would be handled and such. And come to think of it, there's also a couple POST-specific code paths that would have to be generalized somehow.

@lpd-au
Copy link

lpd-au commented May 8, 2020

HTML defines part of it and so does https://fetch.spec.whatwg.org/. And yes, what HTML forms can do are basically the enshrined exception.

That is to say, the exception could be extended if the specification editors such as yourself thought it prudent? There is no immovable W3C charter issue, for example, or fresh security concern that does not apply to the existing methods?

A same-origin mode would similarly be risky (and unclear) as navigation does not have that primitive. So you'd have to define what happens if you get a cross-origin redirect and how that would be handled and such. And come to think of it, there's also a couple POST-specific code paths that would have to be generalized somehow.

I'm afraid I still don't understand. Perhaps you could define what you mean by risky, or elaborate what some of the risks are? Is there an inherent problem or insurmountable issue with having to define how redirects are handled, or generalising code previously implemented to handle POST? Is this not still significantly less complex than CORS support?

@annevk
Copy link
Member

annevk commented May 8, 2020

No, the same-origin policy cannot be extended further as that would put servers at risk.

The risk is that there are a lot of corner cases to handle and navigation is one of the more broken concepts in the HTML Standard. Same-origin is probably less work than CORS, but it's still a lot of work.

@tkawa
Copy link

tkawa commented May 23, 2020

To help with the discussion, there are two drafts. These are highly complete specifications made as a result of past reviews.

IMHO, the latter has considerably less complexity.

@annevk
Copy link
Member

annevk commented May 24, 2020

Neither of those is close to complete as neither goes into the detailed changes needed to HTML's navigate algorithm.

@alexpetros
Copy link

Hi everyone,

Carson Gross and I have been working on a proposal to make this happen. It addresses many of the concerns that have come up on this issue, as well as blockers from past attempts.

The full writeup is here: "Support PUT, PATCH, and DELETE in HTML Forms". I'd like to highlight two aspects of the proposal, in particular.

Common Patterns

(1) A webapp wants to implement login/logout. Login is handled easily with a POST form, but proper logout support should be:

  • Known to the client to be unsafe, so it doesn't cache or pre-fetch
  • Known to the client to be idempotent, so it can be retried without user confirmation
  • Not in violation of HTTP semantics (GET is for retrieval, POST is for sending data)

The ability to make a button that DELETEs a /session would satisfy these requirements, create the best user experience (no "are you sure?" on a retry), and give developers a more natural solution for logging out than the still-common logout link—the source of a decade of pre-fetching bugs.

(2) A social media webapp wants to implement "groups" functionality. Requirements:

  • Groups have lots of sub-resources (i.e. /group/123/members), so all group-level operations need to be at /group/123, for clarity.
  • Admins can edit group details, but only the group owner can delete the group

The best way to model this is by using separate HTTP methods for editing and deleting i.e. PUT /group/123 to edit the group, and DELETE /group/123 to delete it. By doing so, the webapp can assign different permissions at the router-level, and re-use common permission functions (middleware, annotations, etc); if all unsafe requests have to tunnel through POST /group/123, they risk very common security mistakes like assigning the same permissions to updating and deleting.

Both of these examples are described in more detail in Section 8.

Security and Navigation

For same-origin requests, the browser should simply issue the request; for cross-origin requests, the browser should issue a CORS pre-flight request, and bail (loudly, with a warning screen) if the server does not affirm the request.

Four years ago, @annevk wrote:

The risk is that there are a lot of corner cases to handle and navigation is one of the more broken concepts in the HTML Standard.

and

Maybe if something like https://wicg.github.io/cors-rfc1918/ motivated adding such complexity to navigation this would become more feasible. But until that happens this isn't worth the significant cost unfortunately.

In the time since, both of these have progressed. The navigation standard was updated, making it easier to modify, and Private Network Access appears to be making progress, providing additional justification for implementers. We also consulted implementers about this proposal and were advised that adding CORS to navigation would be preferable to a single-origin mode (this does not imply their endorsement, it's just to note that we asked).

Adding CORS to navigation not only ensures that <form action=/example method=PUT> attribute inherits the exact same security benefits as fetch('/example', { method: 'PUT' }), while not opening up existing servers to new avenues of attack (since they're already available in JS), it also allows HTML authors to replace POST—which has significant CORS exceptions—with methods that are more resistant to CSRF. This would make the median web application more secure today, and potentially pave the way to replace POST with a more secure alternative in the future.

We outline browser behavior specifics, including the CORS algorithm, in Section 4, and discuss security in more detail in Section 5.

We believe that this feature is essential to HTML, for a variety of reasons discussed within, and are interested in helping to move this long-standing request forward, however we can.

@mamund
Copy link

mamund commented Aug 19, 2024

@alexpetros :

happy to see this proposal.

adding here that it would be a good idea to consider how the ETag and Last-Modifed headers can be used to create conditional requests (e.g. avoiding the Lost Update problem).

see https://www.rfc-editor.org/rfc/rfc9110.html#name-validator-fields

@chrishtr chrishtr added the agenda+ To be discussed at a triage meeting label Aug 20, 2024
@jlunman
Copy link

jlunman commented Aug 20, 2024

Deleted my previous comment because the suggestion was clearly half-baked. But I still reiterate my concern about introducing new form methods: How will this impact users on browsers that haven't implemented it yet?

Current browsers only support GET and POST methods, and will default to GET when any other method is specified. So if your browser doesn't support <form method="put">, it will behave like <form method="get"> and submit its form data on the query string. This could lead to information leakage via browser history, server logs, referrer header, etc.

@alexpetros
Copy link

@mamund:

adding here that it would be a good idea to consider how the ETag and Last-Modifed headers can be used to create conditional requests (e.g. avoiding the Lost Update problem).

see https://www.rfc-editor.org/rfc/rfc9110.html#name-validator-fields

It's an honor to see your comment on this proposal, Mike, I'm sure you know it's heavily in debt to your work.

In the RFC, validator fields are included in response to safe requests, which PUT is not, consistent with the same RFC's stance that PUT responses are not cacheable. I think that it certainly makes sense for PUT responses to be able to tell the client "this response is the resource and you can save it", the same way POST/PATCH sort of can, but at least as far as I can tell, that would require a change to HTTP as well as HTML. That's probably a bit more than this proposal can accomplish.

I am very optimistic that better method support will unblock optimizations like that one, because we'll have more developer data to analyze, a wider pool of people who would benefit, and less API work required to make it happen.

@jlunman:

Deleted my previous comment because the suggestion was clearly half-baked. But I still reiterate my concern about introducing new form methods: How will this impact users on browsers that haven't implemented it yet?

At a high level, I think it is more important to get the API right than it is to drive immediate adoption. If you believe, as I do, that HTML will be around for decades, then waiting a couple years before developers feel comfortable using PUT forms is fine price to pay in exchange for the decades in which forms will remain intuitive.

Current browsers only support GET and POST methods, and will default to GET when any other method is specified.

This is nevertheless an important concern, and one of the reasons why I recommend that people never do login with htmx, because it will cause information leakage on browsers with scripting disabled. I think it is mostly resolved by a polyfill, as the only people who would not be covered by this are users who a) use an out-of-date browser and b) have scripting disabled. Given the user profile of someone who browses the web with scripting disabled, I think that number approaches zero in very short order.

Another way to resolve this is just to add an httpmethod field, and also add support for the new methods to method, so that while this remains a live concern, HTML documents can do <form method=POST httpmethod=PUT> and then phase out use of httpmethod once old browsers are out of circulation. We'll see if the spec editors and security teams think that's necessary.

@06b
Copy link

06b commented Aug 20, 2024

@alexpetros:

Another way to resolve this is just to add an httpmethod field, and also add support for the new methods to method, so that while this remains a live concern, HTML documents can do <form method=POST httpmethod=PUT> and then phase out use of httpmethod once old browsers are out of circulation. We'll see if the spec editors and security teams think that's necessary.

I was going to suggest a similar solution to @jlunman's concern by keeping the form owner's method as post and then putting the new method on the formmethod on a submit button.

<form method="post">
    <input type="submit" formmethod="put" value="Submit a message">
</form>

This suggestion however backfired due to the fact that the formmethod attribute invalid value default is the GET state according to Form submission attributes within the spec:

The method of an element is one of those states. If the element is a submit button and has a formmethod attribute, then the element's method is that attribute's state; otherwise, it is the form owner's method attribute's state.

If the spec were updated to allow for the invalid value default of a formmethod to then default to the form owner's method attribute state, then that could allow for what I was going to suggest to work and if the form owner method was invalid, then it could remain as the default of the GET state.

Looking at your suggestion, since formmethod is an attribute for form submissions that may be specified on submit buttons, if we added allowing formmethod attribute to be added to the form element itself, that could allow for <form method="POST" formmethod="PUT"> (I don't love it and it looks super hacky but it allows it) to work, because as of right now it would still default to the method of POST, which would avoid @jlunman's concern.

@jlunman
Copy link

jlunman commented Aug 22, 2024

At a high level, I think it is more important to get the API right than it is to drive immediate adoption. If you believe, as I do, that HTML will be around for decades.

This is very true, and I acknowledge that this feature request dates back well over a decade, and had the change been made back then, it would basically be a non-issue now. So I'd be pleased to see this finally move forward, even if it means I have to wait another decade or so before I consider it safe to use in production.

I think it is mostly resolved by a polyfill, as the only people who would not be covered by this are users who a) use an out-of-date browser and b) have scripting disabled.

There are far more reasons why JS can fail than just being deliberately disabled by users. And it's one thing if it just means the site doesn't work right. It's quite another thing if it results in sensitive data getting exposed.

Another way to resolve this is just to add an httpmethod field, and also add support for the new methods to method, so that while this remains a live concern, HTML documents can do

and then phase out use of httpmethod once old browsers are out of circulation.

I like this. It fits with HTML's long tradition of being backward- and forward-compatible, so that neither users nor browser developers are forced to update in lockstep.

@alexpetros
Copy link

alexpetros commented Aug 22, 2024

There are far more reasons why JS can fail than just being deliberately disabled by users.

Great point. For instance it's hard (at least in my experience) to make sure that every single possible way that a form might enter the DOM is processed by the polyfill.

I like this. It fits with HTML's long tradition of being backward- and forward-compatible, so that neither users nor browser developers are forced to update in lockstep.

I'll think I'll add it to the alternatives section! I'll make note of possibly re-using formmethod at the top-level as well, @06b. I personally find that a bit more confusing than using a new name, but we could mention it. overridemethod could be a plausible name as well.

@alexpetros
Copy link

alexpetros commented Aug 27, 2024

Per this discussion, I've added a section about the possibility of including an additional overridemethod that overrides the method attribute. I think this is sort of an exciting possibility because it resolves my main problem with the current polyfill—that it can't emulate form navigation properly—and allows for a much smoother upgrade path using server middleware.

@Delapouite
Copy link

@alexpetros thanks a lot for your initiative!

Your current document currently has focus on the trio PUT, PATCH, DELETE.

How do you see other HTTP proposals such as the new QUERY method fits into the picture?
https://httpwg.org/http-extensions/draft-ietf-httpbis-safe-method-w-body.html

Should the reflection already provides some answers on how to support custom methods, to also take care of related area of well-known HTTP vocabulary such as WebDAV?
https://en.wikipedia.org/wiki/WebDAV

@alexpetros
Copy link

Hi @Delapouite!

My long-term view is that HTML should support custom methods. This would unlock some very interesting and powerful self-description patterns with relatively little burden on implementers.

That having been said, this proposal focuses on PUT, PATCH, and DELETE support because:

  1. The evidence of demand for these methods is abundant
  2. These methods have existing specifications and implementations, so no HTTP work needs to be done
  3. The API itself is straightfoward (extend the method attribute with three new values)

While I do talk about the possibility of custom methods in the proposal—they were even included in a previous one—they have an API surface that needs to be studied a little more. For instance: how would the form decide whether to use URL parameters or body content? What happens if your custom method gets standardized with behavior your server doesn't expect? I think these questions are easy enough to resolve, but I don't want to to logroll them with support for existing, standardized methods, which don't have them.

I hope that the spec + implementation work required to make PUT, PATCH, and DELETE happen generates momentum for a robust custom methods approach, but even if it doesn't, those three methods alone still generate tremendous value for the ecosystem.

@past past removed the agenda+ To be discussed at a triage meeting label Aug 29, 2024
@AramZS
Copy link

AramZS commented Aug 29, 2024

Glad to see this was picked up at the most recent meeting, I think this work would be extremely valuable, starting with PUT, PATCH, and DELETE which have the clearest mapping to the type of activity we'd like to express through HTML forms regularly, makes a lot of sense to me.

I see there are some concerns about graceful degradation and I think it is reasonable to ask developers who want to use this proposed feature to be able to use feature detection (the implementation should present a way to support feature detection). Forms often have interactivity (and I'd anticipate forms which use PUT, PATCH and DELETE might be more likely to do so) so I don't think it is unreasonable to expect developers to handle detecting the feature and modifying forms accordingly.

I agree that the demand for these types of methods is clear and abundant. There is a lot of "form-like" behavior that attempts to access either these verbs or emulate features that should be connected to these verbs without using the actual FORM functionality. We should push developers towards using FORM for form-like behavior and I think that this proposed change would significantly help with that.

@hannah23280
Copy link

So for the time being, what are the recommended ways to submit form with the PUT, PATCH and DELETE methods

@alexpetros
Copy link

I've made two changes based on feedback from WAHTNOT #10574:

  • Clarified that non-redirect status codes should all be handled the same (i.e. 200 vs 201 vs 202). The server obviously still has to send the appropriate one, but the user agent should render whatever hypermedia the server returns along with it.
  • Changed overridemethod to custommethod, in order to more deliberately pave the way for full custom method support.

@AramZS:

I see there are some concerns about graceful degradation and I think it is reasonable to ask developers who want to use this proposed feature to be able to use feature detection (the implementation should present a way to support feature detection).

I would certainly support a JS-based feature detection mechanism, although I do believe that a lot of the feature's value lies in not having to use JS for it, hence the attempt to provide an HTML-only feature detection mechanism via custommethod. If you have any thoughts on what feature detection you'd like to see in the proposal, please let me know!

@hannah23280:

So for the time being, what are the recommended ways to submit form with the PUT, PATCH and DELETE methods

I think the best way to do so is with a light hypermedia framework, like htmx or turbo. While JavaScript is not capable of creating the experience I'm trying to push here—proper navigation—the frameworks I linked to have nice partial page replacement mechanisms that support all the HTTP methods, and it's a relatively small lift to go from those to this, if this proposal works out.

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