Refactor PrestashopProxyController to streamline API endpoint handling and improve code readability

This commit is contained in:
Vincent Guillet
2025-12-03 12:28:22 +01:00
parent d076286728
commit ff331e1630

View File

@@ -2,139 +2,94 @@ package fr.gameovergne.api.controller.prestashop;
import fr.gameovergne.api.service.prestashop.PrestashopClient; import fr.gameovergne.api.service.prestashop.PrestashopClient;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger; import lombok.RequiredArgsConstructor;
import org.slf4j.LoggerFactory; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
@RestController @RestController
@RequestMapping("/api/ps") @RequestMapping("/api") // important : ton context-path est /gameovergne-api, donc ici on reste sur /api
@RequiredArgsConstructor
@Slf4j
public class PrestashopProxyController { public class PrestashopProxyController {
Logger log = LoggerFactory.getLogger(PrestashopProxyController.class);
private final PrestashopClient prestashopClient; private final PrestashopClient prestashopClient;
public PrestashopProxyController(PrestashopClient prestashopClient) { // ---------- GET générique /api/ps/** ----------
this.prestashopClient = prestashopClient;
}
// --- Helpers communs --- @GetMapping(path = "/ps/**", produces = MediaType.APPLICATION_JSON_VALUE)
private String extractPath(HttpServletRequest request) {
String fullPath = (String) request.getAttribute(
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE
);
String bestMatchPattern = (String) request.getAttribute(
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) {
rawQuery = URLDecoder.decode(rawQuery, StandardCharsets.UTF_8);
}
return rawQuery;
}
// ---------- GET ----------
@GetMapping("/**")
public ResponseEntity<String> proxyGet(HttpServletRequest request) { public ResponseEntity<String> proxyGet(HttpServletRequest request) {
String path = extractPath(request); String requestUri = request.getRequestURI(); // ex: /gameovergne-api/api/ps/categories
String rawQuery = extractDecodedQuery(request); String path = requestUri.substring(request.getContextPath().length() + "/api".length()); // -> /ps/categories
String rawQuery = request.getQueryString();
ResponseEntity<String> prestaResponse = return prestashopClient.getWithRawQuery(path, rawQuery);
prestashopClient.getWithRawQuery(path, rawQuery);
return ResponseEntity
.status(prestaResponse.getStatusCode())
.contentType(MediaType.APPLICATION_JSON)
.body(prestaResponse.getBody());
} }
// ---------- POST ---------- // ---------- POST générique XML /api/ps/** (catégories, produits, etc.) ----------
@PostMapping("/**")
@PostMapping(
path = "/ps/**",
consumes = MediaType.APPLICATION_XML_VALUE,
produces = MediaType.APPLICATION_XML_VALUE
)
public ResponseEntity<String> proxyPost(HttpServletRequest request, public ResponseEntity<String> proxyPost(HttpServletRequest request,
@RequestBody String xmlBody) { @RequestBody String xmlBody) {
String path = extractPath(request);
String rawQuery = extractDecodedQuery(request); String requestUri = request.getRequestURI();
String path = requestUri.substring(request.getContextPath().length() + "/api".length()); // ex: /ps/categories
String rawQuery = request.getQueryString();
log.info("XML envoyé à Presta:\n{}", xmlBody); log.info("XML envoyé à Presta:\n{}", xmlBody);
ResponseEntity<String> prestaResponse = return prestashopClient.postWithRawQuery(path, rawQuery, xmlBody);
prestashopClient.postWithRawQuery(path, rawQuery, xmlBody);
return ResponseEntity
.status(prestaResponse.getStatusCode())
.contentType(MediaType.APPLICATION_XML)
.body(prestaResponse.getBody());
} }
// ---------- PUT ---------- // ---------- PUT générique XML /api/ps/** ----------
@PutMapping("/**")
@PutMapping(
path = "/ps/**",
consumes = MediaType.APPLICATION_XML_VALUE,
produces = MediaType.APPLICATION_XML_VALUE
)
public ResponseEntity<String> proxyPut(HttpServletRequest request, public ResponseEntity<String> proxyPut(HttpServletRequest request,
@RequestBody String xmlBody) { @RequestBody String xmlBody) {
String path = extractPath(request);
String rawQuery = extractDecodedQuery(request);
log.info("XML envoyé à Presta:\n{}", xmlBody); String requestUri = request.getRequestURI();
String path = requestUri.substring(request.getContextPath().length() + "/api".length());
String rawQuery = request.getQueryString();
ResponseEntity<String> prestaResponse = log.info("XML envoyé (proxy PUT):\n{}", xmlBody);
prestashopClient.putWithRawQuery(path, rawQuery, xmlBody);
return ResponseEntity return prestashopClient.putWithRawQuery(path, rawQuery, xmlBody);
.status(prestaResponse.getStatusCode())
.contentType(MediaType.APPLICATION_XML)
.body(prestaResponse.getBody());
} }
// ---------- DELETE ---------- // ---------- DELETE générique /api/ps/** ----------
@DeleteMapping("/**")
@DeleteMapping(path = "/ps/**", produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<String> proxyDelete(HttpServletRequest request) { public ResponseEntity<String> proxyDelete(HttpServletRequest request) {
String path = extractPath(request);
String rawQuery = extractDecodedQuery(request);
ResponseEntity<String> prestaResponse = String requestUri = request.getRequestURI();
prestashopClient.deleteWithRawQuery(path, rawQuery); String path = requestUri.substring(request.getContextPath().length() + "/api".length());
String rawQuery = request.getQueryString();
return ResponseEntity return prestashopClient.deleteWithRawQuery(path, rawQuery);
.status(prestaResponse.getStatusCode())
.contentType(MediaType.APPLICATION_XML)
.body(prestaResponse.getBody());
} }
// ---------- UPLOAD IMAGE PRODUIT /api/ps/images/products/{productId} ----------
/**
* Upload d'une image produit :
* Front → (multipart/form-data) → /api/ps/images/products/{productId}
* Backend → (bytes) → https://shop.gameovergne.fr/api/images/products/{productId}
*/
@PostMapping( @PostMapping(
path = "/api/ps/images/products/{productId}", path = "/ps/images/products/{productId}",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
produces = MediaType.APPLICATION_XML_VALUE produces = MediaType.APPLICATION_XML_VALUE
) )
public ResponseEntity<String> uploadProductImage( public ResponseEntity<String> uploadProductImage(HttpServletRequest request,
jakarta.servlet.http.HttpServletRequest request, @PathVariable("productId") String productId,
@PathVariable("productId") String productId, @RequestPart("image") MultipartFile imageFile) {
@RequestPart("image") MultipartFile imageFile
) {
String rawQuery = request.getQueryString(); // si jamais tu ajoutes des options côté Presta
String rawQuery = request.getQueryString(); // si un jour tu veux passer des options
log.info("[Proxy] Upload image produit {} (size={} bytes, ct={})", log.info("[Proxy] Upload image produit {} (size={} bytes, ct={})",
productId, imageFile.getSize(), imageFile.getContentType()); productId, imageFile.getSize(), imageFile.getContentType());