Files
eSIM-Tools/netlify.toml
Abner e1ed68023f feat: 引入 Simyo API 多版本代理和路径更新
*   将主 Simyo API 代理地址从旧版 `simyoapi` 更新至 `webapi/api/v1`,以支持最新的 API 接口。
*   为 `esim.availableValidationMethods` 添加 `webapi/api/v2` 特殊代理规则,确保特定端点使用正确的 API 版本。
*   新增 `/api/simyo/legacy/*` 路径,兼容旧版 `simyoapi/api/v1` 接口,以保留向后兼容性。
2026-01-12 22:42:52 +08:00

153 lines
4.9 KiB
TOML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[build]
# 构建命令
command = "npm run build --silent"
# 发布目录:仅暴露构建后的 dist 输出
publish = "dist"
# Functions目录
functions = "netlify/functions"
# Edge Functions 目录
edge_functions = "netlify/edge-functions"
[build.environment]
# 固定 Node 版本,避免二进制依赖(如 sharp在 Node 22 下编译耗时
NODE_VERSION = "20.12.2"
# 安装时减少无关输出与提示
NPM_FLAGS = "--no-audit --no-fund --omit=optional"
# 重定向和重写规则
[[redirects]]
# Giffgaff eSIM页面 - 模块化版本
from = "/giffgaff"
to = "/src/giffgaff/giffgaff_modular.html"
status = 200
[[redirects]]
# Giffgaff eSIM页面 - 原始版本(备份)
from = "/giffgaff-legacy"
to = "/src/giffgaff/giffgaff_complete_esim.html"
status = 200
[[redirects]]
# Simyo eSIM页面 - 模块化版本
from = "/simyo"
to = "/src/simyo/simyo_modular.html"
status = 200
[[redirects]]
# Simyo eSIM页面 - 原始版本(备份)
from = "/simyo-legacy"
to = "/src/simyo/simyo_complete_esim.html"
status = 200
[[redirects]]
# 根路径重定向到选择页面
from = "/"
to = "/index.html"
status = 200
# API代理重定向用于解决CORS问题
# 通用 Simyo API 代理 (webapi - 新版API)
[[redirects]]
from = "/api/simyo/*"
to = "https://appapi.simyo.nl/webapi/api/v1/:splat"
status = 200
force = true
headers = {X-Forwarded-Host = "appapi.simyo.nl"}
# v2 API 代理(用于特定端点如可用验证方式查询)
[[redirects]]
from = "/api/simyo/esim.availableValidationMethods"
to = "https://appapi.simyo.nl/webapi/api/v2/esim.availableValidationMethods"
status = 200
force = true
headers = {X-Forwarded-Host = "appapi.simyo.nl"}
# 保留旧版 simyoapi 路径的兼容性(如果需要)
[[redirects]]
from = "/api/simyo/legacy/*"
to = "https://appapi.simyo.nl/simyoapi/api/v1/:splat"
status = 200
force = true
headers = {X-Forwarded-Host = "appapi.simyo.nl"}
[[headers]]
# 限制 Simyo 代理仅允许指定站点跨域访问
for = "/api/simyo/*"
[headers.values]
Access-Control-Allow-Origin = "https://esim.cosr.eu.org"
Access-Control-Allow-Headers = "Content-Type, Authorization"
Access-Control-Allow-Methods = "GET, POST, OPTIONS"
Vary = "Origin"
# 将 /bff/* 映射到 Edge Function bff-proxy
[[edge_functions]]
path = "/bff/*"
function = "bff-proxy"
[[redirects]]
from = "/api/giffgaff/*"
to = "https://api.giffgaff.com/:splat"
status = 200
force = true
headers = {X-Forwarded-Host = "api.giffgaff.com"}
[[headers]]
for = "/api/giffgaff/*"
[headers.values]
# giffgaff 直连不受此限制,保持通用放行
Access-Control-Allow-Origin = "*"
Access-Control-Allow-Headers = "Content-Type, Authorization"
Access-Control-Allow-Methods = "GET, POST, OPTIONS"
[[redirects]]
from = "/api/giffgaff-id/*"
to = "https://id.giffgaff.com/:splat"
status = 200
force = true
headers = {X-Forwarded-Host = "id.giffgaff.com"}
[[headers]]
for = "/api/giffgaff-id/*"
[headers.values]
Access-Control-Allow-Origin = "*"
Access-Control-Allow-Headers = "Content-Type, Authorization"
Access-Control-Allow-Methods = "GET, POST, OPTIONS"
[[redirects]]
from = "/api/giffgaff-public/*"
to = "https://publicapi.giffgaff.com/:splat"
status = 200
force = true
headers = {X-Forwarded-Host = "publicapi.giffgaff.com"}
[[headers]]
for = "/api/giffgaff-public/*"
[headers.values]
Access-Control-Allow-Origin = "*"
Access-Control-Allow-Headers = "Content-Type, Authorization"
Access-Control-Allow-Methods = "GET, POST, OPTIONS"
# 处理SPA路由如果需要
[[redirects]]
from = "/*"
to = "/index.html"
status = 404
# 安全头部
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "DENY"
X-XSS-Protection = "1; mode=block"
X-Content-Type-Options = "nosniff"
Referrer-Policy = "strict-origin-when-cross-origin"
# 生产 CSP移除 unsafe-inline基于 nonce/hash 的策略(页面模板需注入 nonce
# 如暂无模板注入机制,可先允许外链受信源并避免内联脚本
Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.googletagmanager.com https://challenges.cloudflare.com https://www.google.com https://www.gstatic.com https://browser.sentry-cdn.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; img-src 'self' data: https:; connect-src 'self' https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com https://challenges.cloudflare.com https://www.google.com https://www.gstatic.com https://*.sentry.io; font-src 'self' data: https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; manifest-src 'self';"
[[headers]]
for = "/manifest.webmanifest"
[headers.values]
Content-Type = "application/manifest+json; charset=utf-8"