简体   繁体   中英

mod_wsgi: TypeError: expected byte string object for header name, value of type unicode found

I have a flask web app running in Production using Python 2.7.5 and mod_wsgi 3.4. The webapp runs fine in production and local loopback.

I recently added a Flask Restplus API (3 methods). Everything works locally: My webapp runs fine, 3 Rest Api methods respond correctly, and swagger docs are visible/working at /api/documentation.

However on the Production server using mod_wsgi, my webapp runs fine,my rest api works,but if I access the swagger docs at http://mydomain/api/documentation , I get two errors in httpd error log:

Exception occurred processing WSGI script ...
TypeError: expected byte string object for header name, value of type unicode found

EDIT* in access log all requests are 200... the only 500 error is caused by /api/swagger.json... There's even a 200 for /api/documentation which might be why the swagger title and favicon load into the browser tab, but under that is a message saying 'No API Definition Provided'

I am now trying to set the response headers like so (with charset=UTF-8):

resp = app.response_class(
    response=json.dumps(found_resource),
    status=200,
    content_type='application/json; charset=UTF-8'
)
return resp

and

response = app.response_class(
    response=json.dumps({'success': False}),
    status=400,
    content_type='application/json; charset=UTF-8'
)
return response

Am I setting the header to a byte string object correctly for the responses? Any response is either a json dictionary or json list of dictionaries.

I'm a bit confused because this bug report makes it seem that setting the charset is not necessary and possibly redundant using content_type='application/json; charset=UTF-8

The response needs to be an actual array of bytes instead of aa string. You can use

response = app.response_class(
    response=bytes(json.dumps(found_resource).encode('utf-8')),
    status=200,
    content_type='application/json; charset=UTF-8'
)
return response

If you ever switch to Python 3 you can use bytes(some_string, encoding='utf-8') .

Ok in my case... the fix was setting response.headers with Flask's @app.after_request.

Apparently mod_wsgi likes unicode headers, but HTTP expects byte string. Here's the solution... Without it mod_wsgi will not let swagger.json load:

@app.after_request
def after(response):
    new_resp_headers = {}
    for k, v in response.headers.items():
        new_resp_headers[k.encode('ISO-8859-1')] = v.encode('ISO-8859-1')
    response.headers = new_resp_headers
    return response

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM