Hotwire Discussion

Safari / iOS sends unexpected GET request after form error


I am struggling to understand what is going on with our web app and unexpected behaviour on iOS. I am using Rails with turbo-rails gem v0.7.4. When I submit a form on desktop, there’s just a single PATCH request which redirects to another location on success, or renders form errors on failure:

if @property.update(property_params)
      redirect_to property_path(@property)
      render :property_edit

All is good and dandy. However, when I submit a form using Safari / iOS 14.7.1, straight after PATCH request follows a GET request, which refreshes the form and clears all errors as the form view is refreshed:

Started PATCH "/properties/update/20" for at 2021-08-25 02:04:45 +0300
Processing by PropertiesController#update as HTML
Started GET "/properties/edit/20" for at 2021-08-25 02:04:46 +0300
Processing by PropertiesController#edit as HTML

Does anyone have any explanation to such behaviour and why is this different from desktop? And, most importantly, if there’s a workaround?

If I disable Turbo, behaviour is valid and identical on both desktop and mobile.


Try adding status to redirect:

If you are using XHR requests other than GET or POST and redirecting after the request then some browsers will follow the redirect using the original request method. This may lead to undesirable behavior such as a double DELETE. To work around this you can return a 303 See Other status code which will be followed using a GET request.

redirect_to posts_url, status: :see_other
redirect_to action: 'index', status: 303

see: ActionController::Redirecting

Hello and thank you for your reply.

Unless I misunderstood what you are suggesting, the problem isn’t in redirect, but in rendering post-POST/PUT/PATCH page after form submission, in case of validation errors. On desktop, page is rendered in the same POST/PUT/PATCH request and errors are displayed. On iPhone, another (GET) request mysteriously follows the original form submission for some reason, which refreshes the page and thus clears all errors in the form. And this I cannot explain and cannot locate any information hinting at why this is happening.

Sorry, misunderstood. What about:

if @property.update(property_params)
  redirect_to property_path(@property), status: :see_other
- render :property_edit
+ render :property_edit, status: :unprocessable_entity

I tried that, but result is the same. The status in the console log changes, but that is it. There’s always the second GET request that re-renders the form as if I just clicked the link to edit. Maybe it’s the iOS browser thing, but with Turbo disabled there’s no such issue.

Does this look like the same bug? If a form submission redirects, the target page is rendered twice · Issue #12 · hotwired/turbo-ios · GitHub

There’s a suggestion in the issue on how to fix it, and I made a PR to the demo app to implement that [demo] Always call `session.visit` with options by ghiculescu · Pull Request #18 · hotwired/turbo-ios · GitHub<

Thank you for your reply and attempt to help! Unfortunately, it does not seem like the same issue. There’s no redirect. As stated above, here’s the scenario:

Started PATCH "/properties/update/11" for at 2021-08-25 14:31:59 +0300
Processing by PropertiesController#update as HTML
(some form validation errors occur)
Completed 200 OK in 64ms (Views: 44.3ms | ActiveRecord: 2.4ms | Allocations: 24217)

Started GET "/properties/edit/11" for at 2021-08-25 14:32:02 +0300
Processing by PropertiesController#edit as HTML
(form view is refreshed and all validation errors from PATCH are lost)
Completed 200 OK in 60ms (Views: 30.8ms | ActiveRecord: 2.6ms | Allocations: 32909)

As you can see, GET occurs straight after PATCH and refreshes the page, rendering form without errors, but that GET request shouldn’t even occur and it doesn’t, on desktop browsers.

Oh right, are you using turbo-ios? Or is this just when you edit things through a browser on a phone?

Or is this just when you edit things through a browser on a phone?

It’s when I edit things through a browser on the phone. Ruby on Rails is the backend framework.

Ahhh okay sorry, I misread and assumed it was something else.

In testing our forms in iOS safari, I’m unable to reproduce the issue you are reporting. Can you provide more code?

My code isn’t open source, it’s part of a bigger commercial project. I will see if I’ll find time to make a separate project on github and will be able to isolate the issue.