From 887ccc01d5529a159e5ad8df11a3750aebeb21af Mon Sep 17 00:00:00 2001 From: Sean Date: Tue, 6 Jan 2026 05:56:19 -0500 Subject: [PATCH] shortlink fixes and app properties --- .../config/ShortLinksProperties.java | 18 ++++++- .../ShortLinkRedirectController.java | 52 +++++++++++++++---- src/main/resources/application-dev.yml | 3 +- src/main/resources/application-prod.yml | 8 +-- 4 files changed, 65 insertions(+), 16 deletions(-) diff --git a/src/main/java/group/goforward/battlbuilder/config/ShortLinksProperties.java b/src/main/java/group/goforward/battlbuilder/config/ShortLinksProperties.java index cebda95..4fcebbd 100644 --- a/src/main/java/group/goforward/battlbuilder/config/ShortLinksProperties.java +++ b/src/main/java/group/goforward/battlbuilder/config/ShortLinksProperties.java @@ -11,13 +11,21 @@ public class ShortLinksProperties { private boolean enabled = true; /** - * The public base URL used when generating links (differs in dev vs prod). + * The public base URL used when generating short links (differs in dev vs prod). * Examples: * - http://localhost:8080 * - https://bb.ooo */ private String publicBaseUrl = "http://localhost:8080"; + /** + * The frontend base URL used when redirecting BUILD short links. + * Examples: + * - http://localhost:3000 + * - https://battlbuilder.com + */ + private String frontendBaseUrl = "http://localhost:3000"; + public boolean isEnabled() { return enabled; } @@ -33,4 +41,12 @@ public class ShortLinksProperties { public void setPublicBaseUrl(String publicBaseUrl) { this.publicBaseUrl = publicBaseUrl; } + + public String getFrontendBaseUrl() { + return frontendBaseUrl; + } + + public void setFrontendBaseUrl(String frontendBaseUrl) { + this.frontendBaseUrl = frontendBaseUrl; + } } \ No newline at end of file diff --git a/src/main/java/group/goforward/battlbuilder/controllers/ShortLinkRedirectController.java b/src/main/java/group/goforward/battlbuilder/controllers/ShortLinkRedirectController.java index 86ea5d6..824a920 100644 --- a/src/main/java/group/goforward/battlbuilder/controllers/ShortLinkRedirectController.java +++ b/src/main/java/group/goforward/battlbuilder/controllers/ShortLinkRedirectController.java @@ -1,6 +1,8 @@ package group.goforward.battlbuilder.controllers; +import group.goforward.battlbuilder.config.ShortLinksProperties; import group.goforward.battlbuilder.repos.ShortLinkRepository; + import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -14,36 +16,64 @@ import java.net.URI; public class ShortLinkRedirectController { private final ShortLinkRepository repo; + private final ShortLinksProperties props; - public ShortLinkRedirectController(ShortLinkRepository repo) { + public ShortLinkRedirectController(ShortLinkRepository repo, ShortLinksProperties props) { this.repo = repo; + this.props = props; } + /** + * Single canonical short-link entry point. + * + * We intentionally keep ONE route (/go/{code}) for all short links + * (BUY affiliate redirects + BUILD share links) to avoid duplicated controllers + * and ambiguous Spring mappings. + * + * BUY -> redirect to destination_url (stored from offer.buy_url / AvantLink) + * BUILD-> redirect to frontendBaseUrl + /builds/{buildUuid} + */ @GetMapping("/go/{code}") public ResponseEntity go(@PathVariable String code) { + + // Lookup only active links; 404 for missing/disabled var link = repo.findByCodeAndIsActiveTrue(code) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); - String dest; + final String dest; + // ---------------------------- + // BUY: redirect to affiliate URL + // ---------------------------- if ("BUY".equalsIgnoreCase(link.getType())) { - dest = link.getDestinationUrl(); - if (dest == null || dest.isBlank()) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND); - } + String url = link.getDestinationUrl(); + if (url == null || url.isBlank()) throw new ResponseStatusException(HttpStatus.NOT_FOUND); + dest = url; + // ---------------------------- + // BUILD: redirect to Next.js build page + // ---------------------------- } else if ("BUILD".equalsIgnoreCase(link.getType())) { - if (link.getBuildUuid() == null) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND); - } + if (link.getBuildUuid() == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND); - // ✅ Adjust to your actual frontend route + base URL if needed (dev vs prod) - dest = "/builds/" + link.getBuildUuid(); + // Use env-specific frontend host (dev vs prod) + String base = props.getFrontendBaseUrl(); + if (base == null || base.isBlank()) throw new ResponseStatusException(HttpStatus.NOT_FOUND); + // Normalize trailing slash so we don't end up with //builds/... + base = base.endsWith("/") ? base.substring(0, base.length() - 1) : base; + + // NOTE: Adjust path if your Next.js route changes + dest = base + "/builds/" + link.getBuildUuid(); + + // ---------------------------- + // Unknown type: treat as missing + // ---------------------------- } else { throw new ResponseStatusException(HttpStatus.NOT_FOUND); } + // 302 (FOUND) redirect return ResponseEntity.status(HttpStatus.FOUND) .location(URI.create(dest)) .build(); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 00ba35b..80f3f6c 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,3 +1,4 @@ shortlinks: enabled: true - publicBaseUrl: "http://localhost:8080" \ No newline at end of file + publicBaseUrl: http://localhost:8080 + frontendBaseUrl: http://localhost:3000 \ No newline at end of file diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 68aff4a..fc11479 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -1,3 +1,5 @@ -shortlinks: - enabled: true - publicBaseUrl: "https://battl.build" \ No newline at end of file + + shortlinks: + enabled: true + publicBaseUrl: https://battl.build + frontendBaseUrl: https://battlbuilders.com \ No newline at end of file