Enhance PrestashopProxyController and PrestashopClient to support POST, PUT, and DELETE methods with raw query handling

This commit is contained in:
Vincent Guillet
2025-12-03 11:03:26 +01:00
parent 5068390a14
commit 8680b2fc92
2 changed files with 117 additions and 15 deletions

View File

@@ -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<String> 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<String> proxyGet(HttpServletRequest request) {
String path = extractPath(request);
String rawQuery = extractDecodedQuery(request);
ResponseEntity<String> 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<String> proxyPost(HttpServletRequest request,
@RequestBody String xmlBody) {
String path = extractPath(request);
String rawQuery = extractDecodedQuery(request);
ResponseEntity<String> prestaResponse =
prestashopClient.postWithRawQuery(path, rawQuery, xmlBody);
return ResponseEntity
.status(prestaResponse.getStatusCode())
.contentType(MediaType.APPLICATION_XML)
.body(prestaResponse.getBody());
}
// ---------- PUT ----------
@PutMapping("/**")
public ResponseEntity<String> proxyPut(HttpServletRequest request,
@RequestBody String xmlBody) {
String path = extractPath(request);
String rawQuery = extractDecodedQuery(request);
ResponseEntity<String> prestaResponse =
prestashopClient.putWithRawQuery(path, rawQuery, xmlBody);
return ResponseEntity
.status(prestaResponse.getStatusCode())
.contentType(MediaType.APPLICATION_XML)
.body(prestaResponse.getBody());
}
// ---------- DELETE ----------
@DeleteMapping("/**")
public ResponseEntity<String> proxyDelete(HttpServletRequest request) {
String path = extractPath(request);
String rawQuery = extractDecodedQuery(request);
ResponseEntity<String> prestaResponse =
prestashopClient.deleteWithRawQuery(path, rawQuery);
return ResponseEntity
.status(prestaResponse.getStatusCode())
.contentType(MediaType.APPLICATION_XML)
.body(prestaResponse.getBody());
}
}

View File

@@ -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<String> pour pouvoir propager le status code.
*/
public ResponseEntity<String> 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<String> 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<String> 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<String> 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);
}
}