Reputation: 1741
I 've read answer [https://stackoverflow.com/a/20895594/305883] but did not help for me.
I have a flask app that can serve a template in localhost or debug at endpoint /path/<int:id>/
, but in production with nginx it will fail with error 404.
Flask project has default structure:
app.py
index.html
/templates/mytemplate.html
/static/..
mytemplate.html
will load resources from /static/
folder, with jinja syntax.
EDITED
Goal: I want the application to serve:
root /
will serve index.html
/path/
will open 'myTemplate.html' and populate it with variables
(jinja); if possible I want static assets included in template (e.g
js, css, images) to be served by nginx;
/api/
will serve api rest.
In my local environment I am using flask server, not ningx, and three end-points are working as expected.
In production, I use flask and ningx. Root and /api/ edges work; /path/ , used for templating in flask, does not and return error 404.
For setting up nginx I followed the steps in this tutorial: [https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-uwsgi-and-nginx-on-ubuntu-14-04]
The template in flask is served by:
@application.route('/path/<int:id>/')
def graph_template(id):
meta = {'og:image':'/url/image.jpg'}
try:
key = decode(id)[0]
except:
# todo replace with error 400
return jsonify({'error':'Something got wrong. ID not found'})
return render_template('mytemplate.html', meta=meta, id = id)
I am having difficulties in debugging and find the problem, making /path/
display the template.
nginx configuration
server {
listen 80;
# is this block to serve index on root only ?
# or will search for index files also in routes /path/ in ningx and/or flask?
root /var/www/mySite;
index index.html index.htm;
location /api {
# try_files $uri $uri/ /index.html;
include uwsgi_params;
uwsgi_pass unix:/var/www/mySite/myApp.sock;
# auth_basic "API Login";
# auth_basic_user_file /etc/nginx/pw_file;
# allow 127.0.0.1;
# allow XX.XX.XXX.XXX;
# deny all;
}
location /static {
alias /var/www/mySite/static;
}
}
I tried the following:
Included a proxy_pass:
location / {
proxy_pass http://127.0.0.1:8080;
}
result: cause error 502
Tried by changing port to :80
location / {
proxy_pass http://127.0.0.1:80;
}
result: error 404
Tried with uwsgi_pass socket at /path/ endpoint
location /path/ {
include uwsgi_params;
uwsgi_pass unix:/var/www/mySite/myApp.sock;
}
Result: This route does not exist http://example.com/path/ Which I don't understand because flask should serve the template here - at least not a misconfiguration error 502.
Answer at: [Python Flask server crashing on GET request to specific endpoint: shown two sockets for each endpoint - do I need to use such setup? I m trying to document myself on what a socket is and using nginx documentation but sorry I m not that competent in it and I m moving a bit in darkness.
Could you help in debugging the problem?
Upvotes: 1
Views: 2555
Reputation: 1741
YAII! I was able to find the answer myself:
adding this block in nginx worked out for serving templates from flask with nginx:
location /path/ {
include uwsgi_params;
uwsgi_pass unix:/var/www/mySite/myApp.sock;
}
where /path/
is the endpoint of the template.
I was receiving the message above because flask was actually handling the 404 error, due to I wrote my decorator to hit /path/<int:id>
and handling 404 requests with:
@application.errorhandler(404)
def page_not_found(error):
return 'This route does not exist {}'.format(request.url), 404
However, I will be very grateful if someone could add some comments explaining how the routing between flask and nginx actually works, and a distinction between using a uwsgi_pass
and proxy_pass
(which I found in different tutorials), and the use of sockets (tutorial I followed).
As example, in this question [Python Flask server crashing on GET request to specific endpoint: the user use two sockets for each endpoint, and for me as beginner I thought it may have been the issue and it is not.
With this configuration, I understood flask will handle the .html template: does it handle also the resource in the template (js, css) or are they served by nginx (please see configuration above, all assets are in /static/ folder)
Would there be a better configuration to exploit ningx capabilities in serving flask templates ?
Comments most appreciated!
Upvotes: 1
Reputation: 230
I assume your local env works without nginx
, right? So, lets have a look:
In local environment, hitting
/path/
(with no id) will return an error ofurl not found
, which is ok. Instead in prod environment, nginx will search for/path/index.html
- although I have not mentioned in flask decorator.
Have a look at line three of your nginx
config. In there, you specified that nginx
should look for index.html
.
In local env, if I hit
/path/id/
it works ok. In production env, it returns error 404,no such file or directory
.
I assume, this is because you don't pass any traffic to your flask app
. You need something along the lines of:
location / {
proxy_pass http://127.0.0.1:8080; #Change to match your environment
}
You're missing these (if not, please show your whole nginx
config), so nginx
will search for static files on your storage. However, these requests can't be served by static files, but instead your backend
(aka your flask app
) has to render and create these dynamically. For this to work, you have to send the traffic there.
I have not found an error due to failing with resources from
/static/
folder (e.g. in permission); it looks like flask cannot load or be allowed to serve the templates.Template file can be loaded by the browser at
/mysite/templates/mytemplate.html
Static folder permission is set on 403, but/static/js/file.js
will be read.
Sorry, I don't get this. Could you elaborate?
Upvotes: 0