I have a Flask application that is running behind an NGINX reverse proxy. In one of my functions I need to construct a URL to a different service and I wish to match the HTTP scheme to whatever the NGINX entry scheme is. So if NGINX is reverse proxying an https request, I'd like to generate a url like https://my_other_service. But if NGINX reverse proxies an http I'd like it to be http://my_other_service.
The flask.url_for function is able to automatically determine the proxy scheme when I use it for endpoints in the same app so I figure this must be possible, but in my case the url I'm generating is not an endpoint in the current Flask app.
How can I determine the proxy scheme inside a flask app?
As described on this question, you can directly tell url_for to use a specific scheme when generating a URL:
url_for('secure_thingy',
_external=True,
_scheme='https',
viewarg1=1, ...)
The problem, of course, is that you don't necessarily know whether the URL should be https or not. If it's running behind Nginx in production, it must be https. If it's running on localhost for local development, perhaps https wouldn't work.
One solution would be to just have a configuration setting for your app on what scheme to use. In your development environment, it would be set to http. In your production environment, you'd use https. That's what I would do.
An alternative is to tell Nginx to pass along a special header which you could then use to alter the scheme.
There are instructions on adding headers on the Nginx site, so here's an example:
location /some/path/ {
proxy_set_header X-Force-Https "yes";
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:8000;
}
Then in your Flask code, only pass _scheme='https' to url_for if request.headers.get('X-Force-Https', None) == 'yes'.
That's a more automatic solution, but will require you to modify your production web server environment.
Related
Using this
request.url_root+ attributes["footer"]["district_link"]
in jinja on a page that is https:// gives me a url that has http:// which is causing problems. Is there a way to use this request that preserves this so it will be http:// on a page that uses http and https on a page that uses https?
The backend is using flask if that is relevant here
Is your app proxied behind something like nginx?
If so you will need to use something like ProxyFix to add headers that include this information.
You can read more about proxy configuration in the flask docs on proxy setups.
Once you have ProxyFix working you can make use of the X-Forwarded-Proto header (for example). There's some more helpful info in this answer.
I have a web app created in django, running in gunicorn app server behind nginx webserver/reverse-proxy. I need to have external application to access some processed data (csv/json), for which I need some sort of authentication. The basic django auth/login is not optimal as a simple script needs to pull the data with a simple request, no cookies etc (not created by me).
For now, I have
set up the service being available with https/tls only
created an IP-filter in django to reduce the "attack surface" with:
request.META['HTTP_X_REAL_IP']
and using nginx to forward the ip with:
proxy_set_header X-Real-IP $remote_addr;
Next I was thinking to include and application key (hash of a pw or something) which needs to be included in the request, and is checked against db for a list of valid keys.
Is this a suitable api authentication or is there something else which can be used/recomennded? some sort of application key framework?
There are many authentication methods beside of session/cookie based ones. For your case I will suggest simple token authentication. Just save same token in your django app and external app and on each request from external app to django, send additional header:
Authentication: Token YOUR_TOKEN_KEY
Now all you need to do in django is to fetch that token and check if it matches one saved locally.
If you want more auth options for API, check Django Rest Framework documentation.
Basically when the server gets request from asdf.com it should go to the flask instance running at 5000, when server gets request from fdsa.com it should go to another flask instance (totally different app) running on 5001 and so on.
How can I achieve this, in node.js I was able to use http-proxy and route domains to node.js instances running on different ports.
What you want to do is called a reverse proxy.
You need to run the reverse proxy on port 80 and configure it to forward requests to the ports where your apps are listening on based on some criteria, like matching regular expressions on the requested hostname.
A popular reverse proxy is nginx, but if you like node-http-proxy that should work as well, and in fact they show an example of how to setup a proxy table, which is similar to your needs.
Since bottle.py does URL prefix based routing for its apps, I was wondering if bottle.py could support domain based apps.
There was an ugly hack I found on the maillist but it does not seem work with
default hostname failback
wildcard hostnames e.g. *.mysite.com
one route for multiple hostnames (this would be good for local dev work e.g. mysite.com and mysite.com.localhost will both work)
And I do not want to mess with nginx or other web server based URL rewrites
Anyone having a more elegant solution for Bottle.py apps?
Is there a way to specify a proxy server when using urlfetch on Google App Engine?
Specifically, every time I make a call using urlfetch, I want GAE to go through a proxy server. I want to do this on production, not just dev.
I want to use a proxy because there are problems with using google's outbound IP addresses (rate limiting, no static outbound IP, sometimes blacklisted, etc.). Setting a proxy is normally easy if you can edit the http message itself, but GAE's API does not appear to let you do this.
You can always roll your own:
In case of fixed destination: just setup a fixed port forwarding on a proxy server. Then send requests from GAE to proxy. If you have multiple destinations, then set forwarding on separate ports, one for each destination.
In case of dynamic destination (too much to handle via fixed port forwarding), your GAE app adds a custom http header (X-Something) containing final destination and then connects to custom proxy. Custom proxy inspects this field and forwards the request to the destination.
We ran into this issue and reached out to Google Cloud support. They suggested we use Google App Engine flexible with some app.yaml settings, custom network, and an ip-forwarding NAT gateway instance.
This didn't work for us because many core features from App Engine Standard are not implemented in App Engine Flexible. In essence we would need to rewrite our product.
So, to make applicable URL fetch requests appear to have a static IP we made a custom proxy: https://github.com/csgactuarial/app-engine-proxy
For redundancy reasons, I suggest implementing this as a multi region, multi zone, load balanced system.