feat: 初始提交 - Code Server Bridge完整实现
- OAuth认证系统(Gitea + Lua扩展) - Git自动化操作(本地/SSH远程) - 实时进度WebSocket推送 - 现代化Tab界面UI - Cobra CLI命令行(init/version/serve) - 完整构建系统(Makefile + Taskfile) - UPX压缩支持(体积减少70%)
This commit is contained in:
149
internal/http/handlers/ws.go
Normal file
149
internal/http/handlers/ws.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
// 允许所有来源(生产环境应该做更严格的检查)
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
// ProgressMessage WebSocket进度消息结构
|
||||
type ProgressMessage struct {
|
||||
Status string `json:"status"` // 状态: checking, cloning, pulling, success, error
|
||||
Message string `json:"message"` // 消息文本
|
||||
Percent int `json:"percent"` // 进度百分比 (0-100)
|
||||
}
|
||||
|
||||
// ProgressHub 进度广播中心
|
||||
type ProgressHub struct {
|
||||
clients map[string]*websocket.Conn
|
||||
clientsMux sync.RWMutex
|
||||
broadcast chan ProgressMessage
|
||||
}
|
||||
|
||||
var (
|
||||
hub *ProgressHub
|
||||
hubOnce sync.Once
|
||||
)
|
||||
|
||||
// GetProgressHub 获取进度广播中心单例
|
||||
func GetProgressHub() *ProgressHub {
|
||||
hubOnce.Do(func() {
|
||||
hub = &ProgressHub{
|
||||
clients: make(map[string]*websocket.Conn),
|
||||
broadcast: make(chan ProgressMessage, 10),
|
||||
}
|
||||
go hub.run()
|
||||
})
|
||||
return hub
|
||||
}
|
||||
|
||||
// run 运行广播循环
|
||||
func (h *ProgressHub) run() {
|
||||
for msg := range h.broadcast {
|
||||
h.clientsMux.RLock()
|
||||
for clientID, conn := range h.clients {
|
||||
err := conn.WriteJSON(msg)
|
||||
if err != nil {
|
||||
// 写入失败,移除客户端
|
||||
conn.Close()
|
||||
h.clientsMux.RUnlock()
|
||||
h.removeClient(clientID)
|
||||
h.clientsMux.RLock()
|
||||
}
|
||||
}
|
||||
h.clientsMux.RUnlock()
|
||||
}
|
||||
}
|
||||
|
||||
// addClient 添加客户端
|
||||
func (h *ProgressHub) addClient(clientID string, conn *websocket.Conn) {
|
||||
h.clientsMux.Lock()
|
||||
defer h.clientsMux.Unlock()
|
||||
h.clients[clientID] = conn
|
||||
}
|
||||
|
||||
// removeClient 移除客户端
|
||||
func (h *ProgressHub) removeClient(clientID string) {
|
||||
h.clientsMux.Lock()
|
||||
defer h.clientsMux.Unlock()
|
||||
delete(h.clients, clientID)
|
||||
}
|
||||
|
||||
// SendProgress 发送进度消息
|
||||
func (h *ProgressHub) SendProgress(msg ProgressMessage) {
|
||||
select {
|
||||
case h.broadcast <- msg:
|
||||
case <-time.After(1 * time.Second):
|
||||
// 超时,丢弃消息
|
||||
}
|
||||
}
|
||||
|
||||
// GitProgressWS WebSocket处理器
|
||||
func GitProgressWS() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// 升级HTTP连接到WebSocket
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to upgrade to WebSocket", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// 生成客户端ID
|
||||
clientID := r.RemoteAddr + "-" + time.Now().Format("20060102150405")
|
||||
|
||||
// 添加到hub
|
||||
hub := GetProgressHub()
|
||||
hub.addClient(clientID, conn)
|
||||
defer hub.removeClient(clientID)
|
||||
|
||||
// 发送欢迎消息
|
||||
welcomeMsg := ProgressMessage{
|
||||
Status: "connected",
|
||||
Message: "WebSocket连接已建立",
|
||||
Percent: 0,
|
||||
}
|
||||
if err := conn.WriteJSON(welcomeMsg); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 保持连接,读取客户端消息(主要用于心跳)
|
||||
for {
|
||||
_, _, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
// 连接断开
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SendProgressToClients 辅助函数:向所有客户端发送进度
|
||||
func SendProgressToClients(status, message string, percent int) {
|
||||
hub := GetProgressHub()
|
||||
hub.SendProgress(ProgressMessage{
|
||||
Status: status,
|
||||
Message: message,
|
||||
Percent: percent,
|
||||
})
|
||||
}
|
||||
|
||||
// SendProgressJSON 辅助函数:发送JSON格式的进度消息
|
||||
func SendProgressJSON(w http.ResponseWriter, status, message string, percent int) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(ProgressMessage{
|
||||
Status: status,
|
||||
Message: message,
|
||||
Percent: percent,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user