Flask Nginx url_for _external - python

How does one make the server name replace the localhost when using url_for with _external = True (so: url_for('foobar', _external=True)) under Nginx?
I'm running a flask application.
nginx setting
server {
listen 80;
server_name _;
access_log /var/log/nginx/simplemadetutor.access.log;
error_log /var/log/nginx/simplemadetutor.error.log;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
alias /home/implemad/www/simplemadetutor/app/static;
}
location /favicon.ico {
alias /home/implemad/www/simplemadetutor/app/static/img/favicon.ico;
}
}
the problem is if i type url_for('main.index', _external=True) instead of seeing something like http://simplemadetutor.com I see http://127.0.0.1:8000/
I have tried setting SERVER_NAME = 'simplemadetutor.com'; however, this seem to put the simplemadetutor.com in front of every url generated by url_for extead of just the ones with external=True.

Related

How to setup Nginx to display a website served by an internal Python server

I'm using Nginx as a reverse proxy for several web services and it works well, however, now I need to redirect the input to this server to display a website.
This web runs on an internal server, localhost:51000, and its main page is localhost:51000/login. The server runs under Python.
I would like to use an arbitrary URI to access this website from any computer but I'm not able to configure Nginx for this purpose. Needless to say, I have followed various examples and instructions found on the web and in the nginx documentation.
For example, using the following configuration:
server {
listen 443 ssl;
server_name myweb.com;
server_tokens off;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_certificate ...;
ssl_certificate_key ...;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ...
location / {
root html;
index index.html index.php;
}
location /vis2 {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
rewrite ^/vis2(.*) /$1 break;
proxy_pass http://localhost:51000/login;
}
writing myweb.com/vis2 on a web browser the server redirects to https://myweb.com/login, and the result is a 404 code because it expects to find the login file in the root of myweb.com
Instead, if I use this other configuration:
location /vis1 {
rewrite ^/vis1(.*) /$1 break;
proxy_pass http://localhost:51000/login;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-Proto $scheme;
}
writing myweb.com/vis1 on a web browser the server redirects to https://localhost:51000/login, and this is not accessible from outside the server.
I wonder what am I doing wrong or maybe it is not possible. Any advice?
Thanks in advance

Flask deployment server redirects add server name to address

I configured Nginx as a reverse proxy to a Gunicorn server running on 127.0.0.1:8000.
Nginx configuration is like this:
server {
server_name www.programlama.tk;
rewrite ^ http://programlama.tk/ permanent;
}
server {
listen 80; # listen onport 80
server_name programlama.tk localhost; #requests to this domain or ip
location / {
include proxy_params;
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
So far so good. In my flask application when the user authenticates there is a simple method that redirects to the user's home page which is 'ev'. 'Ev' means home.
#app.route('/ev')
def ev():
return render_template('ev.html')
But instead of http://programlama.tk/ev this, it redirects to
http://programlama.tk%2Cprogramlama.tk/ev
this address, which doesn't exist. Also, it adds the server name to the redirect address.
I changed the nginx configuration a bit as described in the documentation.
Now it works as expected.
location / {
proxy_pass http://127.0.0.1:8000/;
proxy_redirect off;
proxy_set_header Host $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;
}

How to perform url rewrites for different flask apps on different locations on same nginx server with uwsgi?

I am facing the following probelm:
I have set up nginx to listen to two different upstream app servers running with uwsgi on different ports. The two applications use the same static files but depending on the nginx location the firstapplication or the secondapplication gets loaded:
server {
listen 80;
server_name localhost;
charset utf-8;
client_max_body_size 75M;
# Proxy connections to the application servers
# app_servers
location /firstapplication {
include /etc/nginx/mime.types;
proxy_pass http://app_servers_firstapplication/;
proxy_redirect off;
proxy_set_header Host $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-Host $server_name;
rewrite /?(?!/firstapplication)/(.+) /firstapplication/$1 last;
}
location /secondapplication {
include /etc/nginx/mime.types;
proxy_pass http://secondapplication/;
proxy_redirect off;
proxy_set_header Host $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-Host $server_name;
rewrite /?(?!/secondapplication)/(.+) /secondapplication/$1 last;
}
location ^~ /scripts/ {
alias /webapps/scripts/;
}
location ^~ /css/ {
alias /webapps/html/css/;
}
location ^~ /graphics/ {
alias /webapps/html/graphics/;
}
location ^~ /fonts/ {
alias /webapps/html/fonts/;
}
}
When I call mydomain/firstapplication or mydomain/secondapplication the initial page of the corresponding app gets loaded right.
But when the initial page of the app gets loaded and I click on a link in the app it is using the app's urls like /contact instead of /firstapplication/contact and therefore I geht a 404 error for every url I call in the application.
I wanted to solve this problem with location specific rewrites in nginx like this:
rewrite /?(?!/firstapplication)/(.+) /firstapplication/$1 last;
and
rewrite /?(?!/secondapplication)/(.+) /secondapplication/$1 last;
I used a negative lookbehind assertion to avoid a circular redirect when I load the page /fistapplication.
This rewrite regex should work I tested it in this online editor: http://regex101.com/r/yH7sP0/1
Unfortunately nginx does not redirect the application urls and they still lead to 404 errors.
Can I use nginx rewrite module to achieve my goal? Or what other approaches could I use to run two diffrent apps on the same nginx server?

Redirect http to https with nginx instead of using django-sslify?

I tried to use django-sslify and django-secure to redirect all http requests to https, but i just can't get it to work. Is it a valid solution to redirect them with nginx instead, like it is shown here: link
Or, maybe someone could explain, what is wrong with my config right now:
Before i added "proxy_set_header Host $host;" to the second server block it redirected nicely, but forms wouldn't work, because the csrf protection threw referrer errors.
server {
listen 80;
server_name domain.com;
location /static {
alias /home/adrian/sites/www.domain.com/static;
}
location / {
proxy_set_header Host $host;
proxy_pass http://unix:/tmp/www.domain.com.socket;
}
}
server {
listen 200.200.200.200:443;
server_name domain.com;
location /static {
alias /home/adrian/sites/www.domain.com/static;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://unix:/tmp/www.domain.com.de.socket;
}
ssl on;
ssl_certificate /etc/nginx/ssl/ssl.crt;
ssl_certificate_key /etc/nginx/ssl/domain.com.de.key;
ssl_prefer_server_ciphers on;
}
Okay, never mind. Django-sslify just didn't work for some reason and so i retried django-secure with
proxy_set_header Host $host;
set and it did work like a charm. But i would really like to hear, if it would be better or more efficient to redirect with nginx and i will accept that answer. Thanks.

Django SSL Redirect snippet modification, not working as expected

I'm using Nginx as webserver, with a reverse proxy to a gunicorn django server.
I tried using the SSLRedirect snippet from here:
http://djangosnippets.org/snippets/85/
Because this snippet would always return false from is_secure() with my setup, resulting in a redirect loop, I had to make some changes.
SSL works, but when I access http://domain.net/main it doesn't redirect to https://domain.net/main. Isn't it supposed to do that?
Below outlines the modification I made:
if 'HTTP_X_FORWARDED_PROTOCOL' in request.META:
return True
And in my nginx conf (I only need SSL, http not required):
server {
listen 8888;
server_name domain.net;
ssl on;
ssl_certificate /path/to/domain.pem;
ssl_certificate_key /path/to/domain.key;
# serve directly - analogous for static/staticfiles
location /media/ {
root /path/to/root;
}
location /static/ {
root /path/to/root;
}
location / {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 10;
proxy_read_timeout 10;
proxy_pass http://127.0.0.1:8881/;
# note this line
proxy_set_header X-Forwarded-Protocol https;
}
}
Just do it entirely with nginx. No need to involve Django at all:
server {
listen 80;
rewrite ^(.*) https://$host$1 permanent;
}
server {
listen 443;
# The rest of your original server config here
}

Categories

Resources