Cos'e HTTP 417 Expectation Failed
Il codice HTTP 417 Expectation Failed e emesso dal server quando non puo soddisfare l'aspettativa espressa dal client tramite l'header Expect:. Nella pratica, l'aspettativa quasi sempre usata e Expect: 100-continue: il client chiede al server di confermare che e disposto ad accettare il body prima di inviarlo.
Il flusso Expect: 100-continue
Senza Expect: 100-continue, ogni POST/PUT invia immediatamente headers + body. Se il server poi rifiuta (autenticazione, payload troppo grande, ecc), il body e stato trasmesso inutilmente. Con Expect:
- Client invia headers con
Expect: 100-continuema NON il body. - Server valuta headers e decide:
- Accetta: risponde
HTTP/1.1 100 Continue. Client invia il body. - Rifiuta: risponde direttamente con 4xx (es. 401, 413, 417).
- Accetta: risponde
- Dopo aver ricevuto il body, il server invia la risposta finale.
Esempio pratico
PUT /large-upload.bin HTTP/1.1
Host: api.example.com
Content-Length: 500000000
Authorization: Bearer xyz
Expect: 100-continue
# Server valuta headers...
HTTP/1.1 100 Continue
# Client invia il body 500MB
HTTP/1.1 201 Created
Quando si emette 417
Il server emette 417 quando:
- L'aspettativa Expect e diversa da
100-continuee il server non la supporta. - Il server non implementa affatto il meccanismo Expect (rara).
- Estensioni custom dell'header Expect non riconosciute.
Tecnicamente, se Expect contiene solo 100-continue e il server vuole rifiutare, dovrebbe usare il codice di errore appropriato (es. 413 per body troppo grande), non 417. Il 417 e per aspettative semanticamente non comprensibili.
Esempio
POST /api/resource HTTP/1.1
Expect: payment-required, 100-continue
HTTP/1.1 417 Expectation Failed
Content-Type: text/plain
This server does not understand the "payment-required" expectation.
Vantaggi del 100-continue
- Risparmio banda: body grandi non vengono inviati se il server rifiuterebbe.
- Failure fast: errori di auth/permessi rilevati prima del trasferimento.
- UX migliore: client puo cancellare l'upload precocemente.
- Risparmio server: meno I/O su body destinati a essere scartati.
Comportamento dei client
Diversi client gestiscono Expect: 100-continue diversamente:
- curl: lo invia automaticamente per body > 1KB. Disabilitabile con
-H "Expect:". - Java HttpURLConnection: opt-in via
setChunkedStreamingMode+ properties. - Python requests: non lo invia di default, va aggiunto manualmente.
- Browser: non lo usano nelle fetch standard.
- libcurl: default per body > 1KB su HTTP/1.1.
Timeout client
I client che inviano Expect aspettano un breve timeout (tipicamente 1-3 secondi) per la risposta 100. Se non arriva, inviano comunque il body. Questo previene deadlock con server che non capiscono Expect ma non rispondono 417.
Server side: implementazione
Apache HTTPD: gestisce 100-continue automaticamente. Per disabilitarlo: SetEnvIf Expect "100-continue" expect-100-disable.
Nginx: dalla versione 1.13.10 supporta nativamente http2_idle_timeout e gestisce Expect automaticamente per HTTP/1.1.
Application-level (Node, PHP): tipicamente il web server o reverse proxy gestisce, ma alcune fasi (es. autenticazione custom) potrebbero richiedere logica esplicita.
Workaround per server che non supportano 100-continue
Se un proxy intermedio rompe Expect, alcuni client (curl, libcurl) cadono in fallback: inviano comunque il body dopo il timeout. Per evitare overhead, disabilita Expect quando sai che il server non lo supporta:
curl --header "Expect:" -F "file=@bigfile.bin" https://example.com/upload
HTTP/2 e Expect
HTTP/2 ha meccanismi nativi per la stream prioritization e il flow control che rendono Expect: 100-continue meno necessario. Alcuni server HTTP/2 lo gestiscono comunque per retrocompatibilita, altri lo ignorano e procedono direttamente.
Errori comuni
- Proxy intermedi (Nginx, HAProxy, Apache come reverse) che dimenticano di propagare Expect al backend.
- Application code che non sa rispondere 100, lasciando il client appeso.
- Confusione tra 417 e 412 Precondition Failed (sono cose diverse: 412 e per If-Match etc.).
Diagnostica
curl -v -H "Expect: 100-continue" -d "test=1" https://example.com/api/endpoint
# Cerca nella verbose output:
< HTTP/1.1 100 Continue
# oppure
< HTTP/1.1 417 Expectation Failed
Quando il client invia Expect
libcurl invia Expect: 100-continue automaticamente quando body > 1KB. Comportamento configurabile via CURLOPT_HTTPHEADER con Expect: vuoto. Disabilitare quando si parla con server che non lo supportano (timeout aggiunto inutile).
Server che non rispondono 100
Alcuni server vecchi o configurazioni proxy errate ignorano completamente Expect e attendono direttamente il body. Client moderni hanno timeout (es. libcurl: 1 secondo) e inviano body comunque dopo timeout. Risultato: piccolo overhead di latenza, ma transazione completa.
Body grandi e auth fallita
Lo use case ideale: client vuole inviare 1GB ma il server richiede auth. Senza Expect, client uploaderebbe 1GB poi riceverebbe 401. Con Expect, riceve 401 immediatamente, risparmiando banda.
HTTP/2 e 100 Continue
HTTP/2 non usa il 100 Continue come HTTP/1.1: la stream prioritization e flow control nativi gestiscono il problema senza bisogno di un round trip esplicito. Alcuni server H2 (Nginx, Apache) emettono comunque 100 Continue per retrocompatibilita con tooling.
417 nel cloud
Servizi cloud (AWS API Gateway, GCP Cloud Endpoints) tipicamente strippano l'header Expect: 100-continue per semplicità. I client inviano direttamente. Per uploads grandi, raccomandati S3 presigned URL o equivalenti, bypassando il problema.
Hai bisogno di aiuto?
Se il tuo sito mostra errori HTTP, il team di G Tech Group puo aiutarti. Contattaci tramite il modulo di contatto.