我应该如何解码从字节到字符串的HTTP标头?

时间:2014-12-08 11:25:48

标签: python http header

基本上我正在尝试从头开始在python中创建一个小型Web服务器(只是为了学习),我遇到了解码头的问题。代码归结为此(我已将其简化为与问题相关的代码):

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 80))
sock.listen(1)

while True:
    conn, addr = sock.accept()

    print(addr[0])
    request = conn.recv(2048).decode('utf-8')

    headers = (
        'HTTP/1.0 200 OK',
        'Content-Type: text/html'
    )

    content = 'success'

    response = "\n".join(headers) + "\r\n\r\n" + content

    conn.sendall(bytes(response, 'UTF-8'))

    conn.close()

我安装了用于Firefox的插件HttpRequester,以摆弄我目前所拥有的并尝试附加文件,这导致了以下错误:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x90 in position 386: invalid start byte

我该如何解决这个问题?我应该在try中包装这个东西:并忽略导致这种异常的请求吗?

1 个答案:

答案 0 :(得分:2)

RFC 7230有关于字段解析的说法:

  

历史上,HTTP允许在ISO-8859-1字符集[ISO-8859-1]中使用文本的字段内容,仅通过使用[RFC2047]编码来支持其他字符集。实际上,大多数HTTP头字段值仅使用US-ASCII字符集[USASCII]的子集。新定义的标题字段应该将其字段值限制为US-ASCII八位字节。收件人应该将字段内容(obs-text)中的其他八位字节视为不透明数据。

其中RFC 2047为您提供了使用其他字符集的扩展机制;无论如何,这些都将编码为ASCII,并需要一个额外的步骤来解码。就个人而言,我从未见过在HTTP通信中实际使用过这样的标题。

因此,您可以安全地假设所有标头都可以解码为Latin-1,并且RFC 2047标头可以在以后单独处理:

request = conn.recv(2048)
headers, sep, body = request.partition(b'\r\n\r\n')
headers = headers.decode('latin1') 

这确实假设所有标头都适合这些2048字节。

Latin-1(ISO-8859-1)将字节直接解码为一对一,转换为Unicode代码点;即使那些应被视为不透明数据的字段也可以这种方式解码,即使这可能是这些标头的错误编解码器。在实践中,你可能不会遇到这样的标题,即使你这样做,你也不会关心这些标题。重要的标题都是ASCII编码的。