Read more

HTTP 302 redirects for PATCH or DELETE will not redirect with GET

Henning Koch
February 04, 2016Software engineer at makandra GmbH

A HTTP 302 Found redirect to PATCH and DELETE requests will be followed with PATCH or DELETE. Redirect responses to GET and POST will be followed with a GET. The Rails form_for helper will use a workaround to send POST requests with a _method param to avoid this issue for PATCH/DELETE.

Illustration web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
Read more Show snapshot

If you make requests yourself, watch out for the following behavior.

When you make an AJAX request PATCH /foo and the /foo action redirects to /bar, browsers will request PATCH /bar. You probably expected the second request to be GET /bar, since we're used to redirects always resulting in a GET request.

# Browser sends
PATCH /foo HTTP/1.1

# Server responds
HTTP/1.1 302 Found
Location: /bar

# Browser follows redirect
PATCH /bar

# Server responds
HTTP/1.1 404 Not Found

This is also true on some browsers for DELETE, or in general for any AJAX call that is neither GET or POST.

Some workarounds for this issue below.

Fix on the server: Redirect with a modern status code

If your redirecting action redirects with a HTTP status code of 303 See Other the browser will always follow up with a GET request, even if the requesting method is PATCH or DELETE:

def foo
  redirect_to '/bar', status: :see_other

See Modern HTTP Status codes for redirecting for more background.

Fix on the client: Make a POST request with method override

The default configuration Rails and Sinatra includes a Rack middleware Show snapshot that lets you control the HTTP method used for routing by POSTing with a _method param.

In jQuery this would be:

$.ajax('/foo', { type: 'POST', data: { _method: 'PATCH' } });

Since the request is now a POST for the browser, it will follow a redirect with GET as expected.

This is also what Unpoly Show snapshot or the Rails unobtrusive Javascript adapter does when you annotate a link with data-method="PATCH".

Posted by Henning Koch to makandra dev (2016-02-04 08:47)