Que codificação de caracteres devo usar para um cabeçalho HTTP?

122

Estou usando um caractere especial HTML "divertido" (✰) (consulte http://html5boilerplate.com/ para obter mais informações) para um Servercabeçalho HTTP e estou me perguntando se ele é "permitido" por especificação.

  • Usando a guia Rede nas ferramentas de desenvolvimento do Chrome no Windows Xp Pro SP 3, vejo ✰ muito bem.

  • No IE8, o ✰ não é renderizado corretamente.

  • O validador HTML w3.org não o processa corretamente (exibe " â°" em vez disso).

Bem, não estou muito interessado em codificações de caracteres ... e, francamente, não me importo muito com eles; Eu apenas uso cus UTF-8 porque me disseram para usar. :-)


A disparidade é causada por bugs nos diferentes analisadores / navegadores / motores / (seja lá como forem)?

Existe uma especificação para isso ou talvez uma lista de caracteres permitidos para um "valor" de cabeçalho HTTP?

David Murdoch
fonte
29
Essa pergunta seria muito melhor geralmente: "Quais caracteres são permitidos em um valor de cabeçalho http"
Akrikos de
2
"Agora, não estou muito interessado em codificações de caracteres ... e, francamente, eu realmente não me importo muito com eles; eu apenas uso cegamente UTF-8 porque me disseram para fazer. :-)" <--- - Link obrigatório para joelonsoftware.com/2003/10/08/…
d4nyll

Respostas:

124

Resumindo: apenas ASCII tem garantia de funcionamento. Alguns bytes não ASCII são permitidos para compatibilidade com versões anteriores, mas não devem ser exibidos.

HTTPbis desistiu e especificou que nos cabeçalhos não há codificação útil além de ASCII:

Historicamente, o HTTP permitiu conteúdo de campo com texto no conjunto de caracteres ISO-8859-1 [ISO-8859-1], suportando outros conjuntos de caracteres apenas através do uso da codificação [RFC2047]. Na prática, a maioria dos valores de campo de cabeçalho HTTP usa apenas um subconjunto do conjunto de caracteres US-ASCII [USASCII]. Os campos de cabeçalho recém-definidos DEVEM limitar seus valores de campo a octetos US-ASCII. Um destinatário DEVE tratar outros octetos no conteúdo do campo (obs-text) como dados opacos.


Anteriormente, RFC 2616 de 1999 definia isso:

Palavras de * TEXTO PODEM conter caracteres de conjuntos de caracteres diferentes da ISO-8859-1 [22] somente quando codificados de acordo com as regras da RFC 2047 [14].

e RFC 2047 é a codificação MIME , então seria:

=?UTF-8?Q?=E2=9C=B0?=

mas não acho que muitos (se houver) clientes o suportem.

Kornel
fonte
7
Então, o que isso significa? "✰" é válido / permitido?
David Murdoch
8
Para expandir um pouco uma resposta muito útil: "UTF-8" é o conjunto de caracteres e "Q" significa que o valor será "imprimível entre aspas". "B" também pode ser usado se você quiser codificar o valor em BASE64.
GargantuChet
1
@porneL, então o que significa "dados opacos"? O que exatamente o destinatário HTTP deve fazer ao receber esses "dados opacos"?
Pacerier
1
@Pacerier "dados opacos" significa que é uma caixa preta com um monte de bytes que os aplicativos não deveriam tentar exibir ou interpretar (como dados binários). O que acontece com ele depende do cabeçalho, pode variar de "nada" a "descartar".
Kornel de
@Kornel, Btw, por que você mudou seu nome de usuário para kornel?
Pacerier
10

Leia os comentários primeiro, esta resposta provavelmente tira conclusões erradas das fontes certas, precisa ser editada.


Você pode usar qualquer caractere ASCII para impressão, e nenhum caractere especial como ✰ (que não é ASCII )

Dica : você pode codificar qualquer coisa em JSON.

Editar : pode não ser óbvio a princípio, a codificação de caracteres definida no cabeçalho se aplica apenas ao corpo da resposta, não ao cabeçalho em si. (Isso poderia causar um problema de ovo e galinha.)


Eu gostaria de resumir todas as definições relevantes de acordo com as especificações vinculadas por Penchant.

message-header = field-name ":" [ field-value ]
field-name     = token
field-value    = *( field-content | LWS )

Então, estamos atrás do valor do campo .

LWS            = [CRLF] 1*( SP | HT )
CRLF           = CR LF
CR             = <US-ASCII CR, carriage return (13)>
LF             = <US-ASCII LF, linefeed (10)>
SP             = <US-ASCII SP, space (32)>
HT             = <US-ASCII HT, horizontal-tab (9)>

LWS significa Linear White Space. Essencialmente, LWS é Espaço ou Tab, mas você pode quebrar o valor do seu campo em várias linhas, iniciando uma nova linha antes de um Espaço ou Tab.

Vamos simplificar para isso:

field-value    = <any field-content or Space or Tab>

Agora estamos atrás do conteúdo do campo .

field-content  = <the OCTETs making up the field-value
                 and consisting of either *TEXT or combinations
                 of token, separators, and quoted-string>
OCTET          = <any 8-bit sequence of data>
TEXT           = <any OCTET except CTLs,
                 but including LWS>
CTL            = <any US-ASCII control character
                 (octets 0 - 31) and DEL (127)>
token          = 1*<any CHAR except CTLs or separators>
separators     = "(" | ")" | "<" | ">" | "@"
                 | "," | ";" | ":" | "\" | <">
                 | "/" | "[" | "]" | "?" | "="
                 | "{" | "}" | SP | HT

TEXTO é o mais geral e inclui todo o resto - então esqueça o resto-. Aqui está o conjunto de caracteres US-ASCII (= ASCII)

Como você pode ver, todos os caracteres ASCII imprimíveis são permitidos.

zupa
fonte
3
Você está contradizendo as passagens que citou. Por que você diz "e nenhum caractere especial como ✰"? Os caracteres especiais são apenas OCTETs, e como TEXTqualquer um OCTETexceto 0 - 31, isso significa que todos os OCTETs de 32a 255 são permitidos . Os octetos de ✰ são 226, 156e, 176e todos os três são permitidos, portanto ✰ é permitido de acordo com as passagens que você citou.
Pacerier
2
@Pacerier você parece completamente certo, não vejo por que cheguei a essa conclusão.
zupa
@Pacerier ainda não estou pronto para editá-lo, pois precisava verificar as especificações novamente. Temo que detalhes adicionais se restrinjam ao conjunto de caracteres US-ASCII que, por sua vez, apoiaria a conclusão, mas tornaria o raciocínio insuficiente.
zupa
1
Dizer "você pode codificar qualquer coisa em JSON" é um pouco enganador. JSON permite caracteres Unicode, enquanto os cabeçalhos HTTP devem ser US-ASCII. Os caracteres Unicode seriam tratados como dados "opacos" e, portanto, o comportamento é indefinido pela especificação HTTP. Dito isso, o JSON pode se tornar seguro para inclusão em um cabeçalho HTTP escapando dos caracteres Unicode por meio da sequência de escape \ uXXXX.
Jacob
@zupa, Outro problema é ... o que significa " excetoCTLs "? Será que isso significa os personagens CR, LFsão permitidos? Ou isso significa que apenas a sequência contínua " CR LF SP/ HT" é permitida? (Por outras palavras, pode conter valores de cabeçalho um único CRou LFou HTvalores de cabeçalho pode conter os caracteres? CR, LFE HTem qualquer ordem e quantidade?)
Pacerier