Files
eSIM-Tools/netlify.toml
Abner 07e048679f 🐛 fix: 修复 Google Tag Manager 脚本标签重复闭合导致的加载错误
- 移除 index.html 中 Google gtag.js script 标签末尾多余的 `</script>`,避免 DOM 结构异常
- 保留原有 `defer`、`src`、`crossorigin` 配置,确保延迟加载逻辑不被破坏
- 删除冲突的属性 `integrity` 相关内容,配合当前实际加载方式恢复正常请求行为
2026-06-13 22:14:21 +08:00

195 lines
6.3 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]]
# Simyo eSIM页面 - 模块化版本
from = "/simyo"
to = "/src/simyo/simyo_modular.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"
# Markdown for Agents检测 Accept: text/markdown 请求
[[edge_functions]]
path = "/"
function = "markdown-negotiation"
[[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"
# favicon 根路径重定向(浏览器默认请求 /favicon.ico
[[redirects]]
from = "/favicon.ico"
to = "/src/assets/favicon.ico"
status = 200
# OG 社交分享图片重定向
[[redirects]]
from = "/og-image.png"
to = "/src/assets/og-image.png"
status = 200
# 处理SPA路由兜底 404
[[redirects]]
from = "/*"
to = "/index.html"
status = 404
# 静态资源长期缓存CSS/JS/字体/图片)
[[headers]]
for = "/src/styles/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
[[headers]]
for = "/src/js/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
[[headers]]
for = "/src/assets/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
[[headers]]
for = "/dist/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
# HTML 页面:短缓存 + stale-while-revalidate
[[headers]]
for = "/*.html"
[headers.values]
Cache-Control = "public, max-age=300, stale-while-revalidate=86400"
# 安全头部
[[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' 'unsafe-eval' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.googletagmanager.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 https://fonts.googleapis.com; img-src 'self' data: https:; connect-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://browser.sentry-cdn.com https://www.google-analytics.com https://analytics.google.com https://stats.g.doubleclick.net https://www.googletagmanager.com https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com https://www.google.com https://www.gstatic.com https://*.sentry.io; font-src 'self' data: https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://fonts.gstatic.com; manifest-src 'self';"
# Agent 发现 Link 响应头 (RFC 8288)
[[headers]]
for = "/"
[headers.values]
Link = "</.well-known/api-catalog>; rel=\"api-catalog\", </.well-known/oauth-protected-resource>; rel=\"oauth-protected-resource\", </.well-known/mcp/server-card.json>; rel=\"mcp-server-card\", </.well-known/agent-skills/index.json>; rel=\"agent-skills\""
# Markdown for Agents 支持头部
[[headers]]
for = "/"
[headers.values]
Vary = "Accept"
[[headers]]
for = "/manifest.webmanifest"
[headers.values]
Content-Type = "application/manifest+json; charset=utf-8"