14 KiB
Goong APIs In Use
Mục tiêu của tài liệu này:
- mô tả chính xác frontend hiện tại đang dùng gì từ Goong
- mô tả backend cần proxy gì để giấu
api_key - mô tả response nào phải sanitize/rewrite
- tránh liệt kê thừa các API Goong mà app hiện tại không đụng tới
Phạm vi kiểm tra:
- config.ts
- tiles.ts
- useMapLayers.ts
- style JSON đã tải về:
1. Tóm tắt kỹ thuật
Frontend hiện tại không map.setStyle(goongStyleJson) trực tiếp.
Thay vào đó:
- app tự
fetch()2 style JSON của Goong qua backend proxy - app parse style JSON để lấy:
raster sourcetừgoong_satellite.jsonsources + layerscần thiết từgoong_map_web.json
- nếu source dùng
url, app tiếp tục fetch source manifest qua proxy trongtiles.ts - app rewrite
tiles[]về backend proxy rồimap.addSource(...)vàmap.addLayer(...)thủ công - từ thời điểm đó, MapLibre tự request tiếp tile/font URLs đã là URL proxy
Hệ quả:
- nếu BE chỉ proxy
assets/*.jsonthì chưa đủ - proxy phải cover style JSON, source manifest, tile URLs và glyph PBF
- frontend hiện không nhúng
api_keytrong URL; backend proxy chịu trách nhiệm gọi upstream bằng key server-side nếu upstream yêu cầu
2. Luồng request thật hiện tại
2.1. App fetch style JSON qua proxy
Frontend gọi:
${API_BASE_URL}/proxy/tiles.goong.io/assets/goong_satellite.json${API_BASE_URL}/proxy/tiles.goong.io/assets/goong_map_web.json
Upstream gốc trong code vẫn là:
https://tiles.goong.io/assets/goong_satellite.jsonhttps://tiles.goong.io/assets/goong_map_web.json
Nguồn trong code:
GOONG_SATELLITE_STYLE_UPSTREAM_URLở config.tsGOONG_VECTOR_OVERLAY_STYLE_UPSTREAM_URLở config.tsbuildGoongProxyUrl(...)ở config.tsloadGoongStyleDocument(...)ở tiles.ts
Mục đích:
goong_satellite.json- app lấy ra raster source đầu tiên
- dùng làm nền satellite
goong_map_web.json- app lấy ra các layer/source phục vụ:
Country BordersProvince BordersDistrict BordersCountry LabelsRivers
- app lấy ra các layer/source phục vụ:
2.2. Frontend fetch source manifests qua proxy
Khi style source có field url, tiles.ts tự fetch source manifest qua proxy trước khi gọi map.addSource(...).
Các source URL đang xuất hiện trong style JSON:
Trong goong_satellite.json
https://tiles.goong.io/sources/satellite.json?api_key=...https://tiles.goong.io/sources/base.json?api_key=...https://tiles.goong.io/sources/goong.json?api_key=...
Trong goong_map_web.json
https://tiles.goong.io/sources/base.json?api_key=...https://tiles.goong.io/sources/goong.json?api_key=...
Ý nghĩa:
sources/satellite.json- raster source manifest cho nền satellite
sources/base.json- vector source manifest cho các lớp
boundary,worldcountriespoints,worldnationalcapitals
- vector source manifest cho các lớp
sources/goong.json- vector source manifest cho các lớp
riversandlakes,vietnam_administrator
- vector source manifest cho các lớp
2.3. MapLibre fetch tile URLs đã rewrite
Đây là phần dễ bị bỏ sót nhất.
Khi tiles.ts đã tải sources/satellite.json, sources/base.json, sources/goong.json, nó rewrite mọi URL trong field:
tiles[]
về ${API_BASE_URL}/proxy/tiles.goong.io/..., rồi mới đưa source spec cho MapLibre.
Tức là runtime thật của frontend hiện tại là:
- FE fetch style JSON qua proxy
- FE fetch source manifest qua proxy
- FE rewrite
tiles[]về proxy - MapLibre fetch tile URL đã rewrite
Nếu backend muốn che key hoàn toàn, thì backend proxy phải xử lý cả các tile URL này bằng key server-side.
3. Những upstream Goong resource đang dùng thật
Tính theo runtime hiện tại, upstream Goong đang được dùng thật là:
3.1. Style JSON
assets/goong_satellite.jsonassets/goong_map_web.json
3.2. Source manifests
sources/satellite.jsonsources/base.jsonsources/goong.json
3.3. Tile endpoints bên trong source manifests
- raster tile URLs nằm trong
sources/satellite.json - vector tile URLs nằm trong
sources/base.json - vector tile URLs nằm trong
sources/goong.json
Lưu ý:
- tile URL pattern chính xác phải đọc từ source manifest upstream ở runtime
- backend không nên hardcode khi chưa xác minh nội dung
tiles[] - frontend hiện giữ nguyên upstream target path trong proxy URL sau khi strip
api_key
4. Những thứ frontend hiện tại dùng thêm hoặc KHÔNG dùng
4.1. Goong glyphs / fonts
Style JSON của Goong có field:
glyphs: https://tiles.goong.io/fonts/{fontstack}/{range}.pbf?api_key=...
Flow hiện tại có dùng glyphs của Goong qua proxy.
Map đang trỏ glyphs vào:
${API_BASE_URL}/proxy/tiles.goong.io/fonts/{fontstack}/{range}.pbf
Nguồn trong code:
Kết luận:
- backend proxy Goong fonts/glyphs là bắt buộc cho flow hiện tại
4.2. Goong sprite
Style JSON của Goong có:
sprite: https://tiles.goong.io/sprite
Nhưng flow hiện tại không phụ thuộc sprite vì:
- app không nạp toàn bộ Goong style vào map
- app chỉ nhặt
sourcesvàlayers - khi clone overlay labels, code còn chủ động loại bớt icon fields
Nguồn trong code:
cloneOverlayLayer(...)ở tiles.ts
Kết luận:
- không cần backend proxy Goong sprite cho flow hiện tại
4.3. Các REST API khác của Goong
Preview search hiện có dùng trực tiếp các REST API này từ browser:
Place/AutoCompletePlace/DetailGeocodereverse geocoding vớilatlng=lat,lng
Nguồn trong code:
Chưa dùng:
- directions
- distance matrix
- static map
5. Backend cần làm gì
5.1. Mục tiêu backend
Backend phải đảm bảo:
- browser không gọi Goong trực tiếp
- browser không nhìn thấy
api_key - frontend vẫn nhận được dữ liệu theo format mà MapLibre/app hiện tại cần
5.2. Hai kiểu triển khai
Có 2 cách:
Cách A: Transparent proxy
BE trả về gần như đúng response của Goong, nhưng strip/sanitize mọi api_key lồng trong JSON.
Frontend hiện tự wrap các upstream URL đó bằng buildGoongProxyUrl(...).
Ưu điểm:
- gần với Goong
- ít phải đổi frontend hơn
Nhược điểm:
- BE phải sanitize JSON response để không lộ key trong body response
Cách B: Normalize thành API nội bộ
BE không trả nguyên style/source của Goong mà trả dữ liệu đã xử lý sẵn cho FE.
Ưu điểm:
- hợp đồng BE-FE rõ hơn
- ít phụ thuộc format Goong hơn
Nhược điểm:
- cần sửa frontend nhiều hơn
Với frontend hiện tại, Cách A là hợp lý nhất.
Lưu ý quan trọng: frontend hiện mong nhận sources.*.url và tiles[] ở dạng upstream URL hoặc relative URL. Không rewrite các URL này thành /proxy/... trong JSON response hiện tại, vì FE sẽ tự gọi buildGoongProxyUrl(...); rewrite sẵn sẽ dễ bị double-proxy.
6. Contract backend được khuyến nghị
6.1. Proxy style JSON
GET /proxy/tiles.goong.io/assets/goong_satellite.json
Upstream:
https://tiles.goong.io/assets/goong_satellite.json?api_key=<server-side-key>
Backend phải:
- fetch upstream bằng key server-side
- parse JSON
- strip
api_keykhỏisources.*.url,glyphs,spritenếu các field đó xuất hiện trong body - giữ URL upstream/relative để frontend tự wrap bằng
buildGoongProxyUrl(...) - có thể giữ nguyên các field khác
Response:
Content-Type: application/json- body: style JSON đã sanitize, chưa rewrite sang
/proxy/...
GET /proxy/tiles.goong.io/assets/goong_map_web.json
Upstream:
https://tiles.goong.io/assets/goong_map_web.json?api_key=<server-side-key>
Backend phải:
- fetch upstream bằng key server-side
- parse JSON
- strip
api_keykhỏisources.*.url,glyphs,spritenếu các field đó xuất hiện trong body - giữ URL upstream/relative để frontend tự wrap bằng
buildGoongProxyUrl(...) - có thể giữ nguyên các field khác
Response:
Content-Type: application/json- body: style JSON đã sanitize, chưa rewrite sang
/proxy/...
6.2. Proxy source manifests
GET /proxy/tiles.goong.io/sources/satellite.json
Upstream:
https://tiles.goong.io/sources/satellite.json?api_key=<server-side-key>
Backend phải:
- fetch upstream
- parse JSON
- strip
api_keykhỏi mọi URL trongtiles[] - giữ URL upstream/relative để frontend tự wrap bằng
buildGoongProxyUrl(...) - giữ nguyên metadata quan trọng:
tileSizeminzoommaxzoomboundsschemeattribution
Response:
Content-Type: application/json- body: source manifest đã sanitize, chưa rewrite sang
/proxy/...
GET /proxy/tiles.goong.io/sources/base.json
Upstream:
https://tiles.goong.io/sources/base.json?api_key=<server-side-key>
Backend phải:
- fetch upstream
- parse JSON
- strip
api_keykhỏi mọi URL trongtiles[] - giữ URL upstream/relative để frontend tự wrap bằng
buildGoongProxyUrl(...) - giữ nguyên metadata tilejson khác
GET /proxy/tiles.goong.io/sources/goong.json
Upstream:
https://tiles.goong.io/sources/goong.json?api_key=<server-side-key>
Backend phải:
- fetch upstream
- parse JSON
- strip
api_keykhỏi mọi URL trongtiles[] - giữ URL upstream/relative để frontend tự wrap bằng
buildGoongProxyUrl(...) - giữ nguyên metadata tilejson khác
6.3. Proxy tile endpoints
Backend bắt buộc phải có route để trả tile thật.
Frontend hiện build URL proxy generic theo upstream target:
GET /proxy/tiles.goong.io/...
Yêu cầu:
- request browser -> backend
- backend -> upstream Goong bằng key server-side
- stream response về browser
- pass through hoặc preserve:
Content-TypeCache-ControlETagLast-Modified
Response type có thể là:
- raster image
- vector tile protobuf
7. Runtime dependency map cho BE
7.1. Satellite background
Luồng:
- FE đọc
goong_satellite.json - FE lấy
sources.satellite - FE gọi
sources/satellite.jsonqua proxy trongtiles.ts - FE rewrite
tiles[]về proxy URL - MapLibre gọi raster tile URLs đã rewrite
BE cần cover:
- style JSON
- source manifest
- raster tile URLs
7.2. Overlay borders / labels / rivers
Luồng:
- FE đọc
goong_map_web.json - FE lấy selected layers + selected sources
- FE gọi
sources/base.jsonqua proxy trongtiles.ts - FE gọi
sources/goong.jsonqua proxy trongtiles.ts - FE rewrite
tiles[]về proxy URL - MapLibre gọi vector tile URLs đã rewrite
BE cần cover:
- style JSON
- 2 source manifests
- vector tile URLs tương ứng
8. Danh sách tối thiểu BE phải cover
Nếu chỉ làm đúng những gì frontend hiện tại dùng, checklist tối thiểu là:
- proxy
tiles.goong.io/assets/goong_satellite.json - proxy
tiles.goong.io/assets/goong_map_web.json - proxy
tiles.goong.io/sources/satellite.json - proxy
tiles.goong.io/sources/base.json - proxy
tiles.goong.io/sources/goong.json - proxy
tiles.goong.io/fonts/{fontstack}/{range}.pbf - proxy toàn bộ tile URL được khai báo trong
sources/satellite.json - proxy toàn bộ tile URL được khai báo trong
sources/base.json - proxy toàn bộ tile URL được khai báo trong
sources/goong.json
9. Những gì BE chưa cần làm ngay
Cho flow hiện tại, BE chưa cần:
- proxy Goong
sprite - proxy geocoding / directions / autocomplete
Điều này chỉ đúng khi frontend vẫn giữ kiến trúc hiện tại.
Nếu sau này frontend chuyển sang map.setStyle(goongStyleJson) trực tiếp, hãy đánh giá lại:
glyphssprite
vì khi đó chúng có thể trở thành dependency bắt buộc.
10. Gợi ý ngắn cho team BE
Nếu muốn làm ít rủi ro nhất:
- làm proxy
assets/*.json - sanitize nested
api_keytrong style JSON - làm proxy
sources/*.json - sanitize nested
api_keytrong source manifests - làm proxy generic cho tile
- làm proxy Goong fonts/glyphs
Nếu sanitize JSON thiếu thì key có thể lộ ngay trong response style/source. Nếu proxy tile/font thiếu thì map background hoặc labels có thể không tải được.