views:

309

answers:

3

Hi folks,

logging into django admin fails when 'log in' button is pressed first time, but pressing "back" and "log in' again - logs the user in successfully.

I am deploying Django app with zc.buildout here, with a setup similar to what is described here http://www.meppum.com/2009/jan/17/installing-django-ubuntu-intrepid/. Nginx (listening on 127.0.0.1:8003) is running beyond Apache(listening on 127.0.0.1:8001), configurations of both servers are provided at the end of the post. I'm accessing my django app as 127.0.0.1:8003/.

So, 127.0.0.1:8003/admin/ opens django admin login form. 1)Entering username/pass, pressing "log in" redirects to (for some unknown reason?) 127.0.0.1/ admin, therefore ends up with nothing, as there is no server listening on 80 port. HTTP trace (after clicking login in: http://127.0.0.1:8003/admin/)

POST /admin/ HTTP/1.1
Host: 127.0.0.1:8003
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.17) Gecko/2010010604 Ubuntu/9.04 (jaunty) Firefox/3.0.17
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://127.0.0.1:8003/admin/
Cookie: JSESSIONID=0D287C17FBA82223AB7D5884EA534967; sessionid=c65c7af8ebde9e6bdf9c739a731d376b
Content-Type: application/x-www-form-urlencoded
Content-Length: 55
username=to&password=password&this_is_the_login_form=1

HTTP/1.x 302 FOUND
Server: nginx/0.8.29
Date: Mon, 01 Feb 2010 10:27:44 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Expires: Mon, 01 Feb 2010 10:27:44 GMT
Vary: Cookie
Etag: "d41d8cd98f00b204e9800998ecf8427e"
Cache-Control: max-age=0
Set-Cookie: sessionid=9db437da69c359136786696f90ba89f2; expires=Mon, 15-Feb-2010 10:27:44 GMT; Max-Age=1209600; Path=/
Last-Modified: Mon, 01 Feb 2010 10:27:44 GMT
Location: http://127.0.0.1/admin/
Content-Length: 0

2)Pressing browser's back , and 'log in' button once again (or pressing browser's 'back' and 'refresh') logs in succesfully. HTTP trace:

POST /admin/ HTTP/1.1
Host: 127.0.0.1:8003
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.17) Gecko/2010010604 Ubuntu/9.04 (jaunty) Firefox/3.0.17
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://127.0.0.1:8003/admin/
Cookie: JSESSIONID=0D287C17FBA82223AB7D5884EA534967; sessionid=9db437da69c359136786696f90ba89f2
Content-Type: application/x-www-form-urlencoded
Content-Length: 55
username=to&password=password&this_is_the_login_form=1

HTTP/1.x 200 OK
Server: nginx/0.8.29
Date: Mon, 01 Feb 2010 10:52:02 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Mon, 01 Feb 2010 10:52:02 GMT
Vary: Cookie
Etag: "3355a46fb32d7cb6ab21262c359d9eec"
Cache-Control: max-age=0
Last-Modified: Mon, 01 Feb 2010 10:52:02 GMT

It looks like that's a cookie-related issue, but, i guess, the root of the problem might as well lie in the apache and/or nginx config as well.

Any ideas how to make the admin log-in form work immediately?

Cheers!

to

P.S.configs:

apache vhost configuration:

<VirtualHost *:8001>

    <Directory /home/toinbis/Desktop/programming/project/runtime/
htdocs/django_wsgi/>
        Order deny,allow
        Allow from all
    </Directory>

    WSGIDaemonProcess tsd user=www-data group=www-data threads=25
    WSGIProcessGroup tsd

    WSGIScriptAlias / /home/toinbis/Desktop/programming/project/
runtime/htdocs/django_wsgi/djproject.wsgi

    LogLevel warn
    ErrorLog  /home/toinbis/Desktop/programming/project/runtime/logs/
apache_tsd_error.log
    CustomLog /home/toinbis/Desktop/programming/project/runtime/logs/
apache_tsd_access.log combined

    ServerName localhost
</VirtualHost>

nginx configuration:

daemon off;
#user www-data;
worker_processes  2;

error_log  /home/toinbis/Desktop/programming/project/runtime/logs/
nginx_general_error.log;
pid        /home/toinbis/Desktop/programming/project/runtime/var/pids/
nginx.pid;

events {
    worker_connections  1024;
    #server_names_hash_bucket_size: 128;

}

http {
    include       /home/toinbis/Desktop/programming/project/runtime/
etc/nginx_conf/mime.types;
    default_type  application/octet-stream;

    access_log  /home/toinbis/Desktop/programming/project/runtime/logs/
nginx_access.log;
    error_log   /home/toinbis/Desktop/programming/project/runtime/logs/
nginx_error.log;

    sendfile        on;
    tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  2;
    tcp_nodelay        on;

    server_names_hash_bucket_size 128;
    #server_name_hashes 128;
    gzip  on;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)"; #iš ubuntu
    gzip_types text/plain text/css application/x-javascript text/xml
application/xml application/xml+rss text/javascript;

upstream backend {
  server 127.0.0.1:8001;

}

server {
            listen   8003;
            server_name localhost;

            error_log /home/toinbis/Desktop/programming/project/
runtime/logs/project_nginx_error.log;
            access_log /home/toinbis/Desktop/programming/project/
runtime/logs/project_nginx_access.log;

            location / {
                        proxy_pass  http://backend/;
                        include     /home/toinbis/Desktop/programming/
project/runtime/etc/nginx_conf/nginx_proxy_1.conf;
            }

            location  /media/ {
                        root /home/toinbis/Desktop/programming/project/
src/tsd/core/;
            }

}
}

cheers, to

+1  A: 

Your settings are incorrect. Django believes that it runs on port 80. Look at this line in the first HTTP response:

Location: http://127.0.0.1/admin/

Unfortunately, I can't understand right now why this happens. I prefer just to step throught the relevant Django code with a debugger in such cases.

Eugene Morozov
Eugene, thanks for help. Am trying to debug right now... development server seems to work well with the same settings...
toinbis
+1  A: 

@Eugene Morozov has pointed out the end result of the problem, but I think the solution lies deeper.

The Location header being returned is incorrect:

Location: http://127.0.0.1/admin/

This is clearly missing the port number. Unfortunately, it is hard to tell exactly where this is coming from. You may be running into either Nginx or Apache automagically altering the Location header. I'd suggest doing the following to see where the problem crops up:

  • Clear your cookies before each time you log in, or you may get a false positive.
  • Go directly to your Apache instance and see if the problem persists.
    • http://127.0.0.1:8001/admin/
    • If the location header does not have a port on it:
      • Fire up the Django development server on some random port (8005, for example) and see if the problem persists:
        • If the problem persists, it is in your code.
        • If the problem does not persist, Apache is either doing something weird or WSGI/Django isn't getting all the information it needs to determine the port number.
          • Make sure that the wsgi script and the django app can both see the port number in the environment.
    • If the location header has a port in it:
      • Nginx is stripping it off for some reason.
      • Try cutting Apache out of the loop, you probably don't need it.
        • Fire up Django as a FastCGI server and connect Nginx to that instead of Apache.
          • This will actually lower some of the overhead on your server (less request passing, extra threads, memory use, etc).
          • Fairly good setup guide over here.

Ninja Edit!
Not sure if this will help, but it seems there is an option in Nginx for ignoring the port number in redirects. The URL is dead, so I'm pasting this from over here.

http://wiki.codemongers.com/NginxHttpCoreModule#port_in_redirect

syntax: port_in_redirect [ on|off ]
default: port_in_redirect on
context: http, server, location

Directive allows or prevents port indication in redirects handled by nginx.

Jack M.
Wow, great answer! Is "Fire up Django as a FastCGI server and connect Nginx to that instead of Apache." a general offer for deployments? Are the any tests showing how much overhead can possibly by saved by using fastcgi over apache_modwsgi? will let you know how the tracing of a problem went..
toinbis
I do not know of any benchmarks, just common sense. Why run two full-fledged web servers if you don't have to? (Assuming your project isn't huge, in which case there are reasons to do so.)
Jack M.
Apache-only works well, ok, so "Nginx is stripping it off for some reason" is a lower-level reason. am diving deeper into nginx configs... Thanks once again!
toinbis
@toinbis: I updated the question with some more info from a Ruby site which seemed to have a similar problem. Take a look.
Jack M.
Ninja Edit was amazing - pointed directly where it is (as i suppose) was necessary. Am now playing with different settings in /location settings, will update my post with the results. Jack, thanks a lot!
toinbis
A: 

Euge, James,

thanks a lot for your help once again!

The solution turned out to be described here: changing proxy_set_headerHost $host; to proxy_set_headerHost $host:$server_port; did the trick!

toinbis