Files
OpenFlare/Wavelet/internal/apps/openflare/update/routers.go
T
2026-06-18 16:08:48 +08:00

114 lines
2.7 KiB
Go

// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package update
import (
"encoding/json"
"errors"
"io"
"net/http"
"time"
"github.com/Rain-kl/Wavelet/internal/apps/openflare/compat"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
var upgradeLogsUpgrader = websocket.Upgrader{
CheckOrigin: func(_ *http.Request) bool { return true },
}
// GetLatestReleaseHandler returns the newest GitHub release for the legacy update UI.
func GetLatestReleaseHandler(c *gin.Context) {
release, err := GetLatestRelease(c.Request.Context(), c.Query("channel"))
if err != nil {
compat.Fail(c, err.Error())
return
}
compat.OK(c, release)
}
// UpgradeServerHandler schedules an automatic upgrade from the latest release.
func UpgradeServerHandler(c *gin.Context) {
var request upgradeRequest
if err := bindOptionalJSON(c.Request.Body, &request); err != nil {
compat.Fail(c, "无效的参数")
return
}
release, err := ScheduleUpgrade(c.Request.Context(), request.Channel)
if err != nil {
compat.Fail(c, err.Error())
return
}
okWithMessage(c, release, "服务升级任务已启动,下载完成后将自动重启。")
}
// UploadManualServerBinaryHandler rejects manual uploads (feature disabled upstream).
func UploadManualServerBinaryHandler(c *gin.Context) {
if err := UploadManualBinary(); err != nil {
compat.Fail(c, err.Error())
return
}
}
// ConfirmManualServerUpgradeHandler rejects manual upgrades (feature disabled upstream).
func ConfirmManualServerUpgradeHandler(c *gin.Context) {
if err := ConfirmManualUpgrade(); err != nil {
compat.Fail(c, err.Error())
return
}
}
// StreamServerUpgradeLogsHandler streams upgrade progress snapshots over WebSocket.
func StreamServerUpgradeLogsHandler(c *gin.Context) {
conn, err := upgradeLogsUpgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
defer func() {
_ = conn.Close()
}()
updates, unsubscribe := SubscribeUpgradeStream()
defer unsubscribe()
heartbeatTicker := time.NewTicker(15 * time.Second)
defer heartbeatTicker.Stop()
for {
select {
case snapshot, ok := <-updates:
if !ok {
return
}
if err := conn.WriteJSON(snapshot); err != nil {
return
}
case <-heartbeatTicker.C:
if err := conn.WriteJSON(StreamSnapshot{}); err != nil {
return
}
case <-c.Request.Context().Done():
return
}
}
}
func okWithMessage(c *gin.Context, data any, message string) {
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": message,
"data": data,
})
}
func bindOptionalJSON(body io.Reader, target any) error {
if err := json.NewDecoder(body).Decode(target); err != nil && !errors.Is(err, io.EOF) {
return err
}
return nil
}