PavelDuk
@PavelDuk
Python Dev

Nginx + https + django = 404?

Парни, помогите)

Есть URL:
# стриминг mp3
    path('stream_mp3/<path:song>', views.stream_mp3, name='stream_mp3'),


Есть view:
# внимание! django dev сервер не поддерживает частичный ответ 206 поэтому работает только в nginx
def stream_mp3(request, song):
    song_name = song
    mp3_path = os.getcwd() + '/media/charge/music/' + song_name
    response = HttpResponse('', content_type="audio/mpeg", status=206)
    response['X-Accel-Redirect'] = '/media/charge/music/' + song_name
    response['X-Accel-Buffering'] = 'no'
    response['Content-Length'] = os.path.getsize(mp3_path)
    response['Content-Dispostion'] = "attachment; filename=" + mp3_path
    response['Accept-Ranges'] = 'bytes'
    return response


Есть код в шаблоне:
<audio controls onended="startNextTrack()">
    <source id="audio_sourse" src="{% url 'stream_mp3' song.name %}">
</audio>


Все это дело прекрасно работает у меня на компутере: NGINX+DJANGO. Стримит как надо. Плеер работает

Пришло время деплоя, загрузил, настроил сервер, ПОДКЛЮЧИЛ HTTPS и все:

Failed to https://batareika.app/listen/stream_mp3/bi2mojjroknrollmegapesnime.mp3 load resource: the server responded with a status of 404 (Not Found)


Если кликнуть на ссылку: , получим ответ джанги 404, где примечательно есть такая строчка:
Request URL:	http://batareika.app/media/charge/music/bi2mojjroknrollmegapesnime.mp3


Я не очень понимаю устройство общения джанги и NGINX, но думаю что дело в том что response во вьюхе отдает http ответ в шаблон, а браузер ждет https.

Пробовал перенаправлять траффик в settings.py:
SECURE_SSL_REDIRECT = True

В результате браузер выдает окошко:
Страница недоступна
Сайт выполнил переадресацию слишком много раз.
Возможно, страница откроется, если удалить файлы cookie, установленные этим сайтом.

(куки удалять пробовал)

Меня это совсем сбило с толку. Каким то образом ссылка при перенаправление задвоилась на себя...

И все это при том что без использования HTTPS все работает в штатном режиме.

Прошу заметить, что из всех url адрессов в приложении перестали работать только те, которые отвечают за стриминг. Остальные url прекрасно переварили переход на https ибо нигде на сайте кроме подключаемых шрифтов у меня нет абсолютных url'ов типа http://.......big-bad.js. Только относительные через {% url %} и {% static %}.

Тут настройки NGINX:
gunicorn.socket
[Unit]
  Description=gunicorn socket

  [Socket]
  ListenStream=/run/gunicorn.sock

  [Install]
  WantedBy=sockets.target

gunicorn.service
[Unit]
  Description=gunicorn daemon
  Requires=gunicorn.socket
  After=network.target

  [Service]
  User=root
  Group=www-data
  WorkingDirectory=/root/Batareika
  ExecStart=/root/Batareika/venv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          Batareika.wsgi:application

  [Install]
  WantedBy=multi-user.target

sites-available/Batareika
server {
      listen 80;
      server_name batareika.app;

      location = /favicon.ico { access_log off; log_not_found off; }
      location /static/ {
          root /root/Batareika;
          }

          location / {
          include proxy_params;
          proxy_pass http://unix:/run/gunicorn.sock;
          }
        }

nginx.conf
user root;
worker_processes auto;
pid /run/nginx.pid;

events {
        worker_connections 1000;
        multi_accept on;
        use epoll;

}

http {

        ##
        # Basic Settings
        ##

         # Caches information about open FDs, freqently accessed files.
        open_file_cache max=200000 inactive=20s;
        open_file_cache_valid 30s;
        open_file_cache_min_uses 2;
        open_file_cache_errors on;

        # file upload timeout
        proxy_read_timeout 1200;

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 30;
        client_max_body_size 20M;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##
        # Compression.
        gzip on;
        gzip_min_length 10240;
        gzip_proxied expired no-cache no-store private auth;
        gzip_types text/plain text/css text/xml text/javascript application/x-javasc$
        gzip_disable "msie6";
        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;

Прошу помочь советом. Пока идеи на уровне каких-то диких костылей.
  • Вопрос задан
  • 1283 просмотра
Пригласить эксперта
Ответы на вопрос 4
ky0
@ky0 Куратор тега Nginx
Миллиардер, филантроп, патологический лгун
У вас триста тыщ путей в разных местах, зачем столько? Все простыни я не осилил, но вангую, что в конфиге нгинкса неправильно составлен локейшен или не настроен путь в proxy_pass, который судя по всему нужен.

Попробуйте для начала отдавать файлы просто из корня.
Ответ написан
Комментировать
1) У меня вообще приложение не знает о https, кроме файла конфига NGINX и настройке доступных хостов в settings.py

2) У меня конфиг филейной части выглядит примерно так (опять же связка nginx/gunicorn/django/виртуальное окружение):

server {
        listen 443 ssl;
		ssl_certificate /etc/ssl/your_domain.crt;      
        ssl_certificate_key /etc/ssl/your_domain.key;  
        server_name site.ru www.site.ru;
				
		gzip on;
		gzip_min_length 50;				
		gzip_comp_level 3;					
		gzip_types text/plain text/css text/javascript application/json application/x-javascript text/xml application/xml application/xml+rss;
		
		gzip_disable "msie6";

        location = /favicon.ico { access_log off; log_not_found off; }
        location /static/ {
            root /home/user/site;
			access_log off;
			expires 15d; 
        }

        location  /media/ {
            root /home/user/site/;
			access_log off;
			expires 15d;
        }
        
        location  /robots.txt {
            root /home/user/site/faceset/static;
        }

        location / {
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_pass http://unix:/home/user/site/site.sock;
        }
		
		error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

    server {        
		listen 80;
		server_name site.ru;
		return 301 https://$host$request_uri;        
    }


т.е. главная входная точка идет 443 с https, если идет на 80 порт по http, то я перенаправляю запрос по https.
Ответ написан
Комментировать
@damprog
server {
listen 443;
server_name batareika.app;

ssl_certificate ....
ssl_certificate_key .....

location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /root/Batareika;
}

location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

server {
listen 80;
server_name batareika.app;
return 301 https://$host$request_uri;
}

ИМХО примерно так
найди 5 отличий ))
Ответ написан
Комментировать
@latush
> proxy_pass http://unix:/run/gunicorn.sock;
вот здесь и появляется проблема. https -> http
Для того чтобы ее избежать, используйте uWSGI вместо Gunicorn и wsgi_pass вместо http_pass
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы