Search code examples
pythongunicornfalconframework

Falcon closing the connection too early


Falcon framework never returns the entire response. All I get from curl (or any other HTTP tool) is this:

$ curl -q -D - -o - "localhost:8000/post_account?email=someone@example.com

HTTP/1.1 200 OK
Server: gunicorn/19.4.5
Date: Thu, 31 Mar 2016 11:36:49 GMT
Connection: close
content-length: 3
content-type: application/json; charset=utf-8

curl: (18) transfer closed with 3 bytes remaining to read

index.py

This is the bootstrapping script that defines the routes.

import falcon
from routes import route_account


app = falcon.API()
post_account = route_account.RoutePostAccount()

# Routes
app.add_route('/post_account', post_account)

route_account.py

This is the route handler class. I checked and the result received from _result = account.create_account(**_payload) is good.

from falcon.util import uri
from objects.account_base import AccountBase

account = AccountBase()


class RoutePostAccount(object):

    @staticmethod
    def on_get(req, resp):

        # Convert query parameters string to dict
        _payload = uri.parse_query_string(req.query_string)
        # Create account
        _result = account.create_account(**_payload)
        # Send response
        resp.status = _result.get('status', {}).get('code')
        resp.body = _result

Webserver

$ gunicorn index:app

Does someone see what I don't see? Thanks for any help.


Solution

  • Use gunicorn index:app --log-level DEBUG to start your gunicorn workers. Then, try your curl command again and look at the gunicorn console: there must be an error. I think account.create_account(**_payload) is returning something invalid. Example: if you're running it on python 3 then it must be returning a dictionary but falcon expects a byte string so it fails and closes the connection. You must serialize (to json, xml, whatever you like) the output of account.create_account(**_payload). This way:

    route_account.py:

    import json
    
    from falcon.util import uri
    from objects.account_base import AccountBase
    
    account = AccountBase()
    
    
    class RoutePostAccount(object):
    
        @staticmethod
        def on_get(req, resp):
    
            # Convert query parameters string to dict
            _payload = uri.parse_query_string(req.query_string)
            # Create account
            _result = account.create_account(**_payload)
            # Send response
            resp.status = _result.get('status', {}).get('code')
            resp.body = json.dumps(_result)