Files
Edu/infra/apollo-router/entrypoint.sh
SpecialX caa90eba85 feat(infra): enable apollo-router APQ + manifest + depth/cost limits
Task 14 of portal-shell data abstraction plan (M3 security).

router.yaml:
- persisted_queries: enabled + require_manifest (env-controlled)
- limits: max_depth=10, max_cost=1000, max_batch_size=5
- introspection: env-controlled (prod=false, dev=true)

docker-compose.yml:
- Mount portal-shell/public/pq-manifest.json as read-only volume
- Add APOLLO_REQUIRE_PQ_MANIFEST + APOLLO_ROUTER_INTROSPECTION env vars
- Dev defaults preserve current behavior (manifest optional)

entrypoint.sh:
- Pre-start check: if require_manifest=true, fail fast when manifest missing
- Dev mode: warn but continue when manifest absent

Production enables strict mode via env:
  APOLLO_REQUIRE_PQ_MANIFEST=true
  APOLLO_ROUTER_INTROSPECTION=false
2026-07-17 13:32:46 +08:00

98 lines
3.2 KiB
Bash
Raw Permalink 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.
#!/bin/bash
# Apollo Router 启动脚本
#
# 1. 等待所有子图 /graphql 端点就绪
# 2. 使用 rover 组合 supergraph SDL
# 3. 启动 apollo-router
set -e
SUBGRAPHS=(
"iam:3002"
"core-edu:3004"
"content:3005"
"msg:3007"
"ai:3008"
"data-ana:3006"
)
echo "[apollo-router] Waiting for subgraphs to be ready..."
wait_for_subgraph() {
local name="$1"
local host="$2"
local port="$3"
local max_retries=60
local retry=0
while [ $retry -lt $max_retries ]; do
if curl -sf -o /dev/null "http://${host}:${port}/healthz" 2>/dev/null; then
echo "[apollo-router] ${name} is ready (http://${host}:${port})"
return 0
fi
retry=$((retry + 1))
echo "[apollo-router] Waiting for ${name} at ${host}:${port} (attempt ${retry}/${max_retries})"
sleep 3
done
echo "[apollo-router] WARNING: ${name} not ready after ${max_retries} attempts, continuing anyway..."
return 0
}
for entry in "${SUBGRAPHS[@]}"; do
name="${entry%%:*}"
hostport="${entry#*:}"
host="${hostport%%:*}"
port="${hostport##*:}"
wait_for_subgraph "$name" "$host" "$port"
done
# 组合 supergraph SDL
echo "[apollo-router] Composing supergraph SDL..."
export APOLLO_ELV2_LICENSE=accept
max_compose_retries=5
compose_retry=0
while [ $compose_retry -lt $max_compose_retries ]; do
compose_retry=$((compose_retry + 1))
if rover supergraph compose --config /dist/supergraph.yaml --output /tmp/supergraph.graphql 2>&1; then
echo "[apollo-router] Supergraph composed successfully"
break
fi
echo "[apollo-router] Compose attempt ${compose_retry}/${max_compose_retries} failed, retrying in 5s..."
sleep 5
done
if [ ! -f /tmp/supergraph.graphql ]; then
echo "[apollo-router] ERROR: Failed to compose supergraph after ${max_compose_retries} attempts"
exit 1
fi
# PQ manifest 检查v2.1 M3 安全加固)
# 关联portal-shell spec §4.2、§4.3
# - 生产模式APOLLO_REQUIRE_PQ_MANIFEST=true必须存在 manifest否则启动失败
# - 开发模式APOLLO_REQUIRE_PQ_MANIFEST=falsemanifest 不存在时仅警告
MANIFEST_PATH="/etc/apollo-router/pq-manifest.json"
REQUIRE_MANIFEST="${APOLLO_REQUIRE_PQ_MANIFEST:-false}"
if [ "${REQUIRE_MANIFEST}" = "true" ]; then
if [ ! -f "${MANIFEST_PATH}" ]; then
echo "[apollo-router] ERROR: APOLLO_REQUIRE_PQ_MANIFEST=true but manifest not found at ${MANIFEST_PATH}"
echo "[apollo-router] Run 'pnpm --filter @edu/portal-shell run generate-pq-manifest' to generate it."
exit 1
fi
QUERY_COUNT=$(grep -c '"' "${MANIFEST_PATH}" 2>/dev/null || echo "0")
echo "[apollo-router] PQ manifest loaded (require_manifest=true): ${MANIFEST_PATH}"
else
if [ ! -f "${MANIFEST_PATH}" ]; then
echo "[apollo-router] WARNING: PQ manifest not found at ${MANIFEST_PATH} (require_manifest=false, continuing)"
echo "[apollo-router] APQ will accept hash-only requests but cannot resolve unknown hashes."
else
echo "[apollo-router] PQ manifest loaded (require_manifest=false): ${MANIFEST_PATH}"
fi
fi
# 启动 routerrouter 二进制位于 /dist/router由基础镜像 ghcr.io/apollographql/router 提供)
echo "[apollo-router] Starting Apollo Router on port 3000..."
exec /dist/router --config /dist/configuration.yaml --supergraph /tmp/supergraph.graphql --hot-reload