Django Double Slash in URLS Issue (Multiple Webservers, Apache and Nginx) - django

To see an example: load up a example.com, click on a link that's linking to /test and instead of going to http:// example.com/test/ it goes to http:// www.example.net//test/
Or if you login, the login form for the auto-generated django admin section posts to //admin instead of admin.
Seems like this is a django issue, but the only thing I changed was nginx.
Couple of additional notes (added Oct 31):
This problem seems remarkably similar to https://serverfault.com/questions/134863/nginx-fastcgi-problems-with-django-double-slashes-in-url but the difference is that I'm getting slashes added before the project root "//admin/" vs. "admin//". The successful solution there hasn't helped me.
I'm using the current SVN version of Django.
Here is the nginx fastcgi_conf:
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
Django project config
server {
listen 80;
server_name www.site.net;
location / {
fastcgi_pass unix:/path/to/site/server.sock;
include fastcgi.conf;
access_log /var/log/nginx_django.log main;
}
location ^~ /admin/$ {
fastcgi_pass unix:/path/to/site/server.sock;
include fastcgi.conf;
access_log /var/log/nginx_django.log main;
}
location ~* ^.+\.(mpg|avi|mp3|swf|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|txt|tar|mid|midi|wav|rtf|mpeg))
$ {
root /path/to/site/media;
limit_rate 2000K;
access_log /var/log/nginx_django_media.log download;
access_log off;
}
location ^~ /static/ {
root /path/to/site;
access_log /var/log/nginx_django_static.log download;
expires 30d;
}
location /403.html {
root /opt/nginx;
access_log off;
}
location /401.html {
root /opt/nginx;
access_log off;
}
location /404.html {
root /opt/nginx;
access_log off;
}
location = /_.gif {
empty_gif;
access_log off;
}
}

fastcgi_param SCRIPT_NAME '';
This solve the // problem for me.

Related

Django+fastcgi+nginx logging

I was given django project from another developer. It based on windows server(Django+fastcgi+nginx).
In settings.py present option DEBUG=True but the anyone of the errorlog-files does not contain debugging information
nginx.conf
worker_processes auto;
error_log C:/PATH_TO_PROJECT/nginx/logs/error.log;
error_log C:/PATH_TO_PROJECT/nginx/logs/error.log notice;
error_log C:/PATH_TO_PROJECT/nginx/logs/error.log info;
error_log C:/PATH_TO_PROJECT/nginx/logs/error.log error;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 8080;
server_name localhost;
client_max_body_size 32m;
error_log C:/PATH_TO_PROJECT/nginx/logs/db-rlocalhost.error_log;
error_log C:/PATH_TO_PROJECT/nginx/logs/db-rlocalhost.error_log notice;
error_log C:/PATH_TO_PROJECT/nginx/logs/db-rlocalhost.error_log info;
error_log C:/PATH_TO_PROJECT/nginx/logs/db-rlocalhost.error_log error;
location / {
fastcgi_pass 127.0.0.1:8888;
fastcgi_pass_header Authorization;
fastcgi_hide_header X-Accel-Redirect;
fastcgi_hide_header X-Sendfile;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_PROTOCOL $server_protocol;
}
location /media/ {
alias H:/AUCTION/;
}
location /static/ {
alias C:/PATH_TO_PROJECT/static/;
}
location /static_ac_invoice/ {
alias C:/PATH_TO_PROJECT/tender/ac_invoice/static/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
Running server:
c:\PATH_TO_PROJECT\Scripts\python.exe c:\PATH_TO_PROJECT\tender\manage.py runfcgi method=threaded host=127.0.0.1 port=8888
C:\PATH_TO_PROJECT\nginx\nginx.exe
How can I get debug info without reconfigure project for running in non fastcgi mode?
python manage.py runfcgi method=threaded host=127.0.0.1 port=8888 daemonize=false
Now I can see debug info.
Why is key daemonize=false not present in help output manage.py?

FastCGI application behind NGINX is unable to detect that HTTPS secure connection is used

I'm running FastCGI behind Nginx, and need to detect when the url is accessed via HTTPS. However, my Django web application always reports that the connection is HTTP (request.is_secure() == False). However, SSL is setup correctly, and I've verified my https:// urls are secure with an SSL checker.
How can I get Django to correctly detect when the request is from an HTTPS url?
My Nginx settings are:
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
server {
listen 80;
listen 443 default ssl;
ssl_certificate /home/webapp/ssl.crt
ssl_certificate_key /home/webapp/ssl.key
server_name myapp.com;
access_log /home/webapp/access.log
error_log /home/webapp/error.log
root /home/mywebapp;
location / {
# host and port to fastcgi server
fastcgi_pass 127.0.0.1:8801;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
}
}
}
I start the Django FastCGI process with:
python /home/webapp/manage.py runfcgi method=threaded host=127.0.0.1 port=8801 pidfile=/home/webapp/fastcgi.pid
Thanks to Yuji for the answer. I've updated my server block to conditionally inject HTTPS on or HTTPS off, depending on $server_port:
{
server {
listen 80;
listen 443 default ssl;
if ($server_port = 443) { set $https on; }
if ($server_port = 80) { set $https off; }
ssl_certificate /home/webapp/ssl.crt
ssl_certificate_key /home/webapp/ssl.key
server_name myapp.com;
access_log /home/webapp/access.log
error_log /home/webapp/error.log
root /home/mywebapp;
location / {
# host and port to fastcgi server
fastcgi_pass 127.0.0.1:8801;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
fastcgi_param HTTPS $https;
}
}
}
Make sure nginx is sending fastcgi_param HTTPS on for connections on 443.

Django + NGINX URL Problem

I have set up Django's FastCGI + NGINX, but it's only working for root url: any request to http://example.com/anything redirects to http://example.com. Django's internal server working fine, NGINX static file serving and FastCGI processing of the root URL is fine, error log is clear. Here is my config's server section:
server {
listen 80;
server_name example.com;
location / {
fastcgi_pass localhost:8000;
include fastcgi_params;
}
location /static/ {
alias /root/web_development/src/web_development/static/;
}
}
What am I doing wrong? Thanks in advance.
Try this configs:
server {
listen 80;
server_name example.com;
location / {
root /home/example.com/foo;
fastcgi_pass 127.0.0.1:8000;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
}
}
Make sure you've already informed nginx the port which django runs.
You may need to add this line to location /:
fastcgi_split_path_info ^()(.*)$;
from djangoandnginx

Django and Nginx try_files 403 for site root page

I use such Nginx configuration for the domain:
server_name_in_redirect off;
listen 80;
server_name ~^(www\.)?(.+)$;
root /var/www/$2/htdocs;
location / {
try_files $uri $uri/ $uri/index.htm #django;
index index.html index.htm;
}
location #django {
fastcgi_pass 127.0.0.1:8801;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
fastcgi_param REMOTE_ADDR $remote_addr;
}
Django URL config:
urlpatterns = patterns('',
url(r'^$', home, name='home'),
url(r'index.htm', home, name='home'),
url(r'^(?P<name>.*).htm$', plain_page, name="plain_page"),
}
all urls like http://domain.com/somepage.htm works good, except http://domain.com/ it always shows 403 by Nginx.
if you add static index.htm file to the site root - it's opened because of try_files directive
if you have no static index.htm, but call http://domain.com/index.htm page is opened by django
buf it you have no static index.htm and open http://domain.com/ you get no page, but by idea
index.htm should be looked and passed to the django as the last in the try_files chain.
how to make http://domain.com/ work (should call django's index.htm) in this case?
Add this
location = / {
rewrite ^(.*)$ /index.htm last;
}
underneath the root line to do a rewrite of the URI before further processing.
PS. You have probably sorted this out during the year since your asked, but here it is for other to see.
A better solution is you provide a / url in your urls.py is remove the
root /var/www/$2/htdocs;
Then only include the root in location {} blocks where you serve up static assets.

how to nginx virtual servers + fcgi for django?

I would like to run several virtual hosts via nginx, each serving a different django app via fcgi. Is this possible? If so, does anyone have good resources on where/how to start? The nginx docs seem to be mostly examples, but none of the particular config I'm attempting...
There have been two pretty good blog posts lately about setting up nginx, but both are using nginx to serve static (or cached) content and apache + mod_wsgi to serve Django. I prefer this myself because mod_wsgi makes process management so much easier than fcgi (among other advantages).
Anyway, here are the posts:
The Django and Ubuntu Intrepid Almanac
django, nginx, memcached - the dynamic trio
EDIT: ok I dug out an old tar file with my nginx + django + virtual host config files from a year ago before I switched to apache + mod_wsgi. This was a development machine, so you'll want to adjust # of workers, connections, etc.
nginx.conf:
user nginx nginx;
worker_processes 2;
error_log /var/log/nginx/error_log info;
events {
worker_connections 1024;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main
'$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
connection_pool_size 256;
client_header_buffer_size 1k;
large_client_header_buffers 4 2k;
request_pool_size 4k;
gzip on;
gzip_min_length 1100;
gzip_buffers 4 32k;
gzip_types text/plain text/html application/x-javascript text/xml text/css;
output_buffers 4 32k;
postpone_output 1460;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 75 20;
ignore_invalid_headers on;
include vhosts.d/*.conf;
}
So, the main nginx.conf includes every file in the vhosts.d/ subdirectory. One of my files was for serving PHP on localhost (was probably running phpMyAdmin) like this:
vhosts.d/00_localhost:
server {
listen 127.0.0.1:80;
server_name localhost;
access_log /var/log/nginx/localhost.access_log main;
error_log /var/log/nginx/localhost.error_log info;
root /var/www/localhost/htdocs;
index index.php index.html index.htm;
location ~ .php$ {
fastcgi_pass 127.0.0.1:8888;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
}
}
And then a local Django development server like this:
50_django.local:
server {
listen 80;
server_name django.local;
access_log /var/log/nginx/django.access.log main;
error_log /var/log/nginx/django.error.log info;
root /var/www/django.local;
location ~* ^.+\.(mpg|avi|mp3|swf|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|txt|tar|mid|midi|wav|rtf|mpeg)$ {
access_log off;
break;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|bmp|js)$ {
expires 30d;
break;
}
location / {
fastcgi_pass unix:/var/www/django.local/server.sock;
include fastcgi.conf;
}
location ^~ /admin/ {
fastcgi_pass unix:/var/www/django.local/server.sock;
include fastcgi.conf;
access_log off;
auth_basic "Welcome to admin";
}
}
Finally, each of the virtual servers included a fastcgi.conf for each location.
fastcgi.conf:
fastcgi_pass_header Authorization;
fastcgi_intercept_errors off;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_SOFTWARE "nginx";
fastcgi_param GATEWAY_INTERFACE "CGI/1.1";
fastcgi_param UID_SET $uid_set;
fastcgi_param UID_GOT $uid_got;
I'm not sure all of the above were required, but that was another one of the reasons I switched to mod_wsgi... superior support and documentation :)
Since this question was asked someone created a pip installable django package that will generate an apache or nginx vhost file for you from your settings.py
pip install django-vhost
Check it out here: https://bitbucket.org/djangostars/django-vhost