diff --git a/coupon/app.js b/coupon/app.js index d7475c9..d6e3c8f 100644 --- a/coupon/app.js +++ b/coupon/app.js @@ -18,6 +18,17 @@ assert.equal( )}` ); +function buildServiceUrl(endpoint, path) { + const base = + endpoint.startsWith("http://") || endpoint.startsWith("https://") + ? endpoint + : `http://${endpoint}`; + if (!path) { + return base; + } + return `${base}${path.startsWith("/") ? path : `/${path}`}`; +} + function getRandomNumber(min, max) { return Math.floor(Math.random() * (max - min) + min); } @@ -43,7 +54,7 @@ app.get("/coupons", (req, res) => { // Fetch from membership api axios - .get(`http://${MEMBERSHIP_SERVICE_HOST}/isMember`) + .get(buildServiceUrl(MEMBERSHIP_SERVICE_HOST, "/isMember")) .then(function (response) { console.log("Got response from membership service!", response.data); res.json({ @@ -73,7 +84,7 @@ app.post("/apply-coupon", (req, res) => { // Fetch from membership api axios - .get(`http://${MEMBERSHIP_SERVICE_HOST}/isMember`) + .get(buildServiceUrl(MEMBERSHIP_SERVICE_HOST, "/isMember")) .then(function (response) { console.log("Got response from membership service!", response.data); res.json({ diff --git a/currency/index.php b/currency/index.php index e333f21..9a96e17 100644 --- a/currency/index.php +++ b/currency/index.php @@ -13,6 +13,13 @@ require __DIR__ . '/vendor/autoload.php'; require('dice.php'); +function buildServiceBaseUrl(string $endpoint): string { + if (!str_starts_with($endpoint, 'http://') && !str_starts_with($endpoint, 'https://')) { + return "http://$endpoint"; + } + return $endpoint; +} + $logger = new Logger('currency-server'); $logger->pushHandler(new StreamHandler('php://stdout', Level::Info)); @@ -52,7 +59,7 @@ } $geoServiceHost = getenv('GEOLOCATION_SERVICE_HOST'); - $client = new Client(['base_uri' => "http://$geoServiceHost"]); + $client = new Client(['base_uri' => buildServiceBaseUrl($geoServiceHost)]); try { $res1 = $client->request('GET', "/location/$currency1", ['headers' => ['Accept' => 'application/json']]); diff --git a/frontend/src/main/java/dev/keyval/kvshop/frontend/CouponService.java b/frontend/src/main/java/dev/keyval/kvshop/frontend/CouponService.java index cc69900..1327385 100644 --- a/frontend/src/main/java/dev/keyval/kvshop/frontend/CouponService.java +++ b/frontend/src/main/java/dev/keyval/kvshop/frontend/CouponService.java @@ -20,7 +20,7 @@ public CouponService(@Value("${COUPON_SERVICE_HOST}") String couponServiceHost) public CouponResult getCoupons() { // Make http request to coupon service RestTemplate restTemplate = new RestTemplate(); - CouponResult res = restTemplate.getForObject("http://" + couponServiceHost + "/coupons", CouponResult.class); + CouponResult res = restTemplate.getForObject(ServiceUrl.build(couponServiceHost, "/coupons"), CouponResult.class); log.info("Fetched coupons from coupon service, got result: {}", res.getCoupon()); return res; } @@ -28,7 +28,7 @@ public CouponResult getCoupons() { public CouponResult applyCoupon() { // Make http request to coupon service RestTemplate restTemplate = new RestTemplate(); - CouponResult res = restTemplate.postForObject("http://" + couponServiceHost + "/apply-coupon", null, CouponResult.class); + CouponResult res = restTemplate.postForObject(ServiceUrl.build(couponServiceHost, "/apply-coupon"), null, CouponResult.class); log.info("Applied coupon to coupon service, got result: {}", res.getCoupon()); return res; } diff --git a/frontend/src/main/java/dev/keyval/kvshop/frontend/CurrencyService.java b/frontend/src/main/java/dev/keyval/kvshop/frontend/CurrencyService.java index 461d456..c220387 100644 --- a/frontend/src/main/java/dev/keyval/kvshop/frontend/CurrencyService.java +++ b/frontend/src/main/java/dev/keyval/kvshop/frontend/CurrencyService.java @@ -16,7 +16,7 @@ public CurrencyService(@Value("${CURRENCY_SERVICE_HOST}") String currencyService } public CurrencyResult getCurrencyInfo(String currencyPair) { - String url = "http://" + currencyServiceHost + "/rate/" + currencyPair; + String url = ServiceUrl.build(currencyServiceHost, "/rate/" + currencyPair); CurrencyResult res = new RestTemplate().getForObject(url, CurrencyResult.class); log.info("Successfully fetched from Currency service, got result: {}", res.toString()); diff --git a/frontend/src/main/java/dev/keyval/kvshop/frontend/GeoService.java b/frontend/src/main/java/dev/keyval/kvshop/frontend/GeoService.java index a5f5b70..cddd38b 100644 --- a/frontend/src/main/java/dev/keyval/kvshop/frontend/GeoService.java +++ b/frontend/src/main/java/dev/keyval/kvshop/frontend/GeoService.java @@ -16,7 +16,7 @@ public GeoService(@Value("${GEOLOCATION_SERVICE_HOST}") String geoServiceHost) { } public GeoResult getLocationInfo(String loc) { - String url = "http://" + geoServiceHost + "/location/" + loc; + String url = ServiceUrl.build(geoServiceHost, "/location/" + loc); GeoResult res = new RestTemplate().getForObject(url, GeoResult.class); log.info("Successfully fetched from Geolocation service, got result: {}", res.toString()); diff --git a/frontend/src/main/java/dev/keyval/kvshop/frontend/InventoryService.java b/frontend/src/main/java/dev/keyval/kvshop/frontend/InventoryService.java index 062bea2..b9f5b2c 100644 --- a/frontend/src/main/java/dev/keyval/kvshop/frontend/InventoryService.java +++ b/frontend/src/main/java/dev/keyval/kvshop/frontend/InventoryService.java @@ -19,7 +19,7 @@ public InventoryService(@Value("${INVENTORY_SERVICE_HOST}") String inventoryServ public List getInventory() { // Make http request to product service RestTemplate restTemplate = new RestTemplate(); - Product[] result = restTemplate.getForObject("http://" + inventoryServiceHost + "/inventory", Product[].class); + Product[] result = restTemplate.getForObject(ServiceUrl.build(inventoryServiceHost, "/inventory"), Product[].class); // Convert result to list of products return Arrays.asList(result); @@ -28,6 +28,6 @@ public List getInventory() { public void buy(int id) { // Make http request to product service RestTemplate restTemplate = new RestTemplate(); - restTemplate.postForObject("http://" + inventoryServiceHost + "/buy?id=" + id, null, Void.class); + restTemplate.postForObject(ServiceUrl.build(inventoryServiceHost, "/buy?id=" + id), null, Void.class); } } diff --git a/frontend/src/main/java/dev/keyval/kvshop/frontend/PricingService.java b/frontend/src/main/java/dev/keyval/kvshop/frontend/PricingService.java index d61cfb6..dcc1c63 100644 --- a/frontend/src/main/java/dev/keyval/kvshop/frontend/PricingService.java +++ b/frontend/src/main/java/dev/keyval/kvshop/frontend/PricingService.java @@ -18,7 +18,7 @@ public PricingService(@Value("${PRICING_SERVICE_HOST}") String pricingServiceHos public double getPrice(int id) { // Make http request to pricing service RestTemplate restTemplate = new RestTemplate(); - PriceResult priceResult = restTemplate.getForObject("http://" + pricingServiceHost + "/price?id=" + id, PriceResult.class); + PriceResult priceResult = restTemplate.getForObject(ServiceUrl.build(pricingServiceHost, "/price?id=" + id), PriceResult.class); return priceResult.getPrice(); } } diff --git a/frontend/src/main/java/dev/keyval/kvshop/frontend/ServiceUrl.java b/frontend/src/main/java/dev/keyval/kvshop/frontend/ServiceUrl.java new file mode 100644 index 0000000..83232a0 --- /dev/null +++ b/frontend/src/main/java/dev/keyval/kvshop/frontend/ServiceUrl.java @@ -0,0 +1,21 @@ +package dev.keyval.kvshop.frontend; + +public final class ServiceUrl { + + private ServiceUrl() { + } + + public static String build(String endpoint, String path) { + String base = endpoint; + if (!base.startsWith("http://") && !base.startsWith("https://")) { + base = "http://" + base; + } + if (path == null || path.isEmpty()) { + return base; + } + if (!path.startsWith("/")) { + path = "/" + path; + } + return base + path; + } +} diff --git a/frontend/src/main/java/dev/keyval/kvshop/frontend/ShippingService.java b/frontend/src/main/java/dev/keyval/kvshop/frontend/ShippingService.java index 9f75d7d..dbf566d 100644 --- a/frontend/src/main/java/dev/keyval/kvshop/frontend/ShippingService.java +++ b/frontend/src/main/java/dev/keyval/kvshop/frontend/ShippingService.java @@ -16,7 +16,7 @@ public ShippingService(@Value("${SHIPPING_SERVICE_HOST}") String shippingService } public ShippingQuoteResult getQuote(int productId) { - String url = "http://" + shippingServiceHost + "/quote?id=" + productId; + String url = ServiceUrl.build(shippingServiceHost, "/quote?id=" + productId); ShippingQuoteResult res = new RestTemplate().getForObject(url, ShippingQuoteResult.class); log.info("Shipping quote for product {}: {} cents ({})", productId, res != null ? res.getShippingCents() : -1, diff --git a/load-generator/src/main.rs b/load-generator/src/main.rs index 48df3ff..d1b5557 100644 --- a/load-generator/src/main.rs +++ b/load-generator/src/main.rs @@ -3,6 +3,22 @@ use std::process; use tokio::time::{sleep, Duration}; use rand::Rng; +fn build_service_url(endpoint: &str, path: &str) -> String { + let base = if endpoint.starts_with("http://") || endpoint.starts_with("https://") { + endpoint.to_string() + } else { + format!("http://{}", endpoint) + }; + if path.is_empty() { + return base; + } + if path.starts_with('/') { + format!("{}{}", base, path) + } else { + format!("{}/{}", base, path) + } +} + #[tokio::main] async fn main() -> Result<(), Box> { let client = reqwest::Client::new(); @@ -29,7 +45,7 @@ async fn main() -> Result<(), Box> { // Make POST request to the specified endpoint let response = client - .post(format!("http://{}/buy?id={}", frontend_service_host, random_id)) + .post(build_service_url(&frontend_service_host, &format!("/buy?id={}", random_id))) .send() .await?; diff --git a/membership/main.go b/membership/main.go index cb3270a..da07c1b 100644 --- a/membership/main.go +++ b/membership/main.go @@ -3,11 +3,11 @@ package main import ( "context" "encoding/json" - "fmt" "log/slog" "net/http" "os" "strconv" + "strings" "github.com/google/uuid" "go.opentelemetry.io/otel" @@ -58,6 +58,17 @@ func checkIfMember(ctx context.Context, userId uuid.UUID) bool { return isMember } +func buildServiceURL(endpoint, path string) string { + base := endpoint + if !strings.HasPrefix(base, "http://") && !strings.HasPrefix(base, "https://") { + base = "http://" + base + } + if path != "" && !strings.HasPrefix(path, "/") { + path = "/" + path + } + return base + path +} + func main() { port := getPortFromEnvOrDefault() slog.Info("Starting Membership service", "port", port) @@ -83,7 +94,7 @@ func main() { return } - req, err := http.NewRequestWithContext(request.Context(), "GET", (fmt.Sprintf("http://%s/price?id=0", os.Getenv(pricingEndpointEnvName))), nil) + req, err := http.NewRequestWithContext(request.Context(), "GET", buildServiceURL(os.Getenv(pricingEndpointEnvName), "/price?id=0"), nil) if err != nil { slog.Error("failed to create request to pricing service", "error", err) writer.WriteHeader(http.StatusInternalServerError)