如何在Flask中将Unicode标题转换为字节字符串?

3

我有一个Flask应用程序,在开发服务器上可以运行。但是,当我尝试在mod_wsgi下运行相同的应用程序时,出现错误:

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

我尝试了很多不同的方法来转换标题,但是我一直得到相同的错误:

for k,v in dict(request.headers).iteritems():
    response.headers[k.encode('latin-1')] = v.encode('latin-1')

我也尝试了以下内容,但仍然出现完全相同的错误提示:
.encode('utf-8'), decode('utf-8'), decode('latin-1'), str()

我做错了什么吗?

编辑(真实的堆栈跟踪...我想):

[Wed Mar 12 23:26:49 2014] [notice] Apache/2.2.25 (Unix) mod_wsgi/3.4 Python/2.7.5 configured -- resuming normal operations
[Wed Mar 12 23:26:49 2014] [info] Server built: Sep  9 2013 06:59:27
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524834): Starting process 'api' with threads=1.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524834): Initializing Python.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524835): Starting process 'api' with threads=1.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524835): Initializing Python.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524833): Starting process 'api' with threads=1.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524833): Initializing Python.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524832): Starting process 'api' with threads=1.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524832): Initializing Python.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524831): Starting process 'api' with threads=1.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524831): Initializing Python.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524833): Attach interpreter ''.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524833): Adding '/path/to/api/lib/python2.7' to path.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524834): Attach interpreter ''.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524834): Adding '/path/to/api/lib/python2.7' to path.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524832): Attach interpreter ''.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524832): Adding '/path/to/api/lib/python2.7' to path.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524835): Attach interpreter ''.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524835): Adding '/path/to/api/lib/python2.7' to path.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524831): Attach interpreter ''.
[Wed Mar 12 23:26:49 2014] [info] mod_wsgi (pid=524831): Adding '/path/to/api/lib/python2.7' to path.
[Wed Mar 12 23:26:51 2014] [info] mod_wsgi (pid=524833): Create interpreter 'web23.webfaction.com|'.
[Wed Mar 12 23:26:51 2014] [info] mod_wsgi (pid=524833): Adding '/path/to/api/lib/python2.7' to path.
[Wed Mar 12 23:26:51 2014] [info] [client 127.0.0.1] mod_wsgi (pid=524833, process='api', application='web23.webfaction.com|'): Loading WSGI script '/path/to/api/wsgi.py'.
[Wed Mar 12 23:26:52 2014] [error] [client 127.0.0.1] mod_wsgi (pid=524833): Exception occurred processing WSGI script '/path/to/api/wsgi.py'.
[Wed Mar 12 23:26:52 2014] [error] [client 127.0.0.1] TypeError: expected byte string object for header name, value of type unicode found

编辑 #2: 这里是Flask中的视图,我正在尝试获取令牌以及如何修改标题(或者至少是尝试):

@app.route('/oauth/token/', methods=['GET','POST'],subdomain='api')
@oauth.token_handler # e.g. the decorator for OAuthlib/OAuthlib-Flask
def access_token():
  return None

@app.after_request
def after(response):
  import urllib
  for k,v in dict(request.headers).iteritems():
    response.headers[urllib.quote(k)] = urllib.quote(v)

  return response

第三版编辑(“打印字典(请求头项).items()”输出):

[('Forwarded-Request-Uri', u'/oauth/token?client_secret=rDRzy2Qgt627dZK6eFtnylluOad7PRuLNUBothIpb0KQWJmOBl&grant_type=client_credentials&client_id=lryd8PqzlSObOQNUUEgEjqKYIeCnnkifs1s16NZ1'), ('Accept-Encoding', u'gzip, deflate, compress'), ('X-Forwarded-Host', u'api.example.com'), ('X-Forwarded-For', u'917.85.235.27'), ('Http-X-Forwarded-Proto', u'https'), ('Host', u'api.example.com'), ('Accept', u'*/*'), ('User-Agent', u'python-requests/2.2.1 CPython/2.7.5+ Linux/3.11.0-12-generic'), ('Connection', u'close'), ('X-Forwarded-Proto', u'https'), ('Https', u'on'), ('X-Forwarded-Server', u'api.example.com'), ('X-Forwarded-Ssl', u'on')]

请问您能否分享完整的堆栈跟踪信息? - metatoaster
4
这并非完整的回溯信息,它只显示了异常所在的行;其余内容是来自其他地方的日志输出。 - Martijn Pieters
1
你尝试过在mod_wsgi上运行一个最小的“hello world” Flask应用程序吗?它是否产生错误?请参阅DebuggingTechniques - jfs
是的,Hello World 应用程序运行良好,如果我没有请求使用 OAuthlib 和 Flask-OAuthlib 的任何内容,我的应用程序也能正常运行。当尝试获取访问令牌时,我遇到了这个问题。 - user3287829
好的...我想我得到了完整的堆栈跟踪...请检查编辑 - user3287829
显示剩余2条评论
3个回答

2
怎么样?
bytes(whatever_unicode.encode("utf-8"))

或者按照J.F. Sebastians的评论
some_unicode.encode("ISO-8859-1")

或许,这与IT技术有关。
import urllib
urllib.quote(unicode_string)

其中一个应该管用...我认为


2
这里的“bytes”是多余的。默认情况下,http头使用的是ISO-8859-1字符集,而不是utf-8。例如,[所有当前的桌面浏览器都支持rfc6266和rfc5987来表示文件名中的字符超出了ISO-8859-1](https://dev59.com/W3M_5IYBdhLWcg3wfTE0)。 - jfs
感谢@J.F.Sebastian!非常有用的信息,实际上我会在我的回答中添加和扩展它(尽管如果你用它来回答,我可能会删除我的回答并点赞你的)。 - Joran Beasley
1
使用urllib quote会发生什么? - Joran Beasley
一样的事情。我猜我在flask中没有正确修改头文件。我在我的@app.after_request函数中有这个功能。 - user3287829
1
添加一个实际的示例,我们可以复制并重现。否则我不确定我能提供多少帮助(即使有示例我也不确定我能提供多少帮助)。 - Joran Beasley
显示剩余3条评论

0

它正在工作!

file = request.files.get('fileupload')

file = StringIO(file.read().decode("ISO-8859-1"))

0

我被这个问题困扰了很长时间。我对所选择的答案一点也不满意。这是我在生产中所使用的代码:

@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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接