resolving domain name on Django-rest-framework HyperlinkedModelSerializer - django

I would like DRF to use for serialized hyperlinks:
http://<mydomain.com>/api/v1/endpoint
rather than
http://127.0.0.1/api/v1/endpoint
Can this be configured within Django or is it related to my http server configuration (gunicorn+nginx)?

Just set host header for django.
Example for nginx:
location /api/ {
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8000;
}

if you are using https, also add :
proxy_set_header X-Forwarded-Proto https;
and everything works fine :)

Related

nginx reverse proxy to localhost

I have application running on my AWS EC2 Instance's localhost:8080.
In order to use these Web portal, I have install nginx on EC2 and reversed proxy localhost so that I can access Web UI on my browser.
Nginx.conf file
server {
listen 80;
server_name ec2-xx-xx-xxx-xxx.eu-central-1.compute.amazonaws.com;
location / {
proxy_pass http://localhost:8080;
location /$request_uri {
proxy_pass http://localhost$request_uri;
}
}
When hitting EC2 URL on my browser,I successfully seeing homepage of application.
But when I hit any url let's say /admin, Nginx redirects to my local computer's localhost:8080/admin not Server's localhost.
All i want is that when hit any url nginx should forward the request to localhost:8080{$URL} and return me the browser.
please suggest where I'm wrong.
Thanks In Advance.
You don't need to add the second location.
location / {
proxy_pass http://localhost:8080;
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;
}
this should be enough to access anything you need.

How to allow django view in nginx with PWA at /

I'm trying to setting up nginx to my PWA app with django backend.
My django backend has some views to pdf reports on /export route.
My PWA app (Vue) runs on /. I'm getting a blank page when access to /export. The blank page is trying to response from PWA, but when I reload with Shift (⇧) it loads the pdf report.
Here is my nginx server config:
server {
server_name awesome.app;
root /home/awesomeapp/pwa;
location /api/ {
include proxy_params;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://unix:/home/awesomeapp/awesome-backend/awesome.sock;
}
location /export/ {
include proxy_params;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://unix:/home/awesomeapp/awesome-backend/awesome.sock;
}
location / {
index index.html;
}
}
Any idea how to setting up nginx to allow the access to the pdf report generated by django?
Secondly, django backend also has a dashboard app (no pwa) but nginx does not allows to access it (only with shift(⇧)).
OP here.
I'm using workbox (https://developers.google.com/web/tools/workbox) to simplify service workers management.
Workbox allows exclude url paths in pwa routing (https://developers.google.com/web/tools/workbox/reference-docs/v4/workbox.routing). Black lists solve my problem.

flask redirect command goes to http rather than https

I have a flask app behind an nginx server. Nginx handles SSL termination and redirect to https. All http requests are redirected.
In flask, which I don't think should have to know about any of this, I have this bit of code:
#bp.route('/', methods=['GET', 'POST'])
def index_root():
"""Assign a session tag.
"""
return redirect(url_for('main.index', tag=make_new_tag()))
#bp.route('/D/<tag>/accueil', methods=['GET', 'POST'])
def index(tag):
return render_template('index.html', title='', tag=tag)
Now I have a problem: When someone requests http://example.com/, they are 301'd by nginx to https://www.example.com/, which is correct. Then flask 302's them to http://www.example.com/D/123/accueil, which is less good, because nginx will just 301 them to https://www.example.com/D/123/accueil (which is good, but I'd have preferred to skip that extra redirect).
Is this a configuration issue somewhere?
Note that in dev it's important that flask really not think about https. Indeed, flask shouldn't need to know anythint at all about https, and this is why I'm finding this a bit mystifying.
Thanks for any pointers.
The current way to achieve this appears to be passing x_proto=1 as an argument to Werkzeug's ProxyFix middleware:
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1 ,x_proto=1)
Be sure to set x_for correctly, as per the docs. This is set to the number of proxies, and must be correct for security reasons, otherwise Flask may trust some headers set by an internet user as if they'd come from the reverse proxy. The danger is setting this to 1 when there's no proxy.
Then in the nginx ensure you're setting the X-Forwarded-Proto header in the location block, before your proxy_pass:
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://localhost:9999/;
}
I haven't tested this with nginx but was able to test directly against the dev server and gunicorn by setting that header specifically in curl:
curl -is http://localhost:5000/ -H 'X-Forwarded-Proto: https'
This returns:
HTTP/1.0 302 FOUND
Location: https://localhost:5000/test_str/accueil`
So it appears to effect url_for which doesn't require modifying individual url_for() calls in your code, which is the case with accepted answer linked by #PGHE.
I've solved this problem on reverse proxy side (Nginx) by using X-Forwarded-HTTPS instead of X-Forwarded-Proto
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-HTTPS on;
proxy_pass http://localhost:9999/;
}

Add global prefix for Django URLs

Instead of using subdomains I would like to add subfolders like:
burger.domain.com -> domain.com/organization/burger/
is there any way to add /organization/<name:str>/ globaly?
Well, if you have a reverse proxy server like NGINX/Apache, you can update the X-Script-Name. For example in NGINX:
location /organization {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Script-Name /organization;
}
In that way, django will be served at path /organization(as per configuration of X-Script-Name). You can also checkout this blog for more information regarding deploying django with Apache.
But, if you don't have such reverse proxy server, then you can use FORCE_SCRIPT_NAME. In django settings add the following line:
FORCE_SCRIPT_NAME = '/organization'

Does Django Channels uses ws:// protocol prefix to route between Django view or Channels app?

I am running Django + Channels server using Daphne. Daphne server is behind Nginx. My Nginx config looks like as given at end.
When I try to connect to ws://example.com/ws/endpoint I am getting NOT FOUNT /ws/endpoint error.
For me, it looks like Daphne is using protocol to route to either Django views or Channels app. If it sees http it routes to Django view and when it sees ws it routes to Channels app.
With following Nginx proxy pass configuration the URL always has http protocol prefix. So I am getting 404 or NOT FOUND in logs. If I change proxy_pass prefix to ws Nginx config fails.
What is the ideal way to setup Channels in the this scenario?
server {
listen 443 ssl;
server_name example.com
location / {
# prevents 502 bad gateway error
proxy_buffers 8 32k;
proxy_buffer_size 64k;
# redirect all HTTP traffic to localhost:8088;
proxy_pass http://0.0.0.0:8000/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header X-NginX-Proxy true;
# enables WS support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 999999999;
}
}
Yes, as in the question Channels detects the route based on the protocol header ws or http/https
Using ws prefix in proxy_pass http://0.0.0.0:8000/; is not possible. To forward the protocol information following config should be included.
proxy_set_header X-Forwarded-Proto $scheme;
This will forward the schema/protocol(ws) information to Channels app. And channels routes according to this information.