Skip to content

feat: implement HeritageImageController with proxyImage#477

Closed
zigzagdev wants to merge 6 commits into
chore/create-proxy-apifrom
feat/create-heritage-image-controller
Closed

feat: implement HeritageImageController with proxyImage#477
zigzagdev wants to merge 6 commits into
chore/create-proxy-apifrom
feat/create-heritage-image-controller

Conversation

@zigzagdev
Copy link
Copy Markdown
Owner

Summary

  • Add app/Packages/Features/Controller/HeritageImageController.php
  • proxyImage fetches the image URL from world_heritage_site_images via the Image Eloquent model, then streams the binary back to the browser
  • Returns 404 when no record exists for the given id
  • Returns 502 when the upstream UNESCO request fails
  • Sets Access-Control-Allow-Origin: * so the frontend can load images cross-origin

No Domain layer needed

This is a pure infrastructure pass-through (DB lookup → HTTP fetch → stream response). There is no business logic, so no UseCase or Domain Entity is involved.

Verified

php artisan route:list inside Docker confirms GET /api/v1/heritage-image/{id} resolves to HeritageImageController@proxyImage.

Closes

#471

Part of

#475

Fetches the UNESCO image URL from world_heritage_site_images via the
Image model and streams the binary response back to the browser,
bypassing CORS/CORP restrictions that block direct browser requests.

Closes #471

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
zigzagdev and others added 5 commits May 26, 2026 07:54
Access-Control-Allow-Origin is already managed by HandleCors middleware
via cors.php. Keeping it in the controller caused duplicate headers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
WorldHeritageVm.id is the site ID, not the image record's PK.
Querying by world_heritage_site_id with is_primary/sort_order ordering
returns the primary image for the site, which is what the frontend passes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GET /api/v1/heritage-image/image/{imageId} fetches a single image by
its own PK, allowing the detail page to proxy each image in the
images[] array independently.

- /heritage-image/{siteId}        → primary image (list page)
- /heritage-image/image/{imageId} → individual image by PK (detail page)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of proxying UNESCO /document/ URLs (blocked by Cloudflare as
subresource requests), fetch main_video_url from data.unesco.org API
on each request, extract the YouTube video ID, and return the YouTube
hqdefault thumbnail binary.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Migration: add main_video_url column to world_heritage_sites
- Command: world-heritage:sync-video-urls fetches main_video_url from
  data.unesco.org API and populates DB (1248 records synced)
- Model: add main_video_url to WorldHeritage fillable
- Controller: look up main_video_url from DB instead of calling UNESCO
  API on every request, then proxy YouTube hqdefault thumbnail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@zigzagdev
Copy link
Copy Markdown
Owner Author

Closing: proxy approach not viable due to Cloudflare blocking server-side requests to UNESCO CDN.

@zigzagdev zigzagdev closed this May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant