Jakiego kodowania znaków należy używać w nagłówku HTTP?

122

Używam „zabawnego” specjalnego znaku HTML (✰) (zobacz http://html5boilerplate.com/, aby uzyskać więcej informacji) dla Servernagłówka HTTP i zastanawiam się, czy jest on „dozwolony” według specyfikacji.

  • Korzystając z karty Sieć w narzędziach programistycznych w przeglądarce Chrome w systemie Windows Xp Pro SP 3, widzę ✰ w porządku.

  • W IE8 ✰ nie jest poprawnie renderowane.

  • Walidator HTML w3.org nie renderuje go poprawnie ( â°zamiast tego wyświetla „ ”).

Otóż, nie przepadam za kodowaniem znaków… i szczerze mówiąc nie przejmuję się nimi zbytnio; Po prostu ślepo używam UTF-8, bo tak mi powiedziano. :-)


Czy rozbieżność jest spowodowana błędami w różnych parserach / przeglądarkach / silnikach / (jakkolwiek one się nazywają)?

Czy jest na to specyfikacja, czy może lista dozwolonych znaków dla „wartości” nagłówka HTTP?

David Murdoch
źródło
29
Ogólne
2
„Otóż, nie przepadam za kodowaniem znaków… i szczerze mówiąc, nie przejmuję się nimi zbytnio; po prostu ślepo używam UTF-8, bo tak mi powiedziano. :-)” <--- - Obowiązkowy link do joelonsoftware.com/2003/10/08/…
d4nyll

Odpowiedzi:

124

W skrócie: tylko ASCII gwarantuje działanie. Niektóre bajty inne niż ASCII są dozwolone ze względu na wsteczną kompatybilność, ale nie powinny być wyświetlane.

HTTPbis zrezygnował i stwierdził, że w nagłówkach nie ma żadnego użytecznego kodowania poza ASCII:

Historycznie, HTTP zezwalał na zawartość pola z tekstem w zestawie znaków ISO-8859-1 [ISO-8859-1], obsługując inne zestawy znaków tylko poprzez użycie kodowania [RFC2047]. W praktyce większość wartości pól nagłówka HTTP wykorzystuje tylko podzbiór zestawu znaków US-ASCII [USASCII]. Nowo zdefiniowane pola nagłówka POWINNY ograniczać ich wartości do oktetów US-ASCII. Odbiorca POWINIEN traktować inne oktety w treści pola (obs-text) jako nieprzezroczyste dane.


Wcześniej RFC 2616 z 1999 definiował to:

Słowa * TEXT MOGĄ zawierać znaki z zestawów znaków innych niż ISO-8859-1 [22] tylko wtedy, gdy są kodowane zgodnie z zasadami RFC 2047 [14].

a RFC 2047 to kodowanie MIME , więc byłoby:

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

ale nie sądzę, że wielu (jeśli jacyś) klientów to obsługuje.

Kornel
źródło
7
więc, co to znaczy? Czy „✰” jest prawidłowe / dozwolone?
David Murdoch
8
Aby nieco rozwinąć bardzo przydatną odpowiedź: „UTF-8” to zestaw znaków, a „Q” oznacza, że ​​wartość będzie „w cudzysłowie do druku”. "B" może być również użyte, jeśli chcesz zakodować wartość w BASE64.
GargantuChet
1
@porneL, Co więc oznaczają „nieprzezroczyste dane”? Co dokładnie powinien zrobić odbiorca HTTP , gdy otrzyma te „nieprzezroczyste dane”?
Pacerier,
1
@Pacerier „nieprzezroczyste dane” oznacza, że ​​jest to czarna skrzynka z wieloma bajtami, których aplikacje nie powinny próbować wyświetlać ani interpretować (jak dane binarne). To, co się z nim stanie, zależy od nagłówka, może wahać się od „nic” do „odrzucenia”.
Kornel
@Kornel, Btw, dlaczego zmieniłeś swoją nazwę użytkownika na kornel?
Pacerier,
10

Najpierw przeczytaj komentarze, ta odpowiedź prawdopodobnie wyciąga błędne wnioski z właściwych źródeł, wymaga edycji.


Możesz użyć dowolnych drukowalnych znaków ASCII i żadnych specjalnych znaków, takich jak ✰ (co nie jest ASCII )

Wskazówka : w JSON możesz zakodować wszystko.

Edycja : na początku może nie być oczywiste, kodowanie znaków zdefiniowane w nagłówku dotyczy tylko treści odpowiedzi, a nie samego nagłówka. (Ponieważ spowodowałoby to problem z kurczakiem i jajkiem).


Chciałbym podsumować wszystkie istotne definicje zgodnie ze specyfikacją, do której link zawiera Penchant.

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

Więc szukamy wartości pola .

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 oznacza Linear White Space. Zasadniczo LWS to spacja lub tabulator, ale możesz podzielić wartość pola na wiele wierszy, rozpoczynając nowy wiersz przed spacją lub tabulatorem.

Uprośćmy to do tego:

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

Teraz szukamy treści terenowych .

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

TEKST jest najbardziej ogólny i zawiera całą resztę - więc zapomnij o reszcie -. Oto zestaw znaków US-ASCII (= ASCII)

Jak widać, wszystkie drukowalne znaki ASCII są dozwolone.

zupa
źródło
3
Ci są sprzeczne fragmenty ty cytowane. Dlaczego mówisz „i nie ma specjalnych znaków takich jak ✰”? Znaki specjalne to po prostu OCTETs, a Ponieważ TEXTjest dowolny OCTETz wyjątkiem 0 - 31, oznacza to, że dozwolone są wszystkie znaki OCTETod 32do . Oktetów z ✰ są , i i wszystkie trzy z nich są dozwolone, dlatego ✰ jest dozwolone zgodnie z cytowanych fragmentów ty. 255 226156176
Pacerier,
2
@Pacerier wydajesz się mieć całkowitą rację, nie rozumiem, dlaczego wyciągnąłem taki wniosek.
zupa
@Pacerier jeszcze nie jestem gotowy, aby go edytować, ponieważ musiałem ponownie dwukrotnie sprawdzić specyfikację. Obawiam się, że dodatkowe szczegóły ograniczają się do zestawu znaków US-ASCII, który z kolei poparłby wniosek, ale uczyniłby rozumowanie niewystarczającym.
zupa
1
Powiedzenie „możesz zakodować wszystko w formacie JSON” jest nieco mylące. JSON dopuszcza znaki Unicode, natomiast nagłówki HTTP powinny mieć format US-ASCII. Znaki Unicode byłyby traktowane jako dane „nieprzezroczyste”, a zatem zachowanie jest niezdefiniowane w specyfikacji HTTP. To powiedziawszy, JSON można zabezpieczyć do umieszczenia w nagłówku HTTP poprzez ucieczkę znaków Unicode za pomocą sekwencji ucieczki \ uXXXX.
Jacob
@zupa, Kolejną kwestią jest… co oznacza „ opróczCTLs ”? To znaczy znaki CR, LFsą dozwolone? Czy może to oznacza, że dozwolona jest tylko ciągła sekwencja „ CR LF SP/ HT”? (Innymi słowy, można header wartości zawierać jeden CRlub LFlub HTwartości nagłówka może zawierać znaki? CR, LFI HTw dowolnej kolejności i ilości?)
Pacerier