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

Encode HTTP method into Request body as _method #370

Merged
merged 1 commit into from
Aug 12, 2022

Conversation

seanpdoyle
Copy link
Contributor

Browsers do not handle <form> element submissions with a [method]
value other than get or post. This also applies to <form> elements
submitted with submitter elements that declare [formmethod] values
other than get or post.

To circumvent that constraint, Rails form builders encode other verbs
into a _method parameter that is forwarded to the server.

On the other hand, Turbo's reliance on fetch means that it can
lift [method] or [formmethod] values directly to fetch calls,
regardless of verb.

The way that Rails responds to DELETE or PATCH requests submitted in
that manner differs from those with _method=DELETE or _method=PATCH.
Primarily, controllers that call redirect_to default to using a 302
Found
status. When a Turbo request with PATCH receives a 302
response, the subsequent request to the resource is also made with the
PATCH verb
, often resulting in unintended side-effects or unhandled
requests.

The Turbo documentation suggests responding to those requests with 303
See Other
instead. This is sound advice, and should be applied.

However, for Rails applications migrating to Turbo from Unobtrusive
JavaScript, making that change application-wide can be demanding.

For reasons outside the scope of the pull request, Rails' internal
machinery redirects requests made with POST verbs that encode a
_method parameter in a way that doesn't require a 303.

This commit transforms the existing turbo:submit-start event listener
into a turbo:before-fetch-request listener that transforms requests
with methods other than POST into POST requests that encode their
methods as _method.

The net result is that migrating applications can gradually introduce
303 See Other redirects at their own pace.

Browsers do not handle `<form>` element submissions with a `[method]`
value other than `get` or `post`. This also applies to `<form>` elements
submitted with submitter elements that declare `[formmethod]` values
other than `get` or `post`.

To circumvent that constraint, Rails form builders encode other verbs
into a `_method` parameter that is forwarded to the server.

On the other hand, Turbo's reliance on [fetch][] means that it can
lift `[method]` or `[formmethod]` values directly to `fetch` calls,
regardless of verb.

The way that Rails responds to `DELETE` or `PATCH` requests submitted in
that manner differs from those with `_method=DELETE` or `_method=PATCH`.
Primarily, controllers that call `redirect_to` default to using a [302
Found][] status. When a Turbo request with `PATCH` receives a `302`
response, the subsequent request to the resource is _also made with the
PATCH verb_, often resulting in unintended side-effects or unhandled
requests.

The Turbo documentation suggests responding to those requests with [303
See Other][] instead. This is sound advice, and _should_ be applied.

However, for Rails applications migrating to Turbo from Unobtrusive
JavaScript, making that change application-wide can be demanding.

For reasons outside the scope of the pull request, Rails' internal
machinery redirects requests made with `POST` verbs that encode a
`_method` parameter in a way that doesn't require a `303`.

This commit transforms the existing `turbo:submit-start` event listener
into a `turbo:before-fetch-request` listener that transforms requests
with methods other than `POST` into `POST` requests that encode their
methods as `_method`.

The net result is that migrating applications can gradually introduce
`303 See Other` redirects at their own pace.

[_method]: https://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-patch-put-or-delete-methods-work-questionmark
[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
[302 Found]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302
[303 See Other]: https://turbo.hotwired.dev/handbook/drive#redirecting-after-a-form-submission
@@ -13,7 +13,7 @@
"release": "npm publish && git commit -am \"$npm_package_name v$npm_package_version\" && git push"
},
"dependencies": {
"@hotwired/turbo": "^7.1.0",
"@hotwired/turbo": "hotwired/dev-builds#@hotwired/turbo/28a5dc4",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will need to be ^7.2.0 once a release is cut.

@dhh dhh merged commit 78feb51 into hotwired:main Aug 12, 2022
@seanpdoyle seanpdoyle deleted the submission-method-encoding branch August 12, 2022 12:03
dhh added a commit that referenced this pull request Sep 13, 2022
* main:
  Allow additional attributes on the `turbo_stream_action_tag` helper (#373)
  Encode HTTP method into Request body as `_method` (#370)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants