0

I'm running Django 1.8, Python 2.7. I have noticed a problem on my site with redirects which seems only to affect my production server using HTTPS protocol, but not staging or dev servers running plain HTTP.

As examples, I've identified two simple things which do not currently work for me over HTTPS:

  1. Visiting https://www.eduduck.com/support/thanks with no trailing slash redirects to https://www.eduduck.com/ instead of appending a slash and redirecting to https://www.eduduck.com/support/thanks/ as I would have expected with (default settings) APPEND_SLASH = True.

  2. Submitting a valid support form 'wrongly' redirects to https://www.eduduck.com/ site base url when using HTTPS but works correctly with HTTP, redirecting to /support/thanks/

It's all routine stuff, or should be. Very perplexed by this; any pointers most gratefully received. NB: Problem only appears under HTTPS

support/urls.py

from django.conf.urls import url
from django.views.generic import TemplateView

from . import views

urlpatterns = [
    url(r'^$', views.support, name='support'),
    url(
        r'^thanks/$',
        TemplateView.as_view(template_name ='support/thanks.html')),
]

support/forms.py

from django import forms

class SupportForm(forms.Form):
    """General request for support or contact"""
    subject = forms.CharField(max_length = 100)
    email = forms.EmailField(label='Your email')
    message = forms.CharField(widget = forms.Textarea)

    def clean_message(self):
        """Sensible messages cannot be too short"""

        message = self.cleaned_data['message']
        wc = len(message.split())
        if wc < 4:
            raise forms.ValidationError(
                "Please muster four or more words of wisdom or woe!"
            )
        return message

support/views.py

from django.core.mail import send_mail

from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.template import RequestContext

from .forms import SupportForm

import logging
logger = logging.getLogger(__name__)

def support(request):
    """Provide a support/contact email form"""

    logger.info('Support view')
    if request.method=="POST":
        form = SupportForm(request.POST)
        if form.is_valid():
            cdata = form.cleaned_data
            send_mail(cdata['subject'],
                      cdata['message'],
                      cdata.get('email', 'example@example.com'),
                        ['example@example.com'],
            )
            return HttpResponseRedirect('/support/thanks/')
    else:
        form = SupportForm()

    return render(
        request, 
        'support/support.html',
        {'support_form': form}, 
    )
Chris McGinlay
  • 285
  • 2
  • 10
  • http://stackoverflow.com/questions/1596552/django-urls-without-a-trailing-slash-do-not-redirect – Shang Wang Jan 19 '16 at 22:39
  • 1
    What is your Apache config like? I think the static config is different for SSL than for plain (port 80). – polarise Jan 19 '16 at 22:42
  • Thanks @polarise, I hadn't thought of the webserver itself. I'm not running Apache, but I am currently reviewing my nginx config. This could well be it. – Chris McGinlay Jan 19 '16 at 22:57
  • Yes, your web server doesn't have to be Apache! – polarise Jan 20 '16 at 02:29
  • So in the end, yes it was my nginx config. I had an old sites-enabled/default config file, which I deleted. This made some progress as could be seen in the nginx log files. The final alteration was - listen [::]:80 default_server; + listen 80 default_server; (which was in my server {} block) – Chris McGinlay Jan 24 '16 at 13:04
  • Have to admit, although I've read over the nginx docs several times, and I know that [::]:80 syntax is something to do with ipv6 compatibility, I'm not exactly sure why replacing it with just port 80 did the trick. – Chris McGinlay Jan 24 '16 at 13:09

1 Answers1

0

So in the end, yes it was my nginx config. I had an old sites-enabled/default config file, which I deleted. This made some progress, but I also had to edit the config file for my production site. The diff for the final (working) server block looks like this:

server {
    - listen [::]:80 default_server; 
    + listen 80 default_server;
    server_name www.example.com;
    return 301 https://$host$request_uri
}

As I mentioned in my earlier comment, despite reading the docs, I still don't exactly know what is wrong with [::]:80 which I thought was for IPv6 compatibility.

Chris McGinlay
  • 285
  • 2
  • 10