From f9a9e817135ceb83e32380f8e7b409122c4fc0ba Mon Sep 17 00:00:00 2001 From: Vincent Guillet Date: Wed, 26 Nov 2025 14:25:25 +0100 Subject: [PATCH] Refactor PrestashopClient and PrestashopProxyController to improve query handling and enhance code clarity --- .../prestashop/PrestashopProxyController.java | 60 ++++--- .../service/prestashop/PrestashopClient.java | 165 +++++++----------- 2 files changed, 104 insertions(+), 121 deletions(-) diff --git a/api/src/main/java/fr/gameovergne/api/controller/prestashop/PrestashopProxyController.java b/api/src/main/java/fr/gameovergne/api/controller/prestashop/PrestashopProxyController.java index 011cfff..05d0499 100644 --- a/api/src/main/java/fr/gameovergne/api/controller/prestashop/PrestashopProxyController.java +++ b/api/src/main/java/fr/gameovergne/api/controller/prestashop/PrestashopProxyController.java @@ -16,21 +16,25 @@ public class PrestashopProxyController { this.prestashopClient = prestashopClient; } - // Utilitaire pour extraire /products, /products/446, etc. private String extractPath(HttpServletRequest request) { String fullPath = request.getRequestURI(); // ex: /api/ps/products/446 String contextPath = request.getContextPath(); // souvent "" String relative = fullPath.substring(contextPath.length()); // /api/ps/products/446 - return relative.replaceFirst("^/api/ps", ""); // => /products/446 + + // On enlève le préfixe /api/ps => /products/446 + return relative.replaceFirst("^/api/ps", ""); } - /* ---------------- GET ---------------- */ + /* =========================== + * GET + * =========================== */ + @GetMapping("/**") public ResponseEntity proxyGet(HttpServletRequest request) { String path = extractPath(request); - String query = request.getQueryString(); // on laisse tel quel + String rawQuery = request.getQueryString(); // on laisse Angular décider des filtres - String body = prestashopClient.get(path, query); + String body = prestashopClient.get(path, rawQuery); return ResponseEntity .ok() @@ -38,48 +42,60 @@ public class PrestashopProxyController { .body(body); } - /* ---------------- POST ---------------- */ + /* =========================== + * POST + * =========================== */ + @PostMapping("/**") - public ResponseEntity proxyPost(HttpServletRequest request, - @RequestBody String xmlBody) { + public ResponseEntity proxyPost( + HttpServletRequest request, + @RequestBody String rawBody + ) { String path = extractPath(request); - String query = request.getQueryString(); + String rawQuery = request.getQueryString(); - String responseBody = prestashopClient.post(path, query, xmlBody); + String body = prestashopClient.post(path, rawQuery, rawBody); - // Presta peut renvoyer JSON ou XML, mais côté front tu traites en JSON return ResponseEntity .ok() .contentType(MediaType.APPLICATION_JSON) - .body(responseBody); + .body(body); } - /* ---------------- PUT ---------------- */ + /* =========================== + * PUT + * =========================== */ + @PutMapping("/**") - public ResponseEntity proxyPut(HttpServletRequest request, - @RequestBody String xmlBody) { + public ResponseEntity proxyPut( + HttpServletRequest request, + @RequestBody String rawBody + ) { String path = extractPath(request); - String query = request.getQueryString(); + String rawQuery = request.getQueryString(); - String responseBody = prestashopClient.put(path, query, xmlBody); + String body = prestashopClient.put(path, rawQuery, rawBody); return ResponseEntity .ok() .contentType(MediaType.APPLICATION_JSON) - .body(responseBody); + .body(body); } - /* ---------------- DELETE ---------------- */ + /* =========================== + * DELETE + * =========================== */ + @DeleteMapping("/**") public ResponseEntity proxyDelete(HttpServletRequest request) { String path = extractPath(request); - String query = request.getQueryString(); + String rawQuery = request.getQueryString(); - String responseBody = prestashopClient.delete(path, query); + String body = prestashopClient.delete(path, rawQuery); return ResponseEntity .ok() .contentType(MediaType.APPLICATION_JSON) - .body(responseBody); + .body(body); } } \ No newline at end of file diff --git a/api/src/main/java/fr/gameovergne/api/service/prestashop/PrestashopClient.java b/api/src/main/java/fr/gameovergne/api/service/prestashop/PrestashopClient.java index 97afe61..be9369f 100644 --- a/api/src/main/java/fr/gameovergne/api/service/prestashop/PrestashopClient.java +++ b/api/src/main/java/fr/gameovergne/api/service/prestashop/PrestashopClient.java @@ -4,14 +4,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; +import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; -import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; -import java.util.List; - @Service public class PrestashopClient { @@ -30,50 +28,37 @@ public class PrestashopClient { this.basicAuth = basicAuth; } - /* ------------------------------------------------------------------ - * Helpers communs - * ------------------------------------------------------------------ */ - - private HttpHeaders baseHeaders() { - HttpHeaders headers = new HttpHeaders(); - headers.set(HttpHeaders.AUTHORIZATION, "Basic " + basicAuth); - return headers; - } - - private String normalizePath(String path) { - if (path == null || path.isBlank()) { - return "/"; - } - return path.startsWith("/") ? path : "/" + path; - } - - /* ------------------------------------------------------------------ - * GET : force JSON + display=full - * - on garde tous les autres paramètres (filter[..], limit, etc.) - * - on écrase/normalise seulement output_format et display - * => équivalent à ce que tu faisais en front avec output_format=JSON&display=full - * ------------------------------------------------------------------ */ - public String get(String path, String query) { - String normalizedPath = normalizePath(path); + /* =========================== + * GET (proxy) + * =========================== */ + /** + * GET générique vers PrestaShop. + * + * - On part de la query envoyée par le front (filters, price[use_tax], ...). + * - On force/se remplace uniquement output_format=JSON et display=full. + */ + public String get(String path, @Nullable String rawQuery) { UriComponentsBuilder builder = UriComponentsBuilder .fromHttpUrl(baseUrl) .path("/api") - .path(normalizedPath); + .path(path); - if (query != null && !query.isBlank()) { - builder.query(query); // on garde tous les filtres venus du front + // On remet la query EXACTEMENT comme envoyée par Angular + if (rawQuery != null && !rawQuery.isBlank()) { + builder.query(rawQuery); } - // on force ces deux-là pour corriger les soucis des crochets + id seuls + // On force juste ces deux paramètres builder.replaceQueryParam("output_format", "JSON"); builder.replaceQueryParam("display", "full"); String url = builder.build(true).toUriString(); + log.info("[PrestaShop] GET {}", url); - HttpHeaders headers = baseHeaders(); - headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + HttpHeaders headers = new HttpHeaders(); + headers.set(HttpHeaders.AUTHORIZATION, "Basic " + basicAuth); HttpEntity entity = new HttpEntity<>(headers); @@ -85,7 +70,7 @@ public class PrestashopClient { String.class ); - log.info("[PrestaShop] Réponse GET {} pour {}", response.getStatusCode(), url); + log.info("[PrestaShop] Réponse HTTP {} pour {}", response.getStatusCode(), url); if (!response.getStatusCode().is2xxSuccessful()) { throw new RuntimeException("PrestaShop returned non-2xx status: " @@ -93,42 +78,38 @@ public class PrestashopClient { } return response.getBody(); - } catch (HttpStatusCodeException e) { - log.error("[PrestaShop] Erreur GET {} status={} body={}", - url, e.getStatusCode(), e.getResponseBodyAsString(), e); - throw new RuntimeException("Erreur GET PrestaShop", e); } catch (RestClientException e) { log.error("[PrestaShop] Erreur GET {}", url, e); throw new RuntimeException("Erreur GET PrestaShop", e); } } - /* ------------------------------------------------------------------ - * POST : XML vers Presta - * - on transmet la query EXACTE venant du front (price[use_tax], filter, etc.) - * - PAS de output_format / display forcés ici - * ------------------------------------------------------------------ */ - public String post(String path, String query, String xmlBody) { - String normalizedPath = normalizePath(path); + /* =========================== + * POST + * =========================== */ + public String post(String path, @Nullable String rawQuery, String body) { UriComponentsBuilder builder = UriComponentsBuilder .fromHttpUrl(baseUrl) .path("/api") - .path(normalizedPath); + .path(path); - if (query != null && !query.isBlank()) { - builder.query(query); + if (rawQuery != null && !rawQuery.isBlank()) { + builder.query(rawQuery); } + // Pour POST, tu peux choisir de forcer output_format si tu veux la réponse en JSON + builder.replaceQueryParam("output_format", "JSON"); + String url = builder.build(true).toUriString(); + log.info("[PrestaShop] POST {}", url); - log.debug("[PrestaShop] POST body=\n{}", xmlBody); - HttpHeaders headers = baseHeaders(); - headers.setContentType(MediaType.APPLICATION_XML); // Presta attend du XML sur POST/PUT - headers.setAccept(List.of(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)); + HttpHeaders headers = new HttpHeaders(); + headers.set(HttpHeaders.AUTHORIZATION, "Basic " + basicAuth); + headers.setContentType(MediaType.APPLICATION_XML); // Presta attend du XML - HttpEntity entity = new HttpEntity<>(xmlBody, headers); + HttpEntity entity = new HttpEntity<>(body, headers); try { ResponseEntity response = restTemplate.exchange( @@ -138,50 +119,45 @@ public class PrestashopClient { String.class ); - log.info("[PrestaShop] Réponse POST {} pour {}", response.getStatusCode(), url); + log.info("[PrestaShop] Réponse HTTP {} pour {}", response.getStatusCode(), url); if (!response.getStatusCode().is2xxSuccessful()) { throw new RuntimeException("PrestaShop returned non-2xx status: " - + response.getStatusCode() + " for URL " + url - + " body=" + response.getBody()); + + response.getStatusCode() + " for URL " + url); } return response.getBody(); - } catch (HttpStatusCodeException e) { - log.error("[PrestaShop] Erreur POST {} status={} body={}", - url, e.getStatusCode(), e.getResponseBodyAsString(), e); - throw new RuntimeException("Erreur POST PrestaShop", e); } catch (RestClientException e) { log.error("[PrestaShop] Erreur POST {}", url, e); throw new RuntimeException("Erreur POST PrestaShop", e); } } - /* ------------------------------------------------------------------ - * PUT : XML vers Presta - * - pareil que POST : on garde la query telle quelle, pas de display=full ici - * ------------------------------------------------------------------ */ - public String put(String path, String query, String xmlBody) { - String normalizedPath = normalizePath(path); + /* =========================== + * PUT + * =========================== */ + public String put(String path, @Nullable String rawQuery, String body) { UriComponentsBuilder builder = UriComponentsBuilder .fromHttpUrl(baseUrl) .path("/api") - .path(normalizedPath); + .path(path); - if (query != null && !query.isBlank()) { - builder.query(query); + if (rawQuery != null && !rawQuery.isBlank()) { + builder.query(rawQuery); } + builder.replaceQueryParam("output_format", "JSON"); + String url = builder.build(true).toUriString(); + log.info("[PrestaShop] PUT {}", url); - log.debug("[PrestaShop] PUT body=\n{}", xmlBody); - HttpHeaders headers = baseHeaders(); + HttpHeaders headers = new HttpHeaders(); + headers.set(HttpHeaders.AUTHORIZATION, "Basic " + basicAuth); headers.setContentType(MediaType.APPLICATION_XML); - headers.setAccept(List.of(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)); - HttpEntity entity = new HttpEntity<>(xmlBody, headers); + HttpEntity entity = new HttpEntity<>(body, headers); try { ResponseEntity response = restTemplate.exchange( @@ -191,46 +167,42 @@ public class PrestashopClient { String.class ); - log.info("[PrestaShop] Réponse PUT {} pour {}", response.getStatusCode(), url); + log.info("[PrestaShop] Réponse HTTP {} pour {}", response.getStatusCode(), url); if (!response.getStatusCode().is2xxSuccessful()) { throw new RuntimeException("PrestaShop returned non-2xx status: " - + response.getStatusCode() + " for URL " + url - + " body=" + response.getBody()); + + response.getStatusCode() + " for URL " + url); } return response.getBody(); - } catch (HttpStatusCodeException e) { - log.error("[PrestaShop] Erreur PUT {} status={} body={}", - url, e.getStatusCode(), e.getResponseBodyAsString(), e); - throw new RuntimeException("Erreur PUT PrestaShop", e); } catch (RestClientException e) { log.error("[PrestaShop] Erreur PUT {}", url, e); throw new RuntimeException("Erreur PUT PrestaShop", e); } } - /* ------------------------------------------------------------------ - * DELETE - * - idem : on relaie la query telle quelle - * ------------------------------------------------------------------ */ - public String delete(String path, String query) { - String normalizedPath = normalizePath(path); + /* =========================== + * DELETE + * =========================== */ + public String delete(String path, @Nullable String rawQuery) { UriComponentsBuilder builder = UriComponentsBuilder .fromHttpUrl(baseUrl) .path("/api") - .path(normalizedPath); + .path(path); - if (query != null && !query.isBlank()) { - builder.query(query); + if (rawQuery != null && !rawQuery.isBlank()) { + builder.query(rawQuery); } + builder.replaceQueryParam("output_format", "JSON"); + String url = builder.build(true).toUriString(); + log.info("[PrestaShop] DELETE {}", url); - HttpHeaders headers = baseHeaders(); - headers.setAccept(List.of(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)); + HttpHeaders headers = new HttpHeaders(); + headers.set(HttpHeaders.AUTHORIZATION, "Basic " + basicAuth); HttpEntity entity = new HttpEntity<>(headers); @@ -242,19 +214,14 @@ public class PrestashopClient { String.class ); - log.info("[PrestaShop] Réponse DELETE {} pour {}", response.getStatusCode(), url); + log.info("[PrestaShop] Réponse HTTP {} pour {}", response.getStatusCode(), url); if (!response.getStatusCode().is2xxSuccessful()) { throw new RuntimeException("PrestaShop returned non-2xx status: " - + response.getStatusCode() + " for URL " + url - + " body=" + response.getBody()); + + response.getStatusCode() + " for URL " + url); } return response.getBody(); - } catch (HttpStatusCodeException e) { - log.error("[PrestaShop] Erreur DELETE {} status={} body={}", - url, e.getStatusCode(), e.getResponseBodyAsString(), e); - throw new RuntimeException("Erreur DELETE PrestaShop", e); } catch (RestClientException e) { log.error("[PrestaShop] Erreur DELETE {}", url, e); throw new RuntimeException("Erreur DELETE PrestaShop", e);