Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on request.get_body() #14

Closed
yalosev opened this issue Sep 23, 2016 · 4 comments
Closed

Crash on request.get_body() #14

yalosev opened this issue Sep 23, 2016 · 4 comments

Comments

@yalosev
Copy link

yalosev commented Sep 23, 2016

Greetings.
I`m trying to use some code from your examples:

import asyncio

from growler import App
from growler.middleware import (Logger, Static, StringRenderer)

loop = asyncio.get_event_loop()

app = App('GrowlerServer', loop=loop)
app.use(Logger())

@app.post('/data')
def post_test(req, res):
    print(req.get_body())

Server = app.create_server(host='127.0.0.1', port=4000)

loop.run_forever()

but when I call this handler:
curl -H "Content-Type: application/json" -X POST -d '{"somekey": "somevalue"}' http://127.0.0.1:4000/data
I`m getting this errors in console:

ERROR:growler.router:140393215106800:Event loop is running.
ERROR:growler.middleware_chain:140393229054640:Event loop is running.
And then app exits with code 0.

Python - 3.5.2
asyncio (3.4.3)
growler (0.7.5)

Do you have some advice, to aboid this problem. Cause it seems, like your framework is very interesting and perfect for my purposes. But this problem ruins all idea ;)

Thank you.

@akubera
Copy link
Member

akubera commented Sep 25, 2016

Ohh, yeah looks like get_body() was a failed experiment - bridging a non-coroutine to a coroutine.

The Problem:

In short, to speed up processing the request, the HTTP headers are read and then the middleware is processed immediately. The res.body attribute is a Future, allowing the backend to cache the (potentially large) file while the webapp is running, until the body is requested. This was the purpose of get_body(), to get the value of the future without having your function be a coroutine.
The problem is, there is no way to do that. I was trying to start a new loop, obviously it didn't like that.

The Solution:

Coroutines are supported as Growler middleware, and you're using python3.5 so it's super easy!

Make post_test asynchronous by doing something like:

@app.post('/data')
async def post_test(req, res):
    print(await req.body)
    res.send_text("OK!\n")

That should work for you (also add the res.send_text so the curl command doesn't print the 404 error).

@akubera
Copy link
Member

akubera commented Sep 25, 2016

For python 3.4 compatibility, this works:

@app.post('/data')
@asyncio.coroutine
def post_test(req, res):
    data = yield from req.body
    print(data)
    res.send_text("OK")

I'm thrilled you think Growler can help you with your project, but please note that it is still a baby project and is missing a lot of functionality. I'd really appreciate any other questions or bugs you find.

@yalosev
Copy link
Author

yalosev commented Sep 27, 2016

Thank you for the answer. I see that it`s baby project. I need just a few things, but with a lot of middlewares. Tbh flask middlewares are awful, while yours are look like node or golang one. Thank you one more time.

@yalosev yalosev closed this as completed Sep 27, 2016
@whodes
Copy link

whodes commented Nov 15, 2017

I'm running into a similar problem, but instead of crashing I'm just waiting forever for the body to load. This happens when I post all different types of files to my POST endpoint and of various of sizes. It works quickly for smaller files but when I send pdfs and pngs that are only 320K it hangs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants