Intestazioni HTTP personalizzate: convenzioni di denominazione


1115

Molti dei nostri utenti ci hanno chiesto di includere i dati relativi al loro account nelle intestazioni HTTP delle richieste che inviamo loro, o anche le risposte che ricevono dalla nostra API. Qual è la convenzione generale per aggiungere intestazioni HTTP personalizzate, in termini di denominazione , formato ... ecc.

Inoltre, sentiti libero di pubblicare qualsiasi utilizzo intelligente di questi che ti sei imbattuto sul web; Stiamo cercando di implementare questo usando ciò che è meglio là fuori come obiettivo :)


25
Tenere presente che i firewall possono rimuovere i campi di intestazione della risposta. Alcuni rimuovono tutto ciò che non è menzionato in RFC 2616 (giugno 1999, HTTP 1.1). Il lato client dovrebbe essere ancora utilizzabile senza i nuovi campi.
Stesch

5
Si noti che il commento di @stesch non si applica quando si utilizza HTTP S .
code_dredd,

1
Nota che il commento di @code_dredd è una leggenda urbana. I firewall possono filtrare il contenuto HTTPS. Vedi howtoforge.com/filtering-https-traffic-with-squid e watchguard.com/help/docs/wsm/xtm_11/en-us/content/en-us/…
stesch,

@stesch Dato che il tuo articolo fondamentalmente trasforma il proxy in qualcosa di simile a un MiTM (prende una connessione client crittografata e poi ne crea una nuova) quindi certo, puoi fare quasi tutto, ma questo fatto nega la crittografia dal PoV del proxy b / c sta decifrando il contenuto stesso del client. In quel caso, dal PoV del proxy, è praticamente come se non stessi usando HTTPS in primo luogo ...
code_dredd

Risposte:


1172

La raccomandazione è stata di iniziare il loro nome con la "X". Ad esempio X-Forwarded-For, X-Requested-With. Questo è anche menzionato nella sezione 5 di RFC 2047 .


Aggiornamento 1 : a giugno 2011, è stata pubblicata la prima bozza IETF per deprecare la raccomandazione di utilizzare il prefisso "X-" per intestazioni non standard. Il motivo è che quando le intestazioni non standard con prefisso "X-" diventano standard, la rimozione del prefisso "X-" interrompe la compatibilità con le versioni precedenti, costringendo i protocolli applicativi a supportare entrambi i nomi (ad esempio, x-gzipe gzipora sono equivalenti). Quindi, la raccomandazione ufficiale è di nominarli sensibilmente senza il prefisso "X-".


Aggiornamento 2 : a giugno 2012, la deprecazione della raccomandazione di utilizzare il prefisso "X-" è diventata ufficiale come RFC 6648 . Di seguito sono citate le citazioni rilevanti:

3. Consigli per i creatori di nuovi parametri

...

  1. NON DOVREBBE anteporre i nomi dei loro parametri con "X-" o costrutti simili.

4. Raccomandazioni per i progettisti di protocollo

...

  1. NON DOVREBBE vietare la registrazione di parametri con un prefisso "X-" o costrutti simili.

  2. NON DEVE stipulare che un parametro con un prefisso "X-" o costrutti simili deve essere inteso come non standardizzato.

  3. NON DEVE stipulare che un parametro senza prefisso "X-" o costrutti simili debba essere inteso come standardizzato.

Nota che "NON DOVREBBE" ("scoraggiato") non è lo stesso di "NON DEVE" ("proibito"), vedi anche RFC 2119 per un'altra specifica su tali parole chiave. In altre parole, puoi continuare a usare le intestazioni con prefisso "X-", ma non è più ufficialmente raccomandato e potresti sicuramente non documentarle come se fossero standard pubblici.


Riepilogo :

  • la raccomandazione ufficiale è semplicemente nominarli sensibilmente senza il prefisso "X-"
  • puoi continuare a usare le intestazioni con prefisso "X-", ma non è più ufficialmente raccomandato e potresti sicuramente non documentarle come se fossero standard pubblici

306
Proprio come ci sono molti bambini che non finiranno mai come atleti professionisti, molte intestazioni personalizzate non finiranno mai come standard. Sono propenso a mantenere la "X-" su quelli.
G-Mac,

19
@ G-Mac concordato. Ci sono così tante intestazioni personalizzate che non finiranno mai per essere standardizzate. I pochi che lo fanno, è semplice modificare il codice da if (header == "x-gzip")a if (header == "x-gzip" || header == "gzip"). Per quanto riguarda la tua analogia, eccone un'altra: è come se i militari dicessero "Oh, è problematico cambiare qualcuno da Privato a Generale. Quindi, da ora in poi, siete tutti Generali. Ora non abbiamo bisogno di fare così tanto lavoro"
Cole Johnson,

24
@ColeJohnson Non sono sicuro se questa analogia funzioni. Il problema qui è che non esiste un punto centrale in cui è possibile modificare il nome. Ogni singolo frammento di codice che prevede ora x-gzip deve essere modificato, oppure la vecchia intestazione deve continuare a essere utilizzata in aggiunta a quella nuova. E 'preferibile andare con RFC 6648.
Vinod

4
@Vinod sì. Ha senso, ma ci sono così tanti standard proposti che non vedranno mai la luce del giorno. Per i tipi di file, certo; rilasciare il X-prefisso. Sono contrario, ma vai avanti e fallo. Per le intestazioni OTOH, non lasciarlo cadere. Rende facile guardare e dire "oh, non è standard; posso ignorarlo" vs "ci sono quelle X-intestazioni non standard , e poi c'è questa che non riconosco; posso ignorarla in sicurezza?"
Cole Johnson,

21
Sebbene il tono della risposta di cweekly sia inutilmente difensivo, credo che abbia ragione, e il suo punto risolve il problema illustrato in questo thread di commenti. In breve, non tentare di identificare se un'intestazione si "laurea" o no; determina invece se si tratta di un'intestazione privata o pubblica (specifica dell'applicazione o "generica" ​​/ "globale"). Per le intestazioni private, utilizzare facoltativamente X-per garantire lo scontro con le intestazioni pubbliche (grazie a RFC6648, che si occupa delle intestazioni pubbliche) e inoltre utilizzare sicuramente un prefisso privato arbitrario. Per le intestazioni pubbliche, non utilizzare X-in nessun caso.
TNE

535

La domanda deve essere riletta. La vera domanda posta non è simile ai prefissi dei fornitori nelle proprietà CSS, dove è appropriato pensare al futuro e al supporto del fornitore e agli standard ufficiali. La vera domanda posta è più simile alla scelta dei nomi dei parametri della query URL. A nessuno dovrebbe interessare quello che sono. Ma la spaziatura dei nomi di quelli personalizzati è una cosa perfettamente valida - e comune e corretta - da fare.

Razionale:
si tratta di convenzioni tra sviluppatori per intestazioni personalizzate e specifiche dell'applicazione - " dati rilevanti per il loro account " - che non hanno nulla a che fare con fornitori, organismi di standardizzazione o protocolli che devono essere implementati da terzi, tranne che lo sviluppatore in questione deve semplicemente evitare i nomi di intestazione che potrebbero avere altri usi previsti da server, proxy o client. Per questo motivo, gli esempi "X-Gzip / Gzip" e "X-Forwarded-For / Forwarded-For" sono controversi. La domanda posta riguarda le convenzioni nel contesto di un'API privata, simile alle convenzioni di denominazione dei parametri della query URL. È una questione di preferenza e spaziatura dei nomi; dubbi sul fatto che "X-ClientDataFoo" sia supportato da qualsiasi proxy o fornitore senza la "X"

Non c'è niente di speciale o magico nel prefisso "X-", ma aiuta a chiarire che si tratta di un'intestazione personalizzata. In effetti, RFC-6648 e altri aiutano a sostenere il caso dell'uso di un prefisso "X-", perché - poiché i fornitori di client e server HTTP abbandonano il prefisso - l'API privata, l'API specifica, i dati personali- il meccanismo di passaggio sta diventando ancora più isolato dalle collisioni dello spazio dei nomi con il piccolo numero di nomi di intestazione riservati ufficiali. Detto questo, la mia preferenza personale e la mia raccomandazione è di fare un passo avanti e fare ad esempio "X-ACME-ClientDataFoo" (se la tua compagnia di widget è "ACME").

IMHO le specifiche IETF non sono sufficientemente specifiche per rispondere alla domanda del PO, perché non riescono a distinguere tra casi d'uso completamente diversi: (A) fornitori che introducono nuove funzionalità applicabili a livello globale come "Forwarded-For" da un lato, rispetto a (B) sviluppatori di app che passano stringhe specifiche dell'app a / da client e server. La specifica riguarda solo la prima, (A). La domanda qui è se ci sono convenzioni per (B). Ci sono. Coinvolgono il raggruppamento dei parametri in ordine alfabetico e la loro separazione dalle numerose intestazioni di tipo (A) rilevanti per gli standard. L'uso del prefisso "X-" o "X-ACME-" è conveniente e legittimo per (B) e non è in conflitto con (A). Più fornitori smettono di usare "X-" per (A), più chiaramente diventeranno quelli (B).

Esempio:
Google (che ha un po 'di peso nei vari organismi di standardizzazione) sta - ad oggi, 20141102 in questa leggera modifica alla mia risposta - attualmente utilizzando "X-Mod-Pagespeed" per indicare la versione del loro modulo Apache coinvolto nella trasformazione di una determinata risposta. Qualcuno sta davvero suggerendo che Google dovrebbe usare "Mod-Pagespeed", senza la "X-", e / o chiedere all'IETF di benedire il suo utilizzo?

Riepilogo:
se stai usando intestazioni HTTP personalizzate (come alternativa talvolta appropriata ai cookie) all'interno della tua app per trasmettere dati al / dal tuo server, e queste intestazioni NON sono esplicitamente destinate a essere utilizzate al di fuori del contesto del tuo applicazione, spaziandoli con un prefisso "X-" o "X-FOO-" è una convenzione ragionevole e comune.


52
Mi farebbe piacere se alcuni votanti del mio commento potessero spiegare quale parte della mia risposta trovano discutibile. Non mi interessa molto del mio punteggio di reputazione, ma sono sinceramente curioso. Dove sta il disaccordo? Grazie.
bisettimanali

56
Sono completamente d'accordo con la tua risposta ed è l'unica risposta qui che risponde alla domanda effettiva posta. Stiamo parlando di intestazioni personalizzate e specifiche dell'applicazione qui, che non saranno mai standardizzate negli standard HTTP. Esiste una convenzione comune per queste che le persone tendono ad usare? (come prefissandoli con "_" forse? cioè: ("_ClientDataFoo")
Marchy

14
Grazie Marchy, sì, la risposta accettata non risponde alla domanda posta. La deprecazione IETF del prefisso "X-" per le intestazioni non standard (ma generiche) è irrilevante per le intestazioni personalizzate specifiche dell'app che non saranno mai standardizzate. Per rispondere alla tua domanda, secondo la mia opinione ed esperienza (16 anni di webdev), la migliore convenzione è quella di utilizzare il già citato "X-ACME-ClientData". "X-" bc non è standard (né lo sarà mai, motivo per cui la deprecazione IETF è discutibile qui), "ACME-" per lo spazio dei nomi alla tua società "ACME" o app specifica, e "ClientData" può essere qualunque nome semantico che ti piace. :)
circa il

5
@DarrelMiller ... da qui la raccomandazione di utilizzare X-ACMECO-WIDGET-FOO. Insisto sul fatto che, per la domanda del PO come chiesto, l'uso di X- semplicemente non è controindicato da RFC-6648 e simili. Se sei un fornitore che fornisce un framework, una libreria o un modulo da utilizzare nei progetti di altre persone, questa è una storia diversa e segui sicuramente quel RFC fino a un T. Ma è solo un argomento controverso per singole applicazioni singole, in cui personalizzato le convenzioni di denominazione dell'intestazione specifiche dell'app sono in realtà API completamente private. Come si scontrerebbero con i nomi di "tutti gli altri"? Di chi sarebbero?
bisettimanale

11
Sinceramente, ho qualche problema a comprendere il ragionamento RFC. Concesso che, se e quando il parametro è standardizzato, ci saranno versioni sia x che non x. Questo è un problema solo se il comportamento delle versioni x e non x è identico. Mi sono imbattuto qui perché sto cercando di aggiungere un'intestazione "per conto di" alla mia API. Potrebbe diventare pubblico un giorno (in quanto è un tipo comune di caso d'uso). Se ho usato "On-Behalf-Of" e un giorno aggiungono che come intestazione standard, quali sono le probabilità che la mia semantica sarà identica a quella standardizzata?
fool4jesus,

62

Il formato per le intestazioni HTTP è definito nelle specifiche HTTP. Parlerò di HTTP 1.1, per il quale la specifica è RFC 2616 . Nella sezione 4.2, "Intestazioni dei messaggi", viene definita la struttura generale di un'intestazione:

   message-header = field-name ":" [ field-value ]
   field-name     = token
   field-value    = *( field-content | LWS )
   field-content  = <the OCTETs making up the field-value
                    and consisting of either *TEXT or combinations
                    of token, separators, and quoted-string>

Questa definizione si basa su due pilastri principali, token e TEXT. Entrambi sono definiti nella sezione 2.2, "Regole di base". Il token è:

   token          = 1*<any CHAR except CTLs or separators>

A sua volta appoggiato su CHAR, CTL e separatori:

   CHAR           = <any US-ASCII character (octets 0 - 127)>

   CTL            = <any US-ASCII control character
                    (octets 0 - 31) and DEL (127)>

   separators     = "(" | ")" | "<" | ">" | "@"
                  | "," | ";" | ":" | "\" | <">
                  | "/" | "[" | "]" | "?" | "="
                  | "{" | "}" | SP | HT

TESTO è:

   TEXT           = <any OCTET except CTLs,
                    but including LWS>

Dove LWS è uno spazio bianco lineare, la cui definizione non riprodurrò, e OCTET è:

   OCTET          = <any 8-bit sequence of data>

C'è una nota che accompagna la definizione:

The TEXT rule is only used for descriptive field contents and values
that are not intended to be interpreted by the message parser. Words
of *TEXT MAY contain characters from character sets other than ISO-
8859-1 [22] only when encoded according to the rules of RFC 2047
[14].

Quindi, due conclusioni. Innanzitutto, è chiaro che il nome dell'intestazione deve essere composto da un sottoinsieme di caratteri ASCII: alfanumerici, alcuni segni di punteggiatura, non molto altro. In secondo luogo, non esiste nulla nella definizione di un valore di intestazione che lo limiti a ASCII o esclude caratteri a 8 bit: è esplicitamente composto da ottetti, con solo caratteri di controllo esclusi (si noti che CR e LF sono considerati controlli). Inoltre, il commento sulla produzione TEXT implica che gli ottetti devono essere interpretati come in ISO-8859-1 e che esiste un meccanismo di codifica (che è orribile, per inciso) per rappresentare personaggi al di fuori di quella codifica.

Quindi, per rispondere a @BalusC in particolare, è abbastanza chiaro che secondo le specifiche, i valori di intestazione sono in ISO-8859-1. Ho inviato caratteri alti 8859-1 (in particolare alcune vocali accentate usate in francese) in un'intestazione di Tomcat e li ho interpretati correttamente da Firefox, quindi, in una certa misura, funziona sia in pratica che in teoria (sebbene questa fosse un'intestazione Location, che contiene un URL, e questi caratteri non sono legali negli URL, quindi questo era in realtà illegale, ma con una regola diversa!).

Detto questo, non farei affidamento sul fatto che ISO-8859-1 funzioni su tutti i server, i proxy e i client, quindi mi atterrerei all'ASCII come una questione di programmazione difensiva.


3
La nuova specifica HTTP RFC7230 dice "I campi di intestazione appena definiti DOVREBBERO limitare i loro valori di campo agli ottetti US-ASCII."
Robert Tupelo-Schneck,

23

RFC6648 consiglia di presumere che l'intestazione personalizzata "potrebbe diventare standardizzata, pubblica, comunemente distribuita o utilizzabile su più implementazioni". Pertanto, si consiglia di non prefissarlo con "X-" o costrutti simili.

Tuttavia, esiste un'eccezione "quando è estremamente improbabile che [la tua intestazione] sia mai standardizzata". Per tali intestazioni "specifiche dell'implementazione e di uso privato", la RFC afferma che uno spazio dei nomi come un prefisso del fornitore è giustificato.


6
"RFC6648 consiglia di presumere che l'intestazione personalizzata" possa diventare standardizzata, pubblica, comunemente distribuita o utilizzabile su più implementazioni. "Penso che questo dia una ragione per usare il X-prefisso perché è più probabile che qualcosa senza prefisso possa diventare standardizzato.
Konrad

@Konrad Se supponi che l' intestazione simile di qualcun altro (non la tua intestazione) possa diventare standardizzata, potresti evitare un conflitto X-, ma questo è un presupposto diverso da quello che RFC6648 prende principalmente. L'eccezione della RFC tiene conto di potenziali conflitti tra un'intestazione standard futura e un'intestazione di un altro fornitore la cui tecnologia potrebbe essere integrata con la vostra attraverso la fusione di società, ecc. Ecco perché l'eccezione richiede un prefisso fornitore.
Edward Brey,

17

La modifica o, più correttamente, l' aggiunta di ulteriori intestazioni HTTP è un ottimo strumento di debug del codice se non altro.

Quando una richiesta URL restituisce un reindirizzamento o un'immagine, non esiste una "pagina" html in cui scrivere temporaneamente i risultati del codice di debug, almeno non visibile in un browser.

Un approccio consiste nel scrivere i dati in un file di registro locale e visualizzarlo in un secondo momento. Un altro è aggiungere temporaneamente le intestazioni HTTP che riflettano i dati e le variabili in fase di debug.

Aggiungo regolarmente ulteriori intestazioni HTTP come X-fubar-somevar: o X-testing-someresult: per testare le cose - e ho trovato molti bug che altrimenti sarebbero stati molto difficili da rintracciare.


2
Perché dovrebbe usare questo "standard"? Le intestazioni funzionano allo stesso modo. Anche con un prefisso "WHO_EVER_READS_THIS_IS_DUMB_" ...
L'incredibile

16

Il registro dei nomi dei campi di intestazione è definito in RFC3864 e non c'è niente di speciale con "X-".

Per quanto ne so, non ci sono linee guida per le intestazioni private; nel dubbio, evitali. Oppure dai un'occhiata al HTTP Extension Framework ( RFC 2774 ).

Sarebbe interessante capire di più del caso d'uso; perché non è possibile aggiungere le informazioni al corpo del messaggio?


13
Il motivo principale per cui sto prendendo in considerazione alcune intestazioni personalizzate è che posso prendere decisioni
sull'instradamento
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.