1

These are my fully working tornado and flask files:

Tornado:

from flaskk import app
from tornado.wsgi import WSGIContainer
from tornado.ioloop import IOLoop
from tornado.web import FallbackHandler, RequestHandler, Application

class MainHandler(RequestHandler):
  def get(self):
    self.write("This message comes from Tornado ^_^")

tr = WSGIContainer(app)

application = Application([
    (r"/tornado", MainHandler),
    (r".*", FallbackHandler, dict(fallback=tr)),
])

if __name__ == '__main__':
    application.listen(5052)
    IOLoop.instance().start()

Flask:

from flask import Flask, jsonify
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

class Report(Resource):
    def get(self):
        return 'hello from flask'

api.add_resource(Report, '/report')

Now I'm trying to setup nginx in front of tornado.
My nginx config file is:

worker_processes 3;

error_log  logs/error.;

events {
    worker_connections 1024;
}

http {
    # Enumerate all the Tornado servers here
    upstream frontends {
        server 127.0.0.1:5052;
    }

    include mime.types;
    default_type application/octet-stream;

    keepalive_timeout 65;

    sendfile on;


    server {
        listen 5050;
        server_name  localhost;

        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_pass http://localhost:5050;
        }
    }
}

When I do a

localhost:5050/

then I get the nginx welcome page. But when I do

localhost:5050/report

then I get a 404. Tornado is running on port 5052.
Why is nginx not calling tornado which thereby should get the result from flask?

Am I missing something here?

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
90abyss
  • 7,037
  • 19
  • 63
  • 94
  • This seems like a bad design. Flask and Tornado serve the exact same purpose. – OneCricketeer Mar 11 '17 at 20:53
  • You don't need Tornado as a WSGI container. https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-uwsgi-and-nginx-on-ubuntu-14-04 – OneCricketeer Mar 11 '17 at 20:58
  • @cricket_007 because of this: https://stackoverflow.com/questions/23394080/why-use-nginx-to-deploy-tornado-instead-of-its-built-in-server – 90abyss Mar 11 '17 at 21:24
  • Okay, that said nothing about Flask. – OneCricketeer Mar 11 '17 at 21:29
  • https://stackoverflow.com/questions/13163990/why-use-tornado-and-flask-together – 90abyss Mar 11 '17 at 21:30
  • also I have been reading many examples online which use flask for api endpoints served behind tornado servers which is behind an nginx load balancer – 90abyss Mar 11 '17 at 21:31
  • I understand that one is blocking and another one, but your routes are not complex enough to warrant using Flask in addition to Tornado. Anyways, does `/tornado` work? – OneCricketeer Mar 11 '17 at 21:33
  • @cricket_007 the one I posted is merely an example. i havent written all the complex routing I will need to do on my flask endpoints. i am just trying to test the waters of nginx at the moment and will work on the routing later. yes localhost:5052/tornado does work. – 90abyss Mar 11 '17 at 21:38
  • No, don't hit Tornado directly. Use nginx at `localhost:5050/tornado`. – OneCricketeer Mar 11 '17 at 21:43
  • ^ That doesn't work. Gives me a 404 :( – 90abyss Mar 11 '17 at 21:46

1 Answers1

2

Firstly, you don't want to proxy to localhost:5050 because that is Nginx itself

You want to proxy to upstream frontends.

proxy_pass http://frontends;

Regarding your Flask issues, I've gotten this to work fine.

@app.route('/report')
def report():
    return 'hello from flask'

$ curl localhost:5052/report
hello from flask

When I added in Flask Restful, that still worked.


You said you see the index page of nginx, so it is running, you just need to correctly hook the other ports together.

The proxy_pass fix seemed to work for me.

$ curl localhost:5050/report
"hello from flask"
$ curl localhost:5050/tornado
This message comes from Tornado ^_^
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • I updated it to "proxy_pass http://frontends;" but that didn't help. flask and tornado are working individually. the problem is that nginx is not connecting to tornado. i am trying to search online reading many examples but nothing seems to work :( – 90abyss Mar 11 '17 at 22:05
  • I have a full working nginx + tornado app myself. https://github.com/cricket007/docker-tornado-site/blob/master/nginx/config/tornado.conf#L44 – OneCricketeer Mar 11 '17 at 22:07
  • I just ran nginx and `proxy_pass http://frontends;` works fine. `localhost:5050/tornado` and `localhost:5050/report` come back correctly. – OneCricketeer Mar 11 '17 at 22:11
  • woah! could you please show me your nginx config file? did you make any changes in the config file posted above? – 90abyss Mar 11 '17 at 22:14
  • It is the exact same file as yours but with the `proxy_pass` pointing to `http://frontends;` like I said already – OneCricketeer Mar 11 '17 at 22:15
  • PHEW! after rebooting my system, its now working for me too! i would always use "nginx -s reload" to restart the nginx. is that not the correct way? – 90abyss Mar 11 '17 at 22:27
  • Thank you so much for sticking with me man! You're totally awesome! :) – 90abyss Mar 11 '17 at 22:28
  • 1
    I would put nginx on a `systemctl` service in linux and restart that way, but I guess `-s reload` should work – OneCricketeer Mar 11 '17 at 22:29
  • And personally, I might use Hug or Falcon if all you want is a separate RESTful API behind Tornado. – OneCricketeer Mar 11 '17 at 22:32
  • Will definitely check em out. Thanks! – 90abyss Mar 11 '17 at 23:12