Dans cet exemple, un client appelle une ressource protégée. Mais quand on appelle /hello, une 500 est renvoyée. En analysant, la 500 provient d'une 401 sur la ressource protégée.
@RestController
public class ClientController {
@GetMapping("/hello")
public ResponseEntity<String> hello() {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/my-resource";
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.AUTHORIZATION, "my-token");
try {
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class, headers);
return ResponseEntity.ok(response.getBody());
} catch (RestClientException e) {
return ResponseEntity.status(HttpStatusCode.valueOf(500)).body(e.getMessage());
}
}
}
@RestController
public class ProtectedResourceController {
@GetMapping("/my-resource")
public ResponseEntity<String> getProtectedResource(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authorizationHeader) {
if (authorizationHeader != null && authorizationHeader.startsWith("my-token")) {
return ResponseEntity.ok("You are authorized");
}
return ResponseEntity.status(HttpStatusCode.valueOf(401)).body("No authorized");
}
}
La méthode getForEntity accepte comme 3e paramètre une Map :
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException;
Or nous passons une instance de HttpHeaders :
HttpHeaders headers = ...
...
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class, headers);
En regardant HttpHeaders on comprend d'où vient le problème :
public class HttpHeaders implements MultiValueMap<String, String>, Serializable { ... }
...
public interface MultiValueMap<K, V> extends Map<K, List<V>> { ... }
C'est un bel exemple de mauvaise abstraction. HttpHeaders n'est pas une MultiValueMap.
Conclusion, le principe "composition over inheritance" outrepassé ici.