From 0918817f3015001771e05e8b1f0ec6a553b55b20 Mon Sep 17 00:00:00 2001 From: Niall Thomson Date: Mon, 8 Jan 2024 21:54:44 -0700 Subject: [PATCH] Added proxy endpoint to UI service (#439) --- .../sample/orders/web/OrderController.java | 3 +- src/ui/pom.xml | 5 ++ .../ui/services/checkout/CheckoutService.java | 1 - .../amazon/sample/ui/web/BaseController.java | 6 +- .../sample/ui/web/CatalogImageController.java | 17 ++-- .../amazon/sample/ui/web/ProxyController.java | 83 +++++++++++++++++++ 6 files changed, 97 insertions(+), 18 deletions(-) create mode 100644 src/ui/src/main/java/com/amazon/sample/ui/web/ProxyController.java diff --git a/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java b/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java index cedcc1194..f52d3c354 100644 --- a/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java +++ b/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java @@ -18,7 +18,6 @@ package com.amazon.sample.orders.web; -import com.amazon.sample.orders.entities.OrderEntity; import com.amazon.sample.orders.services.OrderService; import com.amazon.sample.orders.web.payload.*; @@ -33,7 +32,7 @@ @RestController @RequestMapping("/orders") -@Tag(name="orders") +@Tag(name = "orders") @Slf4j public class OrderController { diff --git a/src/ui/pom.xml b/src/ui/pom.xml index 250d3d35c..796dd0a18 100644 --- a/src/ui/pom.xml +++ b/src/ui/pom.xml @@ -67,6 +67,11 @@ org.springframework.boot spring-boot-devtools + + org.springframework.cloud + spring-cloud-gateway-webflux + 4.1.1 + org.openapitools jackson-databind-nullable diff --git a/src/ui/src/main/java/com/amazon/sample/ui/services/checkout/CheckoutService.java b/src/ui/src/main/java/com/amazon/sample/ui/services/checkout/CheckoutService.java index 0a1143825..2530d803d 100644 --- a/src/ui/src/main/java/com/amazon/sample/ui/services/checkout/CheckoutService.java +++ b/src/ui/src/main/java/com/amazon/sample/ui/services/checkout/CheckoutService.java @@ -19,7 +19,6 @@ package com.amazon.sample.ui.services.checkout; import com.amazon.sample.ui.services.checkout.model.Checkout; -import com.amazon.sample.ui.services.checkout.model.CheckoutSubmitted; import com.amazon.sample.ui.services.checkout.model.CheckoutSubmittedResponse; import com.amazon.sample.ui.services.checkout.model.ShippingAddress; import reactor.core.publisher.Mono; diff --git a/src/ui/src/main/java/com/amazon/sample/ui/web/BaseController.java b/src/ui/src/main/java/com/amazon/sample/ui/web/BaseController.java index feceeb607..2ffaae6f2 100644 --- a/src/ui/src/main/java/com/amazon/sample/ui/web/BaseController.java +++ b/src/ui/src/main/java/com/amazon/sample/ui/web/BaseController.java @@ -18,7 +18,6 @@ package com.amazon.sample.ui.web; -import com.amazon.sample.ui.clients.carts.api.CartsApi; import com.amazon.sample.ui.services.Metadata; import com.amazon.sample.ui.services.carts.CartsService; import com.amazon.sample.ui.web.util.SessionIDUtil; @@ -26,7 +25,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.ui.Model; -import org.springframework.web.server.ServerWebExchange; import reactor.util.retry.Retry; import reactor.util.retry.RetryBackoffSpec; @@ -49,8 +47,8 @@ public BaseController(CartsService cartsService, Metadata metadata) { protected static RetryBackoffSpec retrySpec(String path) { return Retry - .backoff(3, Duration.ofSeconds(1)) - .doBeforeRetry(context -> log.warn("Retrying {}", path)); + .backoff(3, Duration.ofSeconds(1)) + .doBeforeRetry(context -> log.warn("Retrying {}", path)); } protected void populateCommon(ServerHttpRequest request, Model model) { diff --git a/src/ui/src/main/java/com/amazon/sample/ui/web/CatalogImageController.java b/src/ui/src/main/java/com/amazon/sample/ui/web/CatalogImageController.java index 09303977a..264407994 100644 --- a/src/ui/src/main/java/com/amazon/sample/ui/web/CatalogImageController.java +++ b/src/ui/src/main/java/com/amazon/sample/ui/web/CatalogImageController.java @@ -19,33 +19,28 @@ package com.amazon.sample.ui.web; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.CacheControl; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.reactive.function.client.ExchangeStrategies; -import org.springframework.web.reactive.function.client.WebClient; import com.amazon.sample.ui.services.assets.AssetsService; import reactor.core.publisher.Mono; -import java.util.concurrent.TimeUnit; - /** - * This controller serves product images from the catalog backend, adding cache control headers along the way + * This controller serves product images from the catalog backend, adding cache + * control headers along the way */ @RestController public class CatalogImageController { - private AssetsService assetsService; + private AssetsService assetsService; - public CatalogImageController(@Autowired AssetsService assetsService) { - this.assetsService = assetsService; - } + public CatalogImageController(@Autowired AssetsService assetsService) { + this.assetsService = assetsService; + } @GetMapping(value = "/assets/{image}", produces = MediaType.IMAGE_JPEG_VALUE) public Mono> catalogueImage(@PathVariable String image) { diff --git a/src/ui/src/main/java/com/amazon/sample/ui/web/ProxyController.java b/src/ui/src/main/java/com/amazon/sample/ui/web/ProxyController.java new file mode 100644 index 000000000..f5a4d3955 --- /dev/null +++ b/src/ui/src/main/java/com/amazon/sample/ui/web/ProxyController.java @@ -0,0 +1,83 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: MIT-0 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this + * software and associated documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.amazon.sample.ui.web; + +import reactor.core.publisher.Mono; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.gateway.webflux.ProxyExchange; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/proxy") +public class ProxyController { + + @Value("${endpoints.catalog:}") + private String catalogEndpoint; + + @Value("${endpoints.carts:}") + private String cartsEndpoint; + + @Value("${endpoints.orders:}") + private String ordersEndpoint; + + @Value("${endpoints.checkout:}") + private String checkoutEndpoint; + + @GetMapping("/catalogue/**") + public Mono> catalogProxy(ProxyExchange proxy) throws Exception { + return doProxy(proxy, "catalog", catalogEndpoint); + } + + @GetMapping("/carts/**") + public Mono> cartsProxy(ProxyExchange proxy) throws Exception { + return doProxy(proxy, "carts", cartsEndpoint); + } + + @GetMapping("/checkout/**") + public Mono> checkoutProxy(ProxyExchange proxy) throws Exception { + return doProxy(proxy, "checkout", checkoutEndpoint); + } + + @GetMapping("/orders/**") + public Mono> ordersProxy(ProxyExchange proxy) throws Exception { + return doProxy(proxy, "orders", checkoutEndpoint); + } + + public Mono> doProxy(ProxyExchange proxy, String service, String endpoint) + throws Exception { + System.out.println("Endpoint is " + endpoint); + if (isEmpty(endpoint)) { + return Mono + .just(new ResponseEntity<>(("Endpoint not provided for " + service).getBytes(), + HttpStatus.NOT_FOUND)); + } + + String path = proxy.path("/proxy"); + return proxy.uri(endpoint + path).header("Content-Type", "application/json").forward(); + } + + private boolean isEmpty(String check) { + return check.equals("false"); + } +}