Skip to content

Instantly share code, notes, and snippets.

@thieux
Created April 16, 2024 21:15
Show Gist options
  • Save thieux/ee8866011d247f0593701b8c57989f6a to your computer and use it in GitHub Desktop.
Save thieux/ee8866011d247f0593701b8c57989f6a to your computer and use it in GitHub Desktop.

Un problème de type...

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment