69 lines
1.9 KiB
PHP
69 lines
1.9 KiB
PHP
<?php
|
||
/**
|
||
* 簡易BFF(stream版)
|
||
* APIサーバーへのリクエストを中継しつつ、dist以下の静的ファイルも返す
|
||
* 大容量100MB:非推奨
|
||
* 軽量な用途向け(小規模サイトやAPI中継のみなど)
|
||
*/
|
||
// ===== 設定 =====
|
||
$API_BASE_URL = getenv('API_BASE_URL'); // 例: https://xxxxx-uc.a.run.app
|
||
if (!$API_BASE_URL) {
|
||
http_response_code(500);
|
||
echo 'API_BASE_URL is not set';
|
||
exit;
|
||
}
|
||
|
||
// ===== リクエスト情報 =====
|
||
$method = $_SERVER['REQUEST_METHOD'];
|
||
$uri = $_SERVER['REQUEST_URI']; // クエリ含む
|
||
$path = parse_url($uri, PHP_URL_PATH);
|
||
|
||
// /api/* だけ中継
|
||
if (strpos($path, '/api') === 0) {
|
||
$upstreamPath = substr($uri, 4); // /api/foo?x=1 -> /foo?x=1
|
||
if ($upstreamPath === '') $upstreamPath = '/';
|
||
|
||
$url = rtrim($API_BASE_URL, '/') . $upstreamPath;
|
||
|
||
// ヘッダそのまま(最低限)
|
||
$headers = [];
|
||
foreach (getallheaders() as $k => $v) {
|
||
if (strtolower($k) === 'host') continue;
|
||
$headers[] = "$k: $v";
|
||
}
|
||
|
||
$context = stream_context_create([
|
||
'http' => [
|
||
'method' => $method,
|
||
'header' => implode("\r\n", $headers),
|
||
'content' => in_array($method, ['POST', 'PUT', 'PATCH'])
|
||
? file_get_contents('php://input')
|
||
: null,
|
||
'ignore_errors' => true, // 4xx/5xxも受け取る
|
||
]
|
||
]);
|
||
|
||
$response = file_get_contents($url, false, $context);
|
||
|
||
// ステータスコードをそのまま返す
|
||
if (isset($http_response_header[0])) {
|
||
preg_match('#HTTP/\d\.\d\s+(\d+)#', $http_response_header[0], $m);
|
||
if (!empty($m[1])) {
|
||
http_response_code((int)$m[1]);
|
||
}
|
||
}
|
||
|
||
// ヘッダも最低限返す
|
||
foreach ($http_response_header as $h) {
|
||
if (stripos($h, 'Transfer-Encoding:') === 0) continue;
|
||
if (stripos($h, 'Connection:') === 0) continue;
|
||
header($h, false);
|
||
}
|
||
|
||
echo $response;
|
||
exit;
|
||
}
|
||
|
||
// ===== それ以外は静的(例: dist/index.html) =====
|
||
readfile(__DIR__ . '/dist/index.html');
|