package com.gcsc.guide.controller; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; 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.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; import java.util.concurrent.TimeUnit; import static org.springframework.http.HttpStatus.NOT_FOUND; @RestController @RequestMapping("/api/wing/data") @RequiredArgsConstructor @Tag(name = "WING ยท Data", description = "WING embedded datasets (JWT required)") public class WingDataController { @GetMapping(value = "/zones", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity zones() { return serveJson("wing-data/zones.wgs84.geojson"); } @GetMapping(value = "/legacy", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity legacyChinesePermitted() { return serveJson("wing-data/chinese-permitted.v1.json"); } @GetMapping(value = "/subcables/geo", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity subcablesGeo() { return serveJson("wing-data/subcables/cable-geo.json"); } @GetMapping(value = "/subcables/details", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity subcablesDetails() { return serveJson("wing-data/subcables/cable-details.min.json"); } private ResponseEntity serveJson(String classpathLocation) { Resource resource = new ClassPathResource(classpathLocation); if (!resource.exists()) { throw new ResponseStatusException(NOT_FOUND, "Resource not found: " + classpathLocation); } return ResponseEntity.ok() // Authenticated endpoint: allow browser caching but keep it private. .cacheControl(CacheControl.maxAge(6, TimeUnit.HOURS).cachePrivate()) .contentType(MediaType.APPLICATION_JSON) .body(resource); } }