Laravel静态文件在AWS API Gateway+NLB+App Mesh架构下的访问问题
问题核心
Scribe生成文档时,会基于后端服务收到的Host头或Laravel的APP_URL配置生成静态资源URL。在你的链路中,API Gateway→NLB→App Mesh的转发过程中,Host头被改写为内部私有DNS(如NLB或App Mesh虚拟服务域名),导致静态资源URL指向外部无法访问的私有地址。
具体修复步骤
1. 强制Laravel使用公网域名生成URL
静态配置(固定环境)
在Laravel的.env文件或ECS服务的环境变量中,设置APP_URL为API Gateway的公网域名:
APP_URL=https://your-api-gateway-public-domain.com
动态适配(多环境场景)
如果需要根据请求动态获取公网域名,在app/Providers/AppServiceProvider.php的boot方法中添加逻辑,读取API Gateway传递的X-Forwarded-Host头:
public function boot() { if ($forwardedHost = request()->header('X-Forwarded-Host')) { $protocol = request()->header('X-Forwarded-Proto') ?? 'https'; config(['app.url' => "{$protocol}://{$forwardedHost}"]); } }
2. 配置API Gateway传递原始Host头
修改CDK中API Gateway与NLB的集成配置,添加参数传递原始请求的Host头到后端:
const nlbIntegration = new apigateway.Integration({ type: apigateway.IntegrationType.HTTP_PROXY, integrationHttpMethod: 'ANY', uri: `http://${nlbDns}/{proxy}`, options: { connectionType: apigateway.ConnectionType.VPC_LINK, vpcLink: vpcLink, requestParameters: { 'integration.request.path.proxy': 'method.request.path.proxy', // 添加这一行:传递原始Host头到NLB 'integration.request.header.Host': 'method.request.header.Host' }, }, });
3. 调整App Mesh网关路由的Host重写策略
当前配置的rewriteRequestHostname: true会将请求Host改写为虚拟服务的内部域名,需调整:
appmesh.virtualGateway.addGatewayRoute('core-service', { routeSpec: GatewayRouteSpec.http({ routeTarget: coreService.virtualService, match: { path: HttpGatewayRoutePathMatch.startsWith('/'.concat(serviceConfig?.host_name ?? 'core').concat('/')), // 关闭Host重写,保留原始请求的公网Host // rewriteRequestHostname: true, }, }), })
若业务必须保留Host重写,需确保虚拟服务的域名与API Gateway公网域名一致,或在后端通过X-Forwarded-Host获取原始域名。
4. 优化Nginx的Host传递配置
在Nginx的PHP-FPM处理块中,确保传递正确的Host参数给Laravel:
location ~ \.php$ { root /var/www/html/public; // ... 其他缓存配置 ... // 传递原始请求的Host(优先用X-Forwarded-Host) fastcgi_param HTTP_HOST $http_x_forwarded_host; // 回退方案:如果没有X-Forwarded-Host则用当前Host // fastcgi_param HTTP_HOST $http_host; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param HTTPS $fastcgi_param_https_variable; fastcgi_read_timeout 900s; include fastcgi_params; }
5. 重新生成Scribe文档
修改配置后,重新运行生成命令,确保静态资源URL更新为正确的公网域名:
php artisan scribe:generate
验证方法
访问API Gateway公网域名下的Scribe文档页面,打开浏览器开发者工具,查看CSS/JS等静态资源的请求URL,确认其域名是API Gateway的公网地址,而非私有DNS。
内容的提问来源于stack exchange,提问作者bmbbambus

