Passa al contenuto principale

1. Introduction

Specificare la sintassi di nuovi campi header e trailer HTTP è un compito impegnativo; anche con la guida della Sezione 8.3.1 di [RFC7231], per i potenziali autori di campi HTTP rimangono molte decisioni da prendere e molte insidie.

Una volta definito un campo, spesso è necessario scrivere parser e serializer personalizzati, perché ogni valore di campo tratta in modo leggermente diverso sintassi che sembrano comuni.

Questo documento introduce un insieme di strutture dati comuni per la definizione di nuovi valori di campo HTTP, in modo da affrontare questi problemi. In particolare, definisce un modello astratto comune per tali strutture dati e una serializzazione concreta di quel modello nei campi header e trailer HTTP [RFC7230].

I campi HTTP definiti come "Structured Header" o "Structured Trailer", oppure come "Structured Field" quando possono essere entrambi, usano i tipi definiti in questa specifica per definire la propria sintassi e le regole di elaborazione di base. Questo semplifica il lavoro degli autori di specifiche e degli implementatori.

Inoltre, versioni future di HTTP possono definire serializzazioni alternative del modello astratto di queste strutture, consentendo ai campi che usano il modello di essere trasmessi in modo più efficiente senza ridefinirli.

Si noti che lo scopo di questo documento non è ridefinire la sintassi dei campi HTTP esistenti; i meccanismi descritti qui si applicano solo ai campi che scelgono esplicitamente di usarli.

La Sezione 2 descrive come specificare uno Structured Field.

La Sezione 3 definisce diversi tipi di dati astratti che possono essere usati negli Structured Fields.

Questi tipi astratti possono essere serializzati in valori di campo HTTP, o analizzati da essi, usando gli algoritmi descritti nella Sezione 4.


1.1 Intentionally Strict Processing

Questa specifica definisce deliberatamente un comportamento rigoroso di parsing e serializzazione mediante algoritmi passo-passo; l'unica gestione degli errori definita consiste nel far fallire completamente l'operazione.

Questa scelta mira a incoraggiare implementazioni fedeli e una buona interoperabilità. Di conseguenza, un'implementazione che tenta di "aiutare" accettando input in modo più permissivo peggiora in pratica l'interoperabilità, perché esercita pressione sulle altre implementazioni affinché adottino soluzioni simili, ma potenzialmente diverse in modo sottile.

In altre parole, l'elaborazione rigorosa è una caratteristica intenzionale di questa specifica; consente di individuare e correggere prima gli input non conformi ed evita possibili problemi di interoperabilità e sicurezza.

Si noti che, a causa di questa rigorosità, se un campo viene accodato da più parti, ad esempio intermediari o componenti diversi del mittente, un errore nel valore di una delle parti può causare il fallimento del parsing dell'intero valore del campo.


1.2 Notational Conventions

Le parole chiave "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY" e "OPTIONAL" in questo documento devono essere interpretate come descritto in BCP 14 [RFC2119] [RFC8174] quando, e solo quando, compaiono tutte in maiuscolo come mostrato qui.

Questo documento usa algoritmi per specificare il comportamento di parsing e serializzazione e usa la notazione Augmented Backus-Naur Form (ABNF) di [RFC5234] per illustrare la sintassi prevista nei campi header HTTP. In questo processo usa le regole VCHAR, SP, DIGIT, ALPHA e DQUOTE di [RFC5234]. Include anche le regole tchar e OWS di [RFC7230].

Quando si esegue il parsing da campi HTTP, le implementazioni MUST avere un comportamento indistinguibile da quello ottenuto seguendo gli algoritmi. Se c'è divergenza tra un algoritmo di parsing e l'ABNF, prevale l'algoritmo specificato.

Per la serializzazione verso campi HTTP, l'ABNF illustra la rappresentazione prevista sul filo, mentre gli algoritmi definiscono il modo raccomandato per produrla. Le implementazioni MAY discostarsi dal comportamento specificato, purché l'output possa comunque essere elaborato correttamente dagli algoritmi di parsing descritti nella Sezione 4.2.


Punti Chiave

1. Contesto del problema

Difficoltà nella definizione dei campi HTTP tradizionali:

# Ogni campo ha la propria sintassi:
Cache-Control: max-age=3600, private
Accept: text/html, application/json;q=0.9
Content-Type: text/html; charset=utf-8
Link: `https://example.com`; rel="preload"

# Risultato:
- ogni campo richiede un parser personalizzato
- sintassi apparentemente simili hanno in realta differenze sottili
- facile sbagliare, difficile da mantenere

2. Soluzione

Gli Structured Fields offrono:

  • Tipi di dati uniformi: Integer, String, Boolean, List, Dictionary, ecc.
  • Serializzazione standardizzata: regole di formato coerenti
  • Algoritmi di parsing espliciti: eliminazione delle ambiguita
  • Compatibilita in avanti: in futuro si potranno usare codifiche più efficienti

3. Filosofia della rigorosita

Esempio errato - parser permissivo:
Input: key="value (apice di chiusura mancante)
Parsing permissivo: aggiunge automaticamente l'apice e riesce

Problema:
- implementazioni diverse possono "riparare" in modi diversi
- comportamento imprevedibile
- creazione di vulnerabilita di sicurezza

Esempio corretto - parser rigoroso:
Input: key="value (apice di chiusura mancante)
Parsing rigoroso: fallisce immediatamente e restituisce un errore

Vantaggi:
- forza i produttori a generare il formato corretto
- garantisce comportamento coerente tra le implementazioni
- individua i problemi prima

4. Obiettivi di progettazione

  • Non ridefinire i campi esistenti: usare solo per nuovi campi
  • Astratto + concreto: modello astratto + serializzazione HTTP/1.1
  • Estendibile in futuro: si possono definire nuove serializzazioni per HTTP/2 e HTTP/3

5. Struttura del documento

Sezione 2: come definire Structured Fields -> guida per autori di specifiche
Sezione 3: tipi di dati astratti -> List, Dictionary, Item, ecc.
Sezione 4: algoritmi di serializzazione e parsing -> dettagli implementativi concreti

Impatto Pratico

Per gli autori di specifiche

Approccio tradizionale:
----------------------
Definire un nuovo campo "Example-Field"
- scrivere sintassi ABNF personalizzata
- descrivere in dettaglio le regole di parsing
- gestire casi limite
- definire la gestione degli errori
(potrebbero servire decine di pagine)

Approccio Structured Fields:
---------------------------
Definire un nuovo campo "Example-Field"
- citare RFC 8941
- dichiarare che e di tipo Dictionary
- definire il significato di chiavi e valori
(potrebbero bastare pochi paragrafi)

Per gli implementatori

// Approccio tradizionale - ogni campo richiede un parser personalizzato
function parseCacheControl(value) {
// 50-100 righe di codice...
}
function parseAccept(value) {
// altre 50-100 righe di codice...
}
function parseContentType(value) {
// ancora 50-100 righe di codice...
}

// Approccio Structured Fields - parser generici
const cacheControl = parseDictionary(header); // riuso
const accept = parseList(header); // riuso
const contentType = parseItem(header); // riuso

Per l'efficienza di rete

HTTP/1.1: formato testuale
Example-Dict: a=1, b=2, c=3

HTTP/2 (futuro): possibile codifica binaria
[0x01] [dict] [3 items] [a:1] [b:2] [c:3]
piu compatta, ma con la stessa logica

Casi d'Uso

Quando usare gli Structured Fields

  • Definizione di nuovi header HTTP
  • Necessita di strutture dati complesse, come liste o dizionari
  • Desiderio di supportare codifiche più efficienti in futuro
  • Ricerca di buona interoperabilita

Quando non usare gli Structured Fields

  • Campi esistenti gia definiti, come Cache-Control
  • Campi semplici con un solo valore, dove l'uso e possibile ma non necessario
  • Campi che devono mantenere compatibilita con client legacy