Come leggere le intestazioni HTTP nei controller Spring REST

1. Introduzione

In questo breve tutorial, vedremo come accedere alle intestazioni HTTP in un controller Spring Rest.

Innanzitutto, utilizzeremo l' annotazione @RequestHeader per leggere le intestazioni individualmente e tutte insieme.

Dopodiché, daremo uno sguardo più approfondito agli attributi di @RequestHeader .

2. Accesso alle intestazioni HTTP

2.1. Individualmente

Se abbiamo bisogno di accedere a un'intestazione specifica, possiamo configurare @RequestHeader con il nome dell'intestazione:

@GetMapping("/greeting") public ResponseEntity greeting(@RequestHeader("accept-language") String language) { // code that uses the language variable return new ResponseEntity(greeting, HttpStatus.OK); }

Quindi, possiamo accedere al valore utilizzando la variabile passata nel nostro metodo. Se un'intestazione denominata accept-language non viene trovata nella richiesta, il metodo restituisce un errore "400 Bad Request".

Le nostre intestazioni non devono essere stringhe. Ad esempio, se sappiamo che la nostra intestazione è un numero, possiamo dichiarare la nostra variabile come un tipo numerico:

@GetMapping("/double") public ResponseEntity doubleNumber(@RequestHeader("my-number") int myNumber) { return new ResponseEntity(String.format("%d * 2 = %d", myNumber, (myNumber * 2)), HttpStatus.OK); }

2.2. Tutto in una volta

Se non siamo sicuri di quali intestazioni saranno presenti, o se ne occorrono più di quante ne vogliamo nella firma del nostro metodo, possiamo usare l' annotazione @RequestHeader senza un nome specifico.

Abbiamo alcune scelte per il nostro tipo di variabile: un oggetto Map , MultiValueMap o HttpHeaders .

Per prima cosa, otteniamo le intestazioni della richiesta come mappa :

@GetMapping("/listHeaders") public ResponseEntity listAllHeaders( @RequestHeader Map headers) { headers.forEach((key, value) -> { LOG.info(String.format("Header '%s' = %s", key, value)); }); return new ResponseEntity( String.format("Listed %d headers", headers.size()), HttpStatus.OK); }

Se usiamo una mappa e una delle intestazioni ha più di un valore , otterremo solo il primo valore . Questo è l'equivalente dell'utilizzo del metodo getFirst su MultiValueMap .

Se le nostre intestazioni possono avere più valori, possiamo ottenerle come MultiValueMap :

@GetMapping("/multiValue") public ResponseEntity multiValue( @RequestHeader MultiValueMap headers) { headers.forEach((key, value) ->  LOG.info(String.format( "Header '%s' = %s", key, value.stream().collect(Collectors.joining("); return new ResponseEntity( String.format("Listed %d headers", headers.size()), HttpStatus.OK); }

Possiamo anche ottenere le nostre intestazioni come oggetto HttpHeaders :

@GetMapping("/getBaseUrl") public ResponseEntity getBaseUrl(@RequestHeader HttpHeaders headers) { InetSocketAddress host = headers.getHost(); String url = "//" + host.getHostName() + ":" + host.getPort(); return new ResponseEntity(String.format("Base URL = %s", url), HttpStatus.OK); }

L' oggetto HttpHeaders dispone di funzioni di accesso per le intestazioni delle applicazioni comuni.

Quando accediamo a un'intestazione in base al nome da una mappa , MultiValueMap o l' oggetto HttpHeaders , otterremo un valore nullo se non è presente.

3. Attributi @RequestHeader

Ora che abbiamo esaminato le basi dell'accesso alle intestazioni delle richieste con l' annotazione @RequestHeader , diamo un'occhiata più da vicino ai suoi attributi.

Abbiamo già utilizzato implicitamente gli attributi name o value quando abbiamo specificamente chiamato la nostra intestazione:

public ResponseEntity greeting(@RequestHeader("accept-language") String language) {}

Possiamo ottenere la stessa cosa utilizzando l' attributo name :

public ResponseEntity greeting( @RequestHeader(name = "accept-language") String language) {}

Successivamente, usiamo l' attributo value esattamente allo stesso modo:

public ResponseEntity greeting( @RequestHeader(value = "accept-language") String language) {}

Quando nominiamo un'intestazione in modo specifico, l'intestazione è richiesta per impostazione predefinita. Se l'intestazione non viene trovata nella richiesta, il controller restituisce un errore 400.

Usiamo l' attributo richiesto per indicare che la nostra intestazione non è richiesta:

@GetMapping("/nonRequiredHeader") public ResponseEntity evaluateNonRequiredHeader( @RequestHeader(value = "optional-header", required = false) String optionalHeader) { return new ResponseEntity(String.format( "Was the optional header present? %s!", (optionalHeader == null ? "No" : "Yes")),HttpStatus.OK); }

Poiché la nostra variabile sarà nulla se l'intestazione non è presente nella richiesta , dobbiamo essere sicuri di eseguire il controllo null appropriato .

Usiamo l' attributo defaultValue per fornire un valore predefinito per la nostra intestazione:

@GetMapping("/default") public ResponseEntity evaluateDefaultHeaderValue( @RequestHeader(value = "optional-header", defaultValue = "3600") int optionalHeader) { return new ResponseEntity( String.format("Optional Header is %d", optionalHeader), HttpStatus.OK); }

4. Conclusione

In questo breve tutorial, abbiamo imparato come accedere alle intestazioni delle richieste nei controller Spring REST. Innanzitutto, abbiamo utilizzato l' annotazione @RequestHeader per fornire le intestazioni delle richieste ai nostri metodi di controller.

Dopo aver esaminato le basi, abbiamo esaminato in dettaglio gli attributi per l' annotazione @RequestHeader .

Il codice di esempio è disponibile su GitHub.