26

I built a basic web app using Flask, and was able to run it from a virtual machine using its native http server. I quickly realized that with this set up, requests are blocking (I couldn't make concurrent requests for resources; any new request would wait until earlier requests had finished), and decided to try gunicorn to run the app to solve this problem. I followed the documentation, specifically running with this line:

gunicorn -w 4 -b 127.0.0.1:4000 myproject:app 

However, it failed to boot doing just this, and complained that there was no WSGI app. Poking around the internet, I found that a number of people had posted examples including the following:

from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)

I added that, and it resolved my problem. I am confused though because this is apparently meant to solve a problem serving behind an HTTP proxy, but would the addition of gunicorn impose an HTTP proxy? Or was I always behind a proxy, and it just didn't matter for Flask's built-in server?

Also, Werkzeug's documentation on Fixers warns "Do not use this middleware in non-proxy setups for security reasons." Considering the fix was clearly necessary, can I assume I'm on a proxy setup?

wsn
  • 1,097
  • 8
  • 15
Ashley Temple
  • 311
  • 1
  • 4
  • 8
  • +1 - good question. A question for you - were those two lines the *only* things you changed before you redeployed? – Sean Vieira Dec 14 '13 at 17:51
  • 1
    Yep. I tried a couple of other things first, but removed everything related to other attempts when they failed to solve the problem. – Ashley Temple Dec 14 '13 at 20:56
  • 1
    Are you getting any error messages from Gunicorn? ProxyFix just changes some environ variables so you get the correct details through a proxy. Also what version of Flask and Werkzeug are you using? – Joe Doherty Dec 16 '13 at 16:52
  • 2
    I'm surprised that gunicorn fails to boot without this. The only problems which are supposed to be solved by this fixer are related to reverse-proxying, e.g. when you get 127.0.0.1 as the client address because the request to gunicorn comes from nginx. If you are interested in what the fixer actually does, i think the source is clear enough: https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/contrib/fixers.py#L94 – Markus Unterwaditzer Dec 29 '13 at 20:40
  • 1
    You should probably inspect the gunicorn log file to see if there is a more detailed error message. Also, if you are pointing to the wsgi_app object using a module path in some kind of config file, you should ensure that there's a reference to the wsgi_app as a top-level object in the module. In your example, it looks like the wsgi_app is an attribute on some other object in the module, which might not allow it to be accessed via a module path, i.e. 'my_project.wsgi_module.app.wsgi_app' probably won't work but 'my_project.wsgi_module.app' would. Might not be the issue but worth a look. – David Sanders Feb 13 '14 at 22:41
  • Are you actually accessing your web app at http://localhost:4000? It is common to run gunicorn behind another web server, like Apache or nginx, in reverse proxy mode. I'm still not sure why you'd need `ProxyFix` to even get gunicorn to start, though. – sjy Mar 04 '14 at 09:26

2 Answers2

6

A little late to the party, but here (Flask v1) is what the documentation says about ProxyFix.

Documentation for v2

To paraphrase: Deploying your server using gunicorn behind an HTTP proxy you will need to rewrite some of the headers so that the application can work. And Werkzeug ships with a fixer that will solve some of the common setups.

Thomas Gak-Deluen
  • 2,759
  • 2
  • 28
  • 38
4

You need to show the code that defines your Flask application "app".

Where is "app" defined? Are you importing it from another file?

Here is my attempt to reproduce the issue:

$ cat myproject.py
from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "ok"

$ bin/gunicorn -w 4 -b 127.0.0.1:4000 myproject:app &
[1] 27435

2014-03-04 12:18:36 [27435] [INFO] Starting gunicorn 18.0
2014-03-04 12:18:36 [27435] [INFO] Listening at: http://127.0.0.1:4000 (27435)
2014-03-04 12:18:36 [27435] [INFO] Using worker: sync
2014-03-04 12:18:36 [27441] [INFO] Booting worker with pid: 27441
2014-03-04 12:18:36 [27442] [INFO] Booting worker with pid: 27442
2014-03-04 12:18:36 [27445] [INFO] Booting worker with pid: 27445
2014-03-04 12:18:36 [27448] [INFO] Booting worker with pid: 27448

$ curl http://127.0.0.1:4000/
ok

As you can see it works fine. You definitely don't need ProxyFix in this case.

Steven Kryskalla
  • 14,179
  • 2
  • 40
  • 42