Repository: benoitc/gunicorn

Issue:
Error serving aiohttp
Hi,

When trying to serve an `aiohttp==0.22.5` application with `gunicorn==19.6.0` using the `gaiohttp` worker class (as documented) I can an error:

```
Traceback (most recent call last):
  File "/<redacted>/lib/python3.5/site-packages/aiohttp/server.py", line 285, in start
    yield from self.handle_request(message, payload)
  File "/<redacted>/lib/python3.5/site-packages/aiohttp/wsgi.py", line 146, in handle_request
    riter = self.wsgi(environ, response.start_response)
TypeError: __call__() takes 1 positional argument but 3 were given
```

I noticed that `Application.__call__()` accepts no parameters, but `WSGIServerHttpProtocol.handle_request()` tries to call it as a WSGI app (with two arguments, environ and start_response). So I believe `Application.__call__()` could perhaps accept variable parameters and just ignore them, but I'm not sure this would impact anything else.

However, when following the `aiohttp` documentation on deploying with Gunicorn, that is, using `aiohttp.worker.GunicornWebWorker`, then it works fine for me.



Discussion:
If aiohttp ships with its own worker implementation perhaps we can deprecate ours. Here is the relevant part from http://aiohttp.readthedocs.io/en/stable/gunicorn.html#start-gunicorn:

> The custom worker subclass is defined in aiohttp.worker.GunicornWebWorker and should be used instead of the gaiohttp worker provided by Gunicorn, which supports only aiohttp.wsgi applications

Sounds good to me. :-)

normally people from aiohttp are supposed to update the worker there. @asvetlov has the commit bit. I am wondering now why the worker hasn't been updated there .... 

@asvetlov should we deprecate the worker here? Why things changed?

Oops. Sorry. I'll update the worker in a few days.

@asvetlov Thanks! also as of now we don't have to only support wsgi. pure HTTP is ok too :) I will provide more details in the coming month. 

@benoitc also I want to move `aiohttp.wsgi` into `gunicorn` (with keeping a copy in `aiohttp` for deprecation period).
There are no reasons to keep it in `aiohttp` itself -- `guinicorn` is the only user for the module.
Do you have an objection?

P.S.
WSGI support is limited, you know -- async reading of POST body is not allowed.

UPD.
See also KeepSafe/aiohttp#1108

But deployment aiohttp applications behind gunicorn is quite popular -- people prefer to use it for forking several aiohttp workers with well-known rules.

Sorry, it takes more than few days but I didn't give up.
The issue is still in my todo list.
But I should publish new aiohttp release first.

@asvetlov we've discussed packaging the workers separately and we have the gunicorn organization on GitHub already. Maybe aiohttp can be the first worker packaged and added to that organization.

> Maybe aiohttp can be the first worker packaged and added to that organization.

+1 from me.

still. I would appreciate to have the issue fixed. so we can next go further eventually. Any idea of the work to do for it @asvetlov ?

Resolving patch:
diff --git a/examples/frameworks/flaskapp_aiohttp_wsgi.py b/examples/frameworks/flaskapp_aiohttp_wsgi.py
new file mode 100644
--- /dev/null
+++ b/examples/frameworks/flaskapp_aiohttp_wsgi.py
@@ -0,0 +1,24 @@
+# Example command to run the example:
+#
+#   $ gunicorn flaskapp_aiohttp_wsgi:aioapp -k aiohttp.worker.GunicornWebWorker
+#
+
+from aiohttp import web
+from aiohttp_wsgi import WSGIHandler
+from flask import Flask
+
+app = Flask(__name__)
+
+
+@app.route('/')
+def hello():
+    return 'Hello, world!'
+
+
+def make_aiohttp_app(app):
+    wsgi_handler = WSGIHandler(app)
+    aioapp = web.Application()
+    aioapp.router.add_route('*', '/{path_info:.*}', wsgi_handler)
+    return aioapp
+
+aioapp = make_aiohttp_app(app)
diff --git a/gunicorn/config.py b/gunicorn/config.py
--- a/gunicorn/config.py
+++ b/gunicorn/config.py
@@ -624,12 +624,17 @@ class WorkerClass(Setting):
         * ``gevent``   - Requires gevent >= 0.13
         * ``tornado``  - Requires tornado >= 0.2
         * ``gthread``  - Python 2 requires the futures package to be installed
-        * ``gaiohttp`` - Requires Python 3.4 and aiohttp >= 0.21.5
+        * ``gaiohttp`` - Deprecated.
 
         Optionally, you can provide your own worker by giving Gunicorn a
         Python path to a subclass of ``gunicorn.workers.base.Worker``.
         This alternative syntax will load the gevent class:
         ``gunicorn.workers.ggevent.GeventWorker``.
+
+        .. deprecated:: 19.8
+           The ``gaiohttp`` worker is deprecated. Please use
+           ``aiohttp.worker.GunicornWebWorker`` instead. See
+           :ref:`asyncio-workers` for more information on how to use it.
         """
 
 class WorkerThreads(Setting):
diff --git a/gunicorn/workers/gaiohttp.py b/gunicorn/workers/gaiohttp.py
--- a/gunicorn/workers/gaiohttp.py
+++ b/gunicorn/workers/gaiohttp.py
@@ -5,13 +5,23 @@
 
 import sys
 
-if sys.version_info >= (3, 3):
+from gunicorn import util
+
+if sys.version_info >= (3, 4):
     try:
         import aiohttp  # NOQA
     except ImportError:
         raise RuntimeError("You need aiohttp installed to use this worker.")
     else:
-        from gunicorn.workers._gaiohttp import AiohttpWorker
+        try:
+            from aiohttp.worker import GunicornWebWorker as AiohttpWorker
+        except ImportError:
+            from gunicorn.workers._gaiohttp import AiohttpWorker
+
+        util.warn(
+            "The 'gaiohttp' worker is deprecated. See --worker-class "
+            "documentation for more information."
+        )
         __all__ = ['AiohttpWorker']
 else:
-    raise RuntimeError("You need Python >= 3.3 to use the asyncio worker")
+    raise RuntimeError("You need Python >= 3.4 to use the gaiohttp worker")


Test patch: