From 8680b2fc9213da7afa0e350023ca2d86a0a6e057 Mon Sep 17 00:00:00 2001 From: Vincent Guillet Date: Wed, 3 Dec 2025 11:03:26 +0100 Subject: [PATCH] Enhance PrestashopProxyController and PrestashopClient to support POST, PUT, and DELETE methods with raw query handling --- .../prestashop/PrestashopProxyController.java | 80 ++++++++++++++++--- .../service/prestashop/PrestashopClient.java | 52 ++++++++++-- 2 files changed, 117 insertions(+), 15 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 dad0147..41a7e2f 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 @@ -1,13 +1,11 @@ -package fr.gameovergne.api.controller; +package fr.gameovergne.api.controller.prestashop; import fr.gameovergne.api.service.prestashop.PrestashopClient; import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.AntPathMatcher; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.HandlerMapping; import java.net.URLDecoder; @@ -23,28 +21,90 @@ public class PrestashopProxyController { this.prestashopClient = prestashopClient; } - @GetMapping("/**") - public ResponseEntity proxyGet(HttpServletRequest request) { + // --- Helpers communs --- + + private String extractPath(HttpServletRequest request) { String fullPath = (String) request.getAttribute( - HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); + HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + ); String bestMatchPattern = (String) request.getAttribute( - HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); + HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE + ); String relativePath = new AntPathMatcher() .extractPathWithinPattern(bestMatchPattern, fullPath); + // On renvoie toujours avec un "/" devant + return "/" + relativePath; + } + + private String extractDecodedQuery(HttpServletRequest request) { String rawQuery = request.getQueryString(); if (rawQuery != null) { - // 🔥 Correction : on désencode les caractères URL avant de relayer à Presta rawQuery = URLDecoder.decode(rawQuery, StandardCharsets.UTF_8); } + return rawQuery; + } + + // ---------- GET ---------- + @GetMapping("/**") + public ResponseEntity proxyGet(HttpServletRequest request) { + String path = extractPath(request); + String rawQuery = extractDecodedQuery(request); ResponseEntity prestaResponse = - prestashopClient.getWithRawQuery("/" + relativePath, rawQuery); + prestashopClient.getWithRawQuery(path, rawQuery); return ResponseEntity .status(prestaResponse.getStatusCode()) .contentType(MediaType.APPLICATION_JSON) .body(prestaResponse.getBody()); } + + // ---------- POST ---------- + @PostMapping("/**") + public ResponseEntity proxyPost(HttpServletRequest request, + @RequestBody String xmlBody) { + String path = extractPath(request); + String rawQuery = extractDecodedQuery(request); + + ResponseEntity prestaResponse = + prestashopClient.postWithRawQuery(path, rawQuery, xmlBody); + + return ResponseEntity + .status(prestaResponse.getStatusCode()) + .contentType(MediaType.APPLICATION_XML) + .body(prestaResponse.getBody()); + } + + // ---------- PUT ---------- + @PutMapping("/**") + public ResponseEntity proxyPut(HttpServletRequest request, + @RequestBody String xmlBody) { + String path = extractPath(request); + String rawQuery = extractDecodedQuery(request); + + ResponseEntity prestaResponse = + prestashopClient.putWithRawQuery(path, rawQuery, xmlBody); + + return ResponseEntity + .status(prestaResponse.getStatusCode()) + .contentType(MediaType.APPLICATION_XML) + .body(prestaResponse.getBody()); + } + + // ---------- DELETE ---------- + @DeleteMapping("/**") + public ResponseEntity proxyDelete(HttpServletRequest request) { + String path = extractPath(request); + String rawQuery = extractDecodedQuery(request); + + ResponseEntity prestaResponse = + prestashopClient.deleteWithRawQuery(path, rawQuery); + + return ResponseEntity + .status(prestaResponse.getStatusCode()) + .contentType(MediaType.APPLICATION_XML) + .body(prestaResponse.getBody()); + } } \ 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 b99fea3..a846e06 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 @@ -99,12 +99,8 @@ public class PrestashopClient { .toBodilessEntity(); } - // -------- Méthode générique utilisée par le proxy /api/ps/** -------- + // -------- Méthodes génériques utilisées par le proxy /api/ps/** -------- - /** - * Proxy brut : on lui donne le path Presta (ex: "/categories") et la query string déjà encodée. - * On récupère un ResponseEntity pour pouvoir propager le status code. - */ public ResponseEntity getWithRawQuery(String path, String rawQuery) { String uri = baseUrl + path; if (rawQuery != null && !rawQuery.isBlank()) { @@ -119,4 +115,50 @@ public class PrestashopClient { .retrieve() .toEntity(String.class); } + + public ResponseEntity postWithRawQuery(String path, String rawQuery, String xmlBody) { + String uri = baseUrl + path; + if (rawQuery != null && !rawQuery.isBlank()) { + uri = uri + "?" + rawQuery; + } + + log.info("[PrestaShop] POST (proxy) {}", uri); + + return client.post() + .uri(uri) + .contentType(MediaType.APPLICATION_XML) + .body(xmlBody) + .retrieve() + .toEntity(String.class); + } + + public ResponseEntity putWithRawQuery(String path, String rawQuery, String xmlBody) { + String uri = baseUrl + path; + if (rawQuery != null && !rawQuery.isBlank()) { + uri = uri + "?" + rawQuery; + } + + log.info("[PrestaShop] PUT (proxy) {}", uri); + + return client.put() + .uri(uri) + .contentType(MediaType.APPLICATION_XML) + .body(xmlBody) + .retrieve() + .toEntity(String.class); + } + + public ResponseEntity deleteWithRawQuery(String path, String rawQuery) { + String uri = baseUrl + path; + if (rawQuery != null && !rawQuery.isBlank()) { + uri = uri + "?" + rawQuery; + } + + log.info("[PrestaShop] DELETE (proxy) {}", uri); + + return client.delete() + .uri(uri) + .retrieve() + .toEntity(String.class); + } } \ No newline at end of file