Yahya Uddin
Yahya Uddin

Reputation: 28861

Which browsers support 307/308 redirects and how do they handle them?

307 & 308 redirects (https://www.rfc-editor.org/rfc/rfc7538) is accepted by most modern browsers.

However upon google-ing a lot, I am unable to find a list of browser versions that support 307/308 redirects. Many of the posts like: What's the deal with HTTP status code 308? simply ask if 308 redirects is supported or not.

I am aware that some older browsers don't support 307/308 redirects (https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/308), but it's not clear which browser version doesn't.

So my question is, which browser versions support 307/308 redirects?

Also how do older browser handle this status code? Do they just fail?

Upvotes: 7

Views: 8444

Answers (4)

PHP Guru
PHP Guru

Reputation: 1558

You can detect browsers that support 308 responses by checking for the upgrade-insecure-requests HTTP header. This header was added to browsers in 2015 less than a year after support for 308 responses were added. Therefore you can bet that any browser sending a upgrade-insecure-requests: 1 request header already supports 308 responses.

The HTTP Upgrade-Insecure-Requests request header sends a signal to the server expressing the client's preference for an encrypted and authenticated response, and that it can successfully handle the upgrade-insecure-requests CSP directive.

The spec says that it must be sent along with requests for both insecure and secure URLs if HSTS is not preloaded.

User agents MUST send an Upgrade-Insecure-Requests header field along with requests for a priori insecure URLs.

User agents MUST send an Upgrade-Insecure-Requests header field along with requests for [https and wss] URLs whose url’s host is not a preloadable HSTS host.

The spec goes on to say that even if HSTS is preloaded, this header should still periodically be sent and in practice even with HSTS preloaded, it is always sent except when requesting embedded content like images.

When the header is not sent, it is easy to provide a fail-safe fallback that mimics a 308 response like this:

function _308($uri) {
    header('vary: upgrade-insecure-requests');// Don't cache if header varies
    if (!empty($_SERVER['HTTP_UPGRADE_INSECURE_REQUESTS'])) {
        // upgrade-insecure-requests: 1
        // Safe to use 308 response code
        header('location: '.$uri, true, 308);
    }
    elseif (in_array($_SERVER['REQUEST_METHOD'], ['GET','HEAD'])) {
        // When the request method is GET or HEAD
        // a 301 response has the same effect.
        header('location: '.$uri, true, 301);
    }
    else {
        // 307 responses were introduced in 1999
        // and are now universally supported.
        // Browsers don't cache 308 responses
        // when the request method is POST,
        // so 307 has the same effect.
        header('location: '.$uri, true, 307);
    }
    exit;
}

Upvotes: 0

PHP Guru
PHP Guru

Reputation: 1558

Update:

My original answer got a lot of down votes. Here is my updated answer. My original answer can still be found below.

You could detect browsers that support 308 responses by checking for the upgrade-insecure-requests header. This header is used in nearly every request sent by modern browsers. The absence of this header doesn't necessarily mean lack of 308 support, but you could provide a fallback that mimics a 308 response like this:

function _308($location) {
    header('vary: upgrade-insecure-requests');// Don't cache if header varies
    if (!empty($_SERVER['HTTP_UPGRADE_INSECURE_REQUESTS'])) {
        // Safe to use 308 response code
        header('location: '.$location, true, 308);
    }
    elseif (in_array($_SERVER['REQUEST_METHOD'], ['GET','HEAD'])) {
        // When the request method is GET or HEAD a 301 response will suffice.
        header('location: '.$location, true, 301);
    }
    else {
        // 307 responses were introduced in 1999 and are now universally supported.
        // Browsers respond the same as with 308 when request method is POST.
        header('location: '.$location, true, 307);
    }
    exit;
}

This seemed like a better answer than the solution I provided that got 4 down votes (below). HTTP/2 web browsers do universally support 308 responses, but detecting browser support for HTTP/2 server-side is frequently not feasible.


Original Answer:

308 redirects were introduced just before HTTP/2. So theoretically 308 redirects are supported on all browsers that support HTTP/2 and compatibility can be detected by detecting the use of HTTP/2 or better. Obviously this only works if your web server supports HTTP/2 and you are not behind a CDN.

So what you should do is detect the server protocol. If HTTP/2 or better is being used, you can use a 308 redirect and trust that it will work as expected. Otherwise use a 307 redirect which has been around since about 1999 and is supported in all modern browsers. In practice 308 and 307 are handled the same when the request method is POST anyway, since neither is cached in that case.

If that isn't good enough, I recommended including a form in the web page body that can be used to re-submit the submitted POST variables at the new location. If the 307/308 response code is not recognized, the form will be displayed to the user and the redirect will be able to be completed manually. See RFC 2616:

The temporary URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s) , since many pre-HTTP/1.1 user agents do not understand the 307 status. Therefore, the note SHOULD contain the information necessary for a user to repeat the original request on the new URI.

https://www.rfc-editor.org/rfc/rfc2616#page-65

Upvotes: -4

monty
monty

Reputation: 1590

As of 20 Feb 2018, not even all modern/supported browsers support it due to lack of support for IE 11 on Windows 7&8.1:

  • Fail - IE 11 (Version 11.0.9600.18893) on Windows 7. On using a 308 in a site, the browser just appears to hang and not load anything. [Edit] As of 25 July 2018, this is still failing (Version 11.0.9600.19035) - checked just in case, you know, MS decided to do the world of devs a favour.
  • Pass - IE 11 (Version 11.786.15063.0) on Windows 10
  • Pass - Edge (Version 40.15063.674.0) on Windows 10
  • Pass - Chrome (Versions 63.0.3239.132 and 63.0.32.132) on Windows 7 and Mac OS 11.6 respectively
  • Pass - Opera (Version 50.0.2762.67) on Mac OS 11.6
  • Pass - Firefox (Versions 54.0.4 and 47.0.2) on Mac OS 11.6 and Windows 7 respectively
  • Pass - Safari (Version 11.0.3) on Mac OS 11.6

You can test if your browser supports 308 redirects here: http://webdbg.com/test/308/

Suggest using 301 or 307 as the current solution until IE and/or Windows 7&8.1- dies a horrible and painful death (As Microsoft are not planning on ever adding 308 support to IE on Windows 7/8.1).

[Edit 29 Jan 2020] So official support for Windows 7 ended earlier this month (on 14 Jan to be precise) and users on this platform are now being strongly encouraged to upgrade to Win10 so expect to see a precipitous drop in usage statistics.

Upvotes: 9

Julian Reschke
Julian Reschke

Reputation: 42025

All current browsers support 308s (AFAIU).

See https://greenbytes.de/tech/tc/httpredirects.

Upvotes: 0

Related Questions