diff --git a/api/pom.xml b/api/pom.xml
index bb77c35..1377aa6 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -100,15 +100,6 @@
spring-boot-starter-test
test
-
- org.springframework.boot
- spring-boot-starter-webflux
-
-
- io.projectreactor
- reactor-test
- test
-
diff --git a/api/src/main/java/fr/gameovergne/api/config/AppConfig.java b/api/src/main/java/fr/gameovergne/api/config/AppConfig.java
deleted file mode 100644
index 7702bdb..0000000
--- a/api/src/main/java/fr/gameovergne/api/config/AppConfig.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package fr.gameovergne.api.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.reactive.function.client.WebClient;
-
-@Configuration
-public class AppConfig {
-
- @Bean
- public WebClient prestashopWebClient(WebClient.Builder builder) {
- return builder.build();
- }
-}
\ No newline at end of file
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 d0fa1ee..a6dfcd0 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,69 +1,32 @@
package fr.gameovergne.api.controller.prestashop;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
+import fr.gameovergne.api.service.prestashop.PrestashopClient;
+import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
-import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
-import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.web.util.UriComponentsBuilder;
-import reactor.core.publisher.Mono;
+
@RestController
@RequestMapping("/api/ps")
public class PrestashopProxyController {
- private final WebClient webClient;
+ private final PrestashopClient prestashopClient;
- @Value("${prestashop.api.base-url}")
- private String prestaBaseUrl;
-
- @Value("${prestashop.api.key}")
- private String prestaApiKey; // ta clé déjà encodée en Base64
-
- public PrestashopProxyController(WebClient prestashopWebClient) {
- this.webClient = prestashopWebClient;
+ public PrestashopProxyController(PrestashopClient prestashopClient) {
+ this.prestashopClient = prestashopClient;
}
- // ----------- SUPPLIERS -----------
- @GetMapping("/suppliers")
- public ResponseEntity getSuppliers(@RequestParam MultiValueMap params) {
- return forwardGet("/suppliers", params);
- }
+ @GetMapping("/**")
+ public ResponseEntity proxyGet(HttpServletRequest request) {
+ String fullPath = request.getRequestURI(); // ex: /api/ps/suppliers
+ String contextPath = request.getContextPath(); // souvent ""
+ String relative = fullPath.substring(contextPath.length()); // /api/ps/suppliers
- // ----------- CATEGORIES -----------
- @GetMapping("/categories")
- public ResponseEntity getCategories(@RequestParam MultiValueMap params) {
- return forwardGet("/categories", params);
- }
+ // On enlève le préfixe /api/ps -> /suppliers
+ String path = relative.replaceFirst("^/api/ps", "");
- // ----------- MANUFACTURERS -----------
- @GetMapping("/manufacturers")
- public ResponseEntity getManufacturers(@RequestParam MultiValueMap params) {
- return forwardGet("/manufacturers", params);
- }
+ String query = request.getQueryString(); // ex: display=%5Bid,name,active%5D&output_format=JSON
- // ----------- Méthode commune de forward -----------
-
- private ResponseEntity forwardGet(String resourcePath, MultiValueMap params) {
- // IMPORTANT : build(false) => ne PAS ré-encoder les crochets
- UriComponentsBuilder builder = UriComponentsBuilder
- .fromHttpUrl(prestaBaseUrl + resourcePath);
-
- params.forEach((key, values) -> values.forEach(v -> builder.queryParam(key, v)));
-
- String targetUrl = builder.build(false).toUriString(); // false => pas de double encodage
-
- Mono> monoResponse = webClient
- .get()
- .uri(targetUrl)
- .header(HttpHeaders.AUTHORIZATION, "Basic " + prestaApiKey)
- .accept(MediaType.APPLICATION_JSON)
- .retrieve()
- .toEntity(String.class);
-
- // On bloque car ton contrôleur est synchrone (MVC)
- return monoResponse.block();
+ return prestashopClient.get(path, query);
}
}
\ 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 c6c7ae5..8e9645d 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
@@ -1,72 +1,94 @@
-// FILE: api/src/main/java/fr/gameovergne/api/service/prestashop/PrestashopClient.java
package fr.gameovergne.api.service.prestashop;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.*;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.HttpStatusCodeException;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.web.util.UriComponentsBuilder;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
-@Component
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.util.List;
+import java.util.Map;
+
+@Service
public class PrestashopClient {
- private static final Logger log = LoggerFactory.getLogger(PrestashopClient.class);
+ private final HttpClient httpClient = HttpClient.newHttpClient();
- private final RestTemplate restTemplate = new RestTemplate();
+ private final String baseUrl;
+ private final String basicAuth; // valeur déjà encodée Base64 (sans le "Basic ")
- @Value("${prestashop.base-url}")
- private String baseUrl;
-
- @Value("${prestashop.basic-auth}")
- private String basicAuth;
+ public PrestashopClient(
+ @Value("${prestashop.base-url}") String baseUrl,
+ @Value("${prestashop.basic-auth}") String basicAuth
+ ) {
+ this.baseUrl = baseUrl;
+ this.basicAuth = basicAuth;
+ }
public ResponseEntity get(String path, String query) {
+ // path : ex "/suppliers"
+ // query : ex "display=%5Bid,name,active%5D&output_format=JSON"
+ String url = buildUrl(path, query);
+
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .header("Authorization", "Basic " + basicAuth)
+ .GET()
+ .build();
+
try {
- String url = baseUrl + "/api" + path;
+ HttpResponse response =
+ httpClient.send(request, HttpResponse.BodyHandlers.ofString());
- UriComponentsBuilder builder = UriComponentsBuilder
- .fromHttpUrl(url);
-
- if (query != null && !query.isBlank()) {
- // on réinjecte TELS QUELS les query params venant du front
- builder.query(query);
+ // On reconstruit une ResponseEntity en gardant le status PrestaShop
+ HttpHeaders springHeaders = new HttpHeaders();
+ for (Map.Entry> entry : response.headers().map().entrySet()) {
+ springHeaders.put(entry.getKey(), entry.getValue());
}
- String finalUrl = builder.build(true).toUriString();
+ return new ResponseEntity<>(response.body(), springHeaders,
+ HttpStatus.valueOf(response.statusCode()));
- HttpHeaders headers = new HttpHeaders();
- headers.set("Authorization", basicAuth);
- headers.setAccept(MediaType.parseMediaTypes("application/json"));
-
- HttpEntity entity = new HttpEntity<>(headers);
-
- log.debug("[Presta] GET {}", finalUrl);
-
- ResponseEntity response = restTemplate.exchange(
- finalUrl,
- HttpMethod.GET,
- entity,
- String.class
- );
-
- log.debug("[Presta] status={} body={}", response.getStatusCode(), response.getBody());
- return ResponseEntity.status(response.getStatusCode()).body(response.getBody());
-
- } catch (HttpStatusCodeException e) {
- // <-- ICI on garde le vrai status + body de Prestashop
- log.error("[Presta] HTTP error {} body={}", e.getStatusCode(), e.getResponseBodyAsString());
- return ResponseEntity
- .status(e.getStatusCode())
- .body(e.getResponseBodyAsString());
- } catch (Exception e) {
- log.error("[Presta] Unexpected error while calling Presta", e);
- return ResponseEntity
- .status(HttpStatus.INTERNAL_SERVER_ERROR)
- .body("{\"error\":\"Unexpected error while calling Prestashop\"}");
+ } catch (IOException | InterruptedException e) {
+ // En prod tu pourrais logger proprement
+ if (e instanceof InterruptedException) {
+ Thread.currentThread().interrupt();
+ }
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+ .body("{\"error\":\"Failed to call PrestaShop Webservice\"}");
}
}
+
+ private String buildUrl(String path, String query) {
+ StringBuilder sb = new StringBuilder();
+
+ // baseUrl, ex: https://shop.gameovergne.fr
+ sb.append(baseUrl);
+ if (baseUrl.endsWith("/")) {
+ sb.setLength(sb.length() - 1); // on enlève le / final si présent
+ }
+
+ // /api
+ sb.append("/api");
+
+ // path, ex: "/suppliers"
+ if (path != null && !path.isBlank()) {
+ if (!path.startsWith("/")) {
+ sb.append('/');
+ }
+ sb.append(path);
+ }
+
+ // query déjà encodée par le navigateur : NE PAS la ré-encoder !
+ if (query != null && !query.isBlank()) {
+ sb.append('?').append(query);
+ }
+
+ return sb.toString();
+ }
}
\ No newline at end of file