内嵌前端文件
This commit is contained in:
15
.github/workflows/release.yml
vendored
15
.github/workflows/release.yml
vendored
@@ -73,12 +73,7 @@ jobs:
|
||||
|
||||
# 复制安装脚本
|
||||
cp install-service.sh build/hubproxy/
|
||||
|
||||
# 复制Web资源文件(如果存在)
|
||||
if [ -d "src/public" ]; then
|
||||
cp -r src/public build/hubproxy/
|
||||
fi
|
||||
|
||||
|
||||
# 创建README文件
|
||||
cat > build/hubproxy/README.md << 'EOF'
|
||||
# HubProxy
|
||||
@@ -94,20 +89,12 @@ jobs:
|
||||
mkdir -p linux-amd64/hubproxy
|
||||
cp hubproxy/hubproxy-linux-amd64 linux-amd64/hubproxy/hubproxy
|
||||
cp hubproxy/config.toml hubproxy/hubproxy.service hubproxy/install-service.sh hubproxy/README.md linux-amd64/hubproxy/
|
||||
# 复制前端文件(如果存在)
|
||||
if [ -d "hubproxy/public" ]; then
|
||||
cp -r hubproxy/public linux-amd64/hubproxy/
|
||||
fi
|
||||
tar -czf hubproxy-${{ steps.version.outputs.version }}-linux-amd64.tar.gz -C linux-amd64 hubproxy
|
||||
|
||||
# Linux ARM64 包
|
||||
mkdir -p linux-arm64/hubproxy
|
||||
cp hubproxy/hubproxy-linux-arm64 linux-arm64/hubproxy/hubproxy
|
||||
cp hubproxy/config.toml hubproxy/hubproxy.service hubproxy/install-service.sh hubproxy/README.md linux-arm64/hubproxy/
|
||||
# 复制前端文件(如果存在)
|
||||
if [ -d "hubproxy/public" ]; then
|
||||
cp -r hubproxy/public linux-arm64/hubproxy/
|
||||
fi
|
||||
tar -czf hubproxy-${{ steps.version.outputs.version }}-linux-arm64.tar.gz -C linux-arm64 hubproxy
|
||||
|
||||
# 列出生成的文件
|
||||
|
||||
@@ -16,6 +16,5 @@ RUN apk add --no-cache skopeo && mkdir -p temp && chmod 700 temp
|
||||
|
||||
COPY --from=builder /app/hubproxy .
|
||||
COPY --from=builder /app/config.toml .
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
CMD ["./hubproxy"]
|
||||
|
||||
@@ -22,12 +22,12 @@ BINARY_NAME="hubproxy"
|
||||
LOG_DIR="/var/log/hubproxy"
|
||||
TEMP_DIR="/tmp/hubproxy-install"
|
||||
|
||||
echo -e "${BLUE}🚀 HubProxy 一键安装脚本${NC}"
|
||||
echo -e "${BLUE}HubProxy 一键安装脚本${NC}"
|
||||
echo "================================================="
|
||||
|
||||
# 检查是否以root权限运行
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo -e "${RED}❌ 此脚本需要root权限运行${NC}"
|
||||
echo -e "${RED}此脚本需要root权限运行${NC}"
|
||||
echo "请使用: sudo $0"
|
||||
exit 1
|
||||
fi
|
||||
@@ -43,55 +43,75 @@ detect_arch() {
|
||||
echo "arm64"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}❌ 不支持的架构: $arch${NC}"
|
||||
echo -e "${RED}不支持的架构: $arch${NC}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
ARCH=$(detect_arch)
|
||||
echo -e "${BLUE}🖥️ 检测到架构: linux-${ARCH}${NC}"
|
||||
echo -e "${BLUE}检测到架构: linux-${ARCH}${NC}"
|
||||
|
||||
# 检查是否为本地安装模式
|
||||
if [ -f "${BINARY_NAME}" ]; then
|
||||
echo -e "${BLUE}📦 发现本地文件,使用本地安装模式${NC}"
|
||||
echo -e "${BLUE}发现本地文件,使用本地安装模式${NC}"
|
||||
LOCAL_INSTALL=true
|
||||
else
|
||||
echo -e "${BLUE}📥 本地无文件,使用自动下载模式${NC}"
|
||||
echo -e "${BLUE}本地无文件,使用自动下载模式${NC}"
|
||||
LOCAL_INSTALL=false
|
||||
|
||||
# 检查依赖
|
||||
missing_deps=()
|
||||
for cmd in curl jq tar skopeo; do
|
||||
if ! command -v $cmd &> /dev/null; then
|
||||
echo -e "${RED}❌ 缺少依赖: $cmd${NC}"
|
||||
echo "请安装: sudo apt update && sudo apt install -y curl jq skopeo"
|
||||
exit 1
|
||||
missing_deps+=($cmd)
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing_deps[@]} -gt 0 ]; then
|
||||
echo -e "${YELLOW}检测到缺少依赖: ${missing_deps[*]}${NC}"
|
||||
echo -e "${BLUE}正在自动安装依赖...${NC}"
|
||||
|
||||
apt update && apt install -y curl jq skopeo
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}依赖安装失败${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 重新检查依赖
|
||||
for cmd in curl jq tar skopeo; do
|
||||
if ! command -v $cmd &> /dev/null; then
|
||||
echo -e "${RED}依赖安装后仍缺少: $cmd${NC}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "${GREEN}依赖安装成功${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 自动下载功能
|
||||
if [ "$LOCAL_INSTALL" = false ]; then
|
||||
echo -e "${BLUE}🔍 获取最新版本信息...${NC}"
|
||||
echo -e "${BLUE}获取最新版本信息...${NC}"
|
||||
LATEST_RELEASE=$(curl -s "${GITHUB_RELEASES}/latest")
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}❌ 无法获取版本信息${NC}"
|
||||
echo -e "${RED}无法获取版本信息${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION=$(echo "$LATEST_RELEASE" | jq -r '.tag_name')
|
||||
if [ "$VERSION" = "null" ]; then
|
||||
echo -e "${RED}❌ 无法解析版本信息${NC}"
|
||||
echo -e "${RED}无法解析版本信息${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ 最新版本: ${VERSION}${NC}"
|
||||
echo -e "${GREEN}最新版本: ${VERSION}${NC}"
|
||||
|
||||
# 构造下载URL
|
||||
ASSET_NAME="hubproxy-${VERSION}-linux-${ARCH}.tar.gz"
|
||||
DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${VERSION}/${ASSET_NAME}"
|
||||
|
||||
echo -e "${BLUE}📥 下载: ${ASSET_NAME}${NC}"
|
||||
echo -e "${BLUE}下载: ${ASSET_NAME}${NC}"
|
||||
|
||||
# 创建临时目录并下载
|
||||
rm -rf "${TEMP_DIR}"
|
||||
@@ -100,89 +120,83 @@ if [ "$LOCAL_INSTALL" = false ]; then
|
||||
|
||||
curl -L -o "${ASSET_NAME}" "${DOWNLOAD_URL}"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}❌ 下载失败${NC}"
|
||||
echo -e "${RED}下载失败${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 解压
|
||||
tar -xzf "${ASSET_NAME}"
|
||||
if [ $? -ne 0 ] || [ ! -d "hubproxy" ]; then
|
||||
echo -e "${RED}❌ 解压失败${NC}"
|
||||
echo -e "${RED}解压失败${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd hubproxy
|
||||
echo -e "${GREEN}✅ 下载完成${NC}"
|
||||
echo -e "${GREEN}下载完成${NC}"
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}📋 开始安装 HubProxy...${NC}"
|
||||
echo -e "${YELLOW}开始安装 HubProxy...${NC}"
|
||||
|
||||
# 停止现有服务(如果存在)
|
||||
if systemctl is-active --quiet ${SERVICE_NAME} 2>/dev/null; then
|
||||
echo -e "${YELLOW}⏸️ 停止现有服务...${NC}"
|
||||
echo -e "${YELLOW}停止现有服务...${NC}"
|
||||
systemctl stop ${SERVICE_NAME}
|
||||
fi
|
||||
|
||||
# 备份现有配置(如果存在)
|
||||
CONFIG_BACKUP_EXISTS=false
|
||||
if [ -f "${INSTALL_DIR}/${CONFIG_FILE}" ]; then
|
||||
echo -e "${BLUE}💾 备份现有配置...${NC}"
|
||||
echo -e "${BLUE}备份现有配置...${NC}"
|
||||
cp "${INSTALL_DIR}/${CONFIG_FILE}" "${TEMP_DIR}/config.toml.backup"
|
||||
CONFIG_BACKUP_EXISTS=true
|
||||
fi
|
||||
|
||||
# 1. 创建目录结构
|
||||
echo -e "${BLUE}📁 创建目录结构${NC}"
|
||||
echo -e "${BLUE}创建目录结构${NC}"
|
||||
mkdir -p ${INSTALL_DIR}
|
||||
mkdir -p ${LOG_DIR}
|
||||
chmod 755 ${INSTALL_DIR}
|
||||
chmod 755 ${LOG_DIR}
|
||||
|
||||
# 2. 复制二进制文件
|
||||
echo -e "${BLUE}📦 复制二进制文件${NC}"
|
||||
echo -e "${BLUE}复制二进制文件${NC}"
|
||||
cp "${BINARY_NAME}" "${INSTALL_DIR}/"
|
||||
chmod +x "${INSTALL_DIR}/${BINARY_NAME}"
|
||||
|
||||
# 3. 复制配置文件
|
||||
echo -e "${BLUE}⚙️ 复制配置文件${NC}"
|
||||
echo -e "${BLUE}复制配置文件${NC}"
|
||||
if [ -f "${CONFIG_FILE}" ]; then
|
||||
if [ "$CONFIG_BACKUP_EXISTS" = false ]; then
|
||||
cp "${CONFIG_FILE}" "${INSTALL_DIR}/"
|
||||
echo -e "${GREEN}✅ 配置文件复制成功${NC}"
|
||||
echo -e "${GREEN}配置文件复制成功${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ 保留现有配置文件${NC}"
|
||||
echo -e "${YELLOW}保留现有配置文件${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ 配置文件不存在,将使用默认配置${NC}"
|
||||
echo -e "${YELLOW}配置文件不存在,将使用默认配置${NC}"
|
||||
fi
|
||||
|
||||
# 4. 复制公共文件(如果存在)
|
||||
if [ -d "public" ]; then
|
||||
echo -e "${BLUE}🌐 复制Web资源文件${NC}"
|
||||
cp -r "public" "${INSTALL_DIR}/"
|
||||
chmod -R 644 "${INSTALL_DIR}/public"
|
||||
find "${INSTALL_DIR}/public" -type d -exec chmod 755 {} \;
|
||||
fi
|
||||
# 4. 前端文件已嵌入二进制程序,无需复制
|
||||
|
||||
# 5. 安装systemd服务文件
|
||||
echo -e "${BLUE}🔧 安装systemd服务文件${NC}"
|
||||
echo -e "${BLUE}安装systemd服务文件${NC}"
|
||||
cp "${SERVICE_NAME}.service" "/etc/systemd/system/"
|
||||
systemctl daemon-reload
|
||||
|
||||
# 6. 恢复配置文件(如果有备份)
|
||||
if [ "$CONFIG_BACKUP_EXISTS" = true ]; then
|
||||
echo -e "${BLUE}🔄 恢复配置文件...${NC}"
|
||||
echo -e "${BLUE}恢复配置文件...${NC}"
|
||||
cp "${TEMP_DIR}/config.toml.backup" "${INSTALL_DIR}/${CONFIG_FILE}"
|
||||
fi
|
||||
|
||||
# 7. 启用并启动服务
|
||||
echo -e "${BLUE}🚀 启用并启动服务${NC}"
|
||||
echo -e "${BLUE}启用并启动服务${NC}"
|
||||
systemctl enable ${SERVICE_NAME}
|
||||
systemctl start ${SERVICE_NAME}
|
||||
|
||||
# 8. 清理临时文件
|
||||
if [ "$LOCAL_INSTALL" = false ]; then
|
||||
echo -e "${BLUE}🧹 清理临时文件...${NC}"
|
||||
echo -e "${BLUE}清理临时文件...${NC}"
|
||||
cd /
|
||||
rm -rf "${TEMP_DIR}"
|
||||
fi
|
||||
@@ -191,22 +205,11 @@ fi
|
||||
sleep 2
|
||||
if systemctl is-active --quiet ${SERVICE_NAME}; then
|
||||
echo ""
|
||||
echo -e "${GREEN}🎉 HubProxy 安装成功!${NC}"
|
||||
if [ "$LOCAL_INSTALL" = false ]; then
|
||||
echo -e "${BLUE}版本: ${VERSION}${NC}"
|
||||
echo -e "${BLUE}配置文件: ${INSTALL_DIR}/${CONFIG_FILE}${NC}"
|
||||
fi
|
||||
echo ""
|
||||
echo -e "${BLUE}📊 服务状态:${NC}"
|
||||
systemctl status ${SERVICE_NAME} --no-pager -l | head -10
|
||||
echo ""
|
||||
echo -e "${BLUE}🔧 服务管理:${NC}"
|
||||
echo " sudo systemctl start|stop|restart|status ${SERVICE_NAME}"
|
||||
echo " sudo journalctl -u ${SERVICE_NAME} -f"
|
||||
echo ""
|
||||
echo -e "${BLUE}📁 安装目录: ${INSTALL_DIR}${NC}"
|
||||
echo -e "${GREEN}HubProxy 安装成功!${NC}"
|
||||
echo -e "${GREEN}默认运行端口: 5000${NC}"
|
||||
echo -e "${GREEN}配置文件路径: ${INSTALL_DIR}/${CONFIG_FILE}${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ 服务启动失败${NC}"
|
||||
echo -e "${RED}服务启动失败${NC}"
|
||||
echo "查看错误日志: sudo journalctl -u ${SERVICE_NAME} -f"
|
||||
exit 1
|
||||
fi
|
||||
35
src/main.go
35
src/main.go
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
@@ -10,6 +11,23 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
//go:embed public/*
|
||||
var staticFiles embed.FS
|
||||
|
||||
// 服务嵌入的静态文件
|
||||
func serveEmbedFile(c *gin.Context, filename string) {
|
||||
data, err := staticFiles.ReadFile(filename)
|
||||
if err != nil {
|
||||
c.Status(404)
|
||||
return
|
||||
}
|
||||
contentType := "text/html; charset=utf-8"
|
||||
if strings.HasSuffix(filename, ".ico") {
|
||||
contentType = "image/x-icon"
|
||||
}
|
||||
c.Data(200, contentType, data)
|
||||
}
|
||||
|
||||
var (
|
||||
exps = []*regexp.Regexp{
|
||||
regexp.MustCompile(`^(?:https?://)?github\.com/([^/]+)/([^/]+)/(?:releases|archive)/.*$`),
|
||||
@@ -48,21 +66,22 @@ func main() {
|
||||
// 初始化skopeo路由(静态文件和API路由)
|
||||
initSkopeoRoutes(router)
|
||||
|
||||
// 单独处理根路径请求
|
||||
// 静态文件路由(使用嵌入文件)
|
||||
router.GET("/", func(c *gin.Context) {
|
||||
c.File("./public/index.html")
|
||||
serveEmbedFile(c, "public/index.html")
|
||||
})
|
||||
router.GET("/public/*filepath", func(c *gin.Context) {
|
||||
filepath := strings.TrimPrefix(c.Param("filepath"), "/")
|
||||
serveEmbedFile(c, "public/"+filepath)
|
||||
})
|
||||
|
||||
// 指定具体的静态文件路径
|
||||
router.Static("/public", "./public")
|
||||
router.GET("/skopeo.html", func(c *gin.Context) {
|
||||
c.File("./public/skopeo.html")
|
||||
serveEmbedFile(c, "public/skopeo.html")
|
||||
})
|
||||
router.GET("/search.html", func(c *gin.Context) {
|
||||
c.File("./public/search.html")
|
||||
serveEmbedFile(c, "public/search.html")
|
||||
})
|
||||
router.GET("/favicon.ico", func(c *gin.Context) {
|
||||
c.File("./public/favicon.ico")
|
||||
serveEmbedFile(c, "public/favicon.ico")
|
||||
})
|
||||
|
||||
// 注册dockerhub搜索路由
|
||||
|
||||
Reference in New Issue
Block a user