2

Django's PREPEND_WWW plus the Common middleware automatically redirects all root domain traffic to the "www." domain. How do I best achieve the opposite? Under django? Apache? Ngnix?

Bryce
  • 8,313
  • 6
  • 55
  • 73
  • You'll want to do this outside of django. Instructions for [Nginx](http://stackoverflow.com/a/7958540/766952) and [Apache](http://stackoverflow.com/a/1100363/766952). – DanielB Nov 15 '13 at 00:46
  • For a complete answer: why outside of django? And what about www->root in addition to root->wwww? – Bryce Nov 15 '13 at 00:48
  • To save yourself the overhead of hitting django. You'll have to hit nginx/apache before hand, and they can serve the request without having to have django process the request/response. – DanielB Nov 15 '13 at 00:51
  • `non-www`->`www` is done the same as `www`->`non-www`, just reverse the configuration. – DanielB Nov 15 '13 at 00:52
  • I'd do it on the webserver level, but you either use apache or nginx, which answer do u want ? – Mohammad AbuShady Nov 15 '13 at 09:42
  • I tried to write a "good general question" helpful to the largest audience. Thus, the best answer would cover apache, nginx and direct via django. – Bryce Nov 16 '13 at 01:24
  • PREPEND_WWW is the easy answer for non->www, but there's no opposite of it. – Bryce Nov 16 '13 at 05:33

2 Answers2

3

Where, possible, you'll want to do this kind of redirection outside of django. Here are instructions for Nginx and Apache. (You'll need to adjust the config according to desired non-www or www perference.).

As for why to do it outside of django, the answer is performance. There isn't a need here to have django process the request and response, since it can be done earlier in the request lifetime. This means you can save your django processes for when you actually need them.

The only reason you should use PREPEND_WWW, or similar custom middleware, is when you don't have access to the server configuration (such as some shared hosting environments). It's used as a last resort.

Community
  • 1
  • 1
DanielB
  • 2,798
  • 1
  • 19
  • 29
  • How about directly from django, should that be necessary? (in my case it is, as part of the site must use www, and part must not use www). – Bryce Nov 16 '13 at 02:42
  • It still may be possible on apache using mod_rewrite or nginx using a `location` directive. Why does part *have* to use www though? – DanielB Nov 16 '13 at 04:11
  • Part of the site is legacy content which must retain inbound links. The rest of the site is shiny and new, and the chosen convention is root domain. But I'm also here to find in the answers all the options. – Bryce Nov 16 '13 at 05:12
  • Assuming the links would still be valid on the new site, you can use the given solution (which will yield `301 Permanently Moved`). If the old content is not available on the new site, you will need to consider how you will differentiate between a request to the new site and to the old site. `www`-vs-`non-www` may not be suitable for this, as it will probably just confuse your users. – DanielB Nov 16 '13 at 05:25
  • 301 Moved tends to result in some churn for those who validate links. If possible I want the legacy content to serve on either prefix, and the new content to 301 to the root. But for purpose of answering the question, it is fine to just lay out the options. – Bryce Nov 16 '13 at 05:35
  • In that case, you may wish to use internal redirects. This means the redirection will inside the web-server, and the client will end up with a `200 OK` and the requested content. – DanielB Nov 16 '13 at 06:24
  • Right, already got that: the server runs on www and root and serves identical content. Now I want to take all the new content and either hint that the root is rel='canonical', or the stronger step of 301 redirecting any www traffic to the root. – Bryce Nov 16 '13 at 06:27
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/41305/discussion-between-bryce-and-danielb) – Bryce Nov 16 '13 at 06:27
1

As @DanielB it is better for performance to do this outside Django.

But if you want to do it in Django anyway (e.g. you want to learn, or you don't care about performance, or you want to test if your test server doesn't use Apache, or whatever), then you can use this code which I found here:

class RemoveWwwMiddleware():
    def process_request( self, request ):
        try:
            if request.META['HTTP_HOST'].lower().find('www.') == 0:
                from django.http import HttpResponsePermanentRedirect
                return HttpResponsePermanentRedirect(request.build_absolute_uri().replace('//www.', '//'))
        except:
            pass
Mark
  • 18,730
  • 7
  • 107
  • 130