mirror of
https://gitee.com/ShopeX/ECShopX
synced 2026-08-03 02:46:16 +08:00
118 lines
3.8 KiB
Bash
Executable File
118 lines
3.8 KiB
Bash
Executable File
#!/bin/sh
|
||
# ECShopX Web 前端(Nuxt)容器启动脚本
|
||
# 容器重启后自动启动已编译的 Nuxt 生产服务
|
||
|
||
APP_DIR="/data/httpd/ECShopX_web-frontend"
|
||
BUILD_FILE="$APP_DIR/.output/server/index.mjs"
|
||
LOG_FILE="/var/log/nuxt.log"
|
||
WAIT_INTERVAL="${NUXT_WAIT_INTERVAL:-10}"
|
||
PUBLIC_API_BASE="${NUXT_PUBLIC_API_BASE:-http://localhost:8080/api/h5app}"
|
||
INTERNAL_API_BASE="${NUXT_INTERNAL_API_BASE:-${NUXT_API_BASE:-http://ecshopx-dev:8080/api/h5app}}"
|
||
|
||
export TZ="${TZ:-Asia/Shanghai}"
|
||
export NITRO_HOST=0.0.0.0
|
||
export NITRO_PORT=3000
|
||
export HOST=0.0.0.0
|
||
export PORT=3000
|
||
|
||
cd "$APP_DIR" || {
|
||
echo "错误: 无法进入目录 $APP_DIR"
|
||
exit 1
|
||
}
|
||
|
||
start_local_api_proxy() {
|
||
node <<'NODE_PROXY' &
|
||
const http = require('http')
|
||
const https = require('https')
|
||
|
||
const publicBase = process.env.NUXT_PUBLIC_API_BASE || 'http://localhost:8080/api/h5app'
|
||
const internalBase =
|
||
process.env.NUXT_INTERNAL_API_BASE ||
|
||
process.env.NUXT_API_BASE ||
|
||
'http://ecshopx-dev:8080/api/h5app'
|
||
|
||
let publicUrl
|
||
let internalUrl
|
||
try {
|
||
publicUrl = new URL(publicBase)
|
||
internalUrl = new URL(internalBase)
|
||
} catch (error) {
|
||
console.error(`[SSR API Proxy] API URL 解析失败: ${error.message}`)
|
||
process.exit(0)
|
||
}
|
||
|
||
const localHosts = new Set(['localhost', '127.0.0.1', '::1'])
|
||
if (!localHosts.has(publicUrl.hostname)) {
|
||
console.log(`[SSR API Proxy] NUXT_PUBLIC_API_BASE=${publicBase} 不是本机地址,跳过本地转发`)
|
||
process.exit(0)
|
||
}
|
||
|
||
const listenHost = publicUrl.hostname === '::1' ? '::1' : '127.0.0.1'
|
||
const listenPort = Number(publicUrl.port || (publicUrl.protocol === 'https:' ? 443 : 80))
|
||
const publicPath = publicUrl.pathname.replace(/\/+$/, '') || '/'
|
||
const internalPath = internalUrl.pathname.replace(/\/+$/, '') || '/'
|
||
const transport = internalUrl.protocol === 'https:' ? https : http
|
||
|
||
function joinTargetPath(requestPath) {
|
||
const suffix = requestPath.startsWith(publicPath) ? requestPath.slice(publicPath.length) : requestPath
|
||
const normalizedSuffix = suffix.startsWith('/') ? suffix : `/${suffix}`
|
||
return `${internalPath}${normalizedSuffix}`.replace(/\/{2,}/g, '/')
|
||
}
|
||
|
||
const server = http.createServer((req, res) => {
|
||
const incomingUrl = new URL(req.url || '/', publicUrl)
|
||
const headers = { ...req.headers, host: internalUrl.host }
|
||
const targetPath = `${joinTargetPath(incomingUrl.pathname)}${incomingUrl.search}`
|
||
const proxyReq = transport.request(
|
||
{
|
||
protocol: internalUrl.protocol,
|
||
hostname: internalUrl.hostname,
|
||
port: internalUrl.port || (internalUrl.protocol === 'https:' ? 443 : 80),
|
||
method: req.method,
|
||
path: targetPath,
|
||
headers,
|
||
},
|
||
(proxyRes) => {
|
||
res.writeHead(proxyRes.statusCode || 502, proxyRes.headers)
|
||
proxyRes.pipe(res)
|
||
}
|
||
)
|
||
|
||
proxyReq.on('error', (error) => {
|
||
console.error(`[SSR API Proxy] ${req.method} ${targetPath} -> ${error.message}`)
|
||
if (!res.headersSent) {
|
||
res.writeHead(502, { 'content-type': 'text/plain; charset=utf-8' })
|
||
}
|
||
res.end('Bad Gateway')
|
||
})
|
||
|
||
req.pipe(proxyReq)
|
||
})
|
||
|
||
server.on('error', (error) => {
|
||
if (error.code === 'EADDRINUSE') {
|
||
console.log(`[SSR API Proxy] ${listenHost}:${listenPort} 已被占用,跳过本地转发`)
|
||
return
|
||
}
|
||
console.error(`[SSR API Proxy] 启动失败: ${error.message}`)
|
||
})
|
||
|
||
server.listen(listenPort, listenHost, () => {
|
||
console.log(`[SSR API Proxy] http://${listenHost}:${listenPort}${publicPath} -> ${internalBase}`)
|
||
})
|
||
NODE_PROXY
|
||
}
|
||
|
||
export NUXT_PUBLIC_API_BASE="$PUBLIC_API_BASE"
|
||
export NUXT_INTERNAL_API_BASE="$INTERNAL_API_BASE"
|
||
start_local_api_proxy
|
||
|
||
echo "等待 Nuxt 生产构建产物: $BUILD_FILE"
|
||
while [ ! -f "$BUILD_FILE" ]; do
|
||
echo "未找到构建产物,${WAIT_INTERVAL} 秒后重试(可先运行 dev-setup.sh 完成编译)..."
|
||
sleep "$WAIT_INTERVAL"
|
||
done
|
||
|
||
echo "启动 Nuxt 服务 (0.0.0.0:3000)..."
|
||
exec node .output/server/index.mjs >> "$LOG_FILE" 2>&1
|