Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Have option for HTTP redirect to HTTPS #523

ellisonbg opened this Issue · 18 comments

7 participants


It would be nice if requests to HTTP could automatically redirect to HTTPS when SSL is enabled in a Tornado server.


If you have both HTTP and HTTPS in the same tornado process, you must be running two separate HTTPServers (of course such a feature should not be tied to whether SSL is handled at the tornado level, since you could be terminating SSL in a proxy, but since your question stipulated that SSL was enabled in tornado let's focus on this case first). You could simply give the HTTP server a different Application, one that just does this redirect.

I'm not convinced that it's worthwhile to have special-case support for a blanket http-to-https redirect, since the alternative of a separate Application is not that complicated and much more general (supporting different rules for different urls). On the other hand, this does seem more useful than the addslash/removeslash decorators.


I'm in favor of less bloat. Writing your own redirecting Application is dead simple (and more flexible); there's no reason people need this done for them.


That makes perfect sense if you are running the two on different ports, but doesn't help the case of an app on a custom or random port (8000, etc.), where a user may not know whether it's http or https.

What is requested here is for someone who visits http://localhost:8888 to be redirected to https://localhost:8888, instead of the current "Error:...http request" on the server, and "324: ERR_EMPTY_RESPONSE" on the client.

Can you describe how this can be done with current tornado?


@minrk That's not possible - HTTP and HTTPS must run on different ports. The redirection you see on other sites from http:// to https:// works because the first is on port 80, and the second on port 443 - the browser is just hiding the default port numbers from you.


I'm aware of the standard ports, and how that is an easy problem and one that doesn't need solving. This feature request is for the harder one of incorrect request to the actual server (port and all).

SSL is fully aware that it received a plain HTTP request when it fails (it's in the error message), so it must be possible to act on this event.

For example, CherryPy replies with a human-readable message, rather than just closing the connection.

@ellisonbg ellisonbg referenced this issue in ipython/ipython

Redirect http to https for notebook #1460


Interesting. OpenSSL apparently throws an exception with the description "http request" (I assume it comes to this conclusion via some heuristics once the normal SSL handshake fails). If you were going to catch this exception, SSLIOStream would be the place to do it, but that seems like the wrong place to write a response in plain HTTP.

A quick survey of Google, Facebook, and Twitter shows that none of them consider this a big enough problem to handle at all, so I think that a) you shouldn't worry about it, and b) CherryPy-like handling shouldn't be included in Tornado.


A quick survey of Google, Facebook, and Twitter shows that none of them consider this a big enough problem to handle at all, so I think that a) you shouldn't worry about it, and b) CherryPy-like handling shouldn't be included in Tornado.

I agree it makes little sense for a public website, which ~never would be using a manually typed port, but it certainly does for local services on a custom port. This feature request is prompted by the IPython Notebook, where this has already come up plenty of times for users as a minor annoyance.


Ultimately it's up to the user to use a correct url rather than an incorrect one. Some types of mistakes are easy to work around with a simple redirect rule, but this isn't one of them. It's possible to do something clever with this case, but it's pretty tricky and requires violating several layers of abstractions, so I think the right policy here is garbage in, garbage out.

Also consider that redirects from http to https are something of a security vulnerability since the redirect happens outside the SSL protection and is therefore subject to hijacking. In fact, you may be able to use HSTS here so that once a user has connected successfully once, their browser will remember the SSL requirement and not attempt unencrypted access in the future.


Fair enough. If a CherryPy-style solution is not feasible because of where tornado draws its boundaries, then that's the way it is.

garbage in, garbage out

I just have difficulty not wanting to help users, when (unlike garbage in):

  1. the error is simple and obvious (SSL fails with 'http request')
  2. the solution is simple and obvious (plain reply with "I'm https, not http!")

But I understand that with the way tornado is organized, it may not be possible for the implementation to be clean or simple.

Also consider that redirects from http to https are something of a security vulnerability

That's probably why CherryPy uses a message rather than a redirect. This would still be a huge improvement.


I think the real reason cherrypy uses an error rather than a redirect is that it can't know what to redirect to. OpenSSL swallowed the request so cherrypy can't see e.g. the Host header, all it knows is that some HTTP request was attempted. To redirect it would have to use some configured default address (or implement some much more complicated scheme to capture the data for HTTP use before passing it off to SSL). You could probably return an error page with a javascript redirect in it though.


I expect you guys aren't interested, but if ever you are, here's a quick stab at how gross such a thing might look:


Then this version of the hello world example will reply to HTTP requests on the HTTPS port with a configurable message.

I didn't know a better way to propagate an option for SSLIOStream than piggy-backing on ssl_options, but since this is just a demo, I don't think that really matters.

@bdarnell bdarnell closed this

Since a lot of people find this thread, I'll add what I ended up doing. I do a configurable redirector (it can be turned off in my code). I use the built-in Python BasicHTTPServer stuff. Works nicely, no tornado patches to carry, minimal overhead.


Yet again, I wish this was revisited.

@rgbkrk rgbkrk referenced this issue in ipython/docker-notebook

Generate certificates, use a password #1


@dkavanagh That's a two-port solution (which you can do in tornado without multiple threads; just start two HTTPServers on the same IOLoop). This thread is about trying to do the same thing on a single port, which is only possible in a very hacky way. I'm still uncomfortable with the idea of intercepting (certain) ssl errors and doing stuff with the socket object while it's in a poorly-defined state.


Most responders have focused on SSL aspect of this issue, which applies when a Tornado deployment aims to handle SSL and plain/text requests directly.

But if you're behind an SSL-terminating reverse proxy like Heroku HTTP router, it would still be great to have an option that acts in concert with xheaders=True to force http to https redirections.

I've cobbled together this hack as a demo.


@paxan That's a fair point; the X-Forwarded-Proto situation doesn't have the fundamental problems of the single-port TLS and cleartext situation. This looks like it needs a solution that doesn't involve overriding non-public methods (although can you not configure heroku to do the http-to-https redirect for you?). It can be done cleanly today with the HTTPServerConnectionDelegate and HTTPMessageDelegate interfaces, but it's verbose. We should consider either including a wrapper for the Application that does this for you, or some extra sugar to make it easier to wrap Application. In either case, this is really a separate issue than the mixed single-port issue discussed in this thread, so it should probably be in a new github issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.