Fix CORS: add proxy support for browser-based API calls on git-pages
Deploy to git-pages / deploy (push) Successful in 20s
Deploy to git-pages / deploy (push) Successful in 20s
- Add VITE_PROXY_URL env var to route requests through a CORS proxy when deployed as static site (CRDC API doesn't send Access-Control-Allow-Origin) - Update useApi.js, LoadingAnimation.jsx, and ChartPanel.jsx to respect proxy - Add nginx.conf with /api/v1/ reverse proxy + CORS headers for Docker deployment - Include proxy.php — simple PHP CORS proxy for git-pages hosts that support PHP - Document CORS workaround in README Without this fix, browser fetch() calls are blocked by same-origin policy and the app shows a blank white screen despite serving correct HTML.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* Simple CORS proxy for CRDC Arrest Rate API.
|
||||
*
|
||||
* Deploy this file to your git-pages host alongside the static site (e.g., at /crdc-demo/proxy.php).
|
||||
* Then set VITE_PROXY_URL=/crdc-demo/proxy.php in your build environment.
|
||||
*
|
||||
* Usage: GET /proxy.php?target=/api/v1/districts?q=Denver&state=CO
|
||||
*/
|
||||
|
||||
// Allow cross-origin requests from any origin
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Access-Control-Allow-Methods: GET, OPTIONS');
|
||||
header('Access-Control-Allow-Headers: *');
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
||||
http_response_code(204);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Extract and validate the target path from query string
|
||||
$target = isset($_GET['target']) ? $_GET['target'] : '';
|
||||
if (empty($target)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing "target" parameter']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Construct the full API URL — only allow requests to crdc-api.civilytics.org for security
|
||||
$apiBase = 'https://crdc-api.civilytics.org';
|
||||
$url = $apiBase . $target;
|
||||
|
||||
// Validate that we're not proxying arbitrary URLs (prevent SSRF)
|
||||
if (!str_starts_with($url, $apiBase . '/api/v1/')) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Invalid target — must be under /api/v1/']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch the API response and return it with CORS headers
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
// Forward the response with appropriate status code and CORS headers
|
||||
http_response_code($httpCode);
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
echo $response;
|
||||
Reference in New Issue
Block a user