14

We can force SSL in apache servers with following config:

RewriteEngine On 
RewriteCond %{HTTPS} off 
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Here, we tell the apache server that return a 301 Moved Permanently response to the client. But there is another status 101 Switching Protocols and I think this status code is more suitable since we are switching from plain HTTP to HTTPS.

Am I right? Anything wrong? Which status code should I use?

3 Answers 3

24

The correct status code to use here is without a doubt 301 Moved Permanently.

101 Switching Protocols is an internal status code that a server generally uses to automatically negotiate certain types of connections. It's not used when changing the URL from http to https. If you're curious about how it works, you can read about the 101 status code and the protocol upgrade mechanism on MDN, but you'll never need to know about it as a webmaster.

As a general rule, you should never directly use 100 series status codes unless you are actually developing web server software. The 300 and 400 series codes (especially 301, 302, and 404) are the ones you'll want to pay attention to when running a simple website.

5
  • Tiny correction: that a server generally uses to automatically negotiate certain types of connections should read that a *client* uses to request to change to another protocol.
    – AnoE
    Commented Mar 28, 2022 at 14:08
  • 4
    @AnoE 101 is a server status code; it's used by the server to "accept" the client's request to change to another protocol, not by the client to request a change to another protocol. From the MDN article: "The Upgrade header field is used by clients to invite the server to switch to one of the listed protocols, in descending preference order ... If the server decides to upgrade the connection, it sends back a 101 Switching Protocols response status" Commented Mar 28, 2022 at 16:38
  • 1
    Yes, my comment was not formulated in a great way. The client initiates the upgrade, the server responds with 101, was just nitpicking because your answer leaves the impression that the server initiates the upgrade.
    – AnoE
    Commented Mar 29, 2022 at 12:53
  • 1
    "You should never use 100 or 200 series status codes unless you are actually developing web server software" - Maybe true of 100, but definitely not true of the 200 series. For example, if you are implementing a RESTful interface you will need to respond with 201 Created on resource creation and maybe 202 Accepted or 204 No Content when a resource is deleted, depending on your model. Also, if you support range requests in your application, you may need to report 206 Partial Content.
    – HappyDog
    Commented Mar 29, 2022 at 22:53
  • @HappyDog You're right, fixed. Commented Mar 30, 2022 at 0:20
12

No - 101 Switching Protocols is not appropriate for redirecting to HTTPS, as this status indicates that the current connection should be upgraded to the new protocol, whereas a redirect instructs the client (browser) to retry the request at a new location.

The confusion may arise because, from your point of view, the two places are the same location, with the only difference being the protocol/port number used to access it. However, from the perspective of the URI scheme, these are two separately-addressable locations (as the protocol is part of the address), hence a redirect is the correct method to use.

With an upgrade request, the 101 Switching Protocols header is output and then the server immediately switches to using the new protocol on the same connection.

4
  • As in: If this were what happens, the communication would continue over port 80, and encryption established within. Commented Mar 29, 2022 at 18:17
  • You can implement TLS in this manner, though it's not very common. See en.wikipedia.org/wiki/HTTP/1.1_Upgrade_header#Use_with_TLS for a bit more detail. It is most commonly used for websockets, which use a binary protocol, negotiated over HTTP using the Upgrade header and a 101 response code.
    – HappyDog
    Commented Mar 29, 2022 at 22:46
  • @HappyDog Is there an example of such a server?
    – 9pfs
    Commented Mar 30, 2022 at 4:33
  • I don't have an example, but I'm sure they exist.
    – HappyDog
    Commented Mar 30, 2022 at 13:17
3

RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

It seems to me that the simpler regex .* should work just as well.

Here, we tell the apache server that return a 301 Moved Permanently response to the client. But there is another status 101 Switching Protocols and I think this status code is more suitable since we are switching from plain HTTP to HTTPS.

No, the correct status code is 301, for two reasons:

  1. This is a redirect. Per RFC 7231, section 6, redirects are indicated by the 3xx series of status codes. Section 6.4.2 defines the 301 Moved Permanently status code, which is clearly the appropriate one for HTTP → HTTPS redirects.
  2. Apache does not take kindly to redirects with status codes outside the 3xx series:

However, if a status code is outside the redirect range (300-399) then the substitution string is dropped entirely, and rewriting is stopped as if the L were used.

A redirect instructs the web browser to create a new HTTP request. In this case, that request requires a new connection to a new origin: changing either the scheme or the port changes the origin, and in this case, you change both. This is very different to the 101 Switching Protocols status code, which immediately causes the current connection to switch to some other protocol. This other protocol could be anything (as agreed between the server and client), but will probably have nothing to do with HTTP!

2
  • "It seems to me that the simpler regex .* should work just as well." Or, indeed, simply ^ which might be a tiny bit faster, depending on the regex engine, since it doesn't need to walk all over the string. Commented Mar 30, 2022 at 13:37
  • @UlrichSchwarz I don’t actually use Apache. But lots of other people do, and I assumed a quick web search would sort this out. I was wrong. I kept finding things like RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 or even RewriteRule ^/?(.*)$ https://%{SERVER_NAME}/$1. How is there no canonical answer for this? Indeed, how is there no built-in feature for this? Commented Mar 30, 2022 at 13:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.