Init V4 community edition (#2265)

* Init V4 community edition

* Init V4 community edition
This commit is contained in:
AaronLiu
2025-04-20 17:31:25 +08:00
committed by GitHub
parent da4e44b77a
commit 21d158db07
597 changed files with 119415 additions and 41692 deletions

View File

@@ -1,62 +1,75 @@
package middleware
import (
"github.com/cloudreve/Cloudreve/v3/pkg/auth"
"github.com/cloudreve/Cloudreve/v3/pkg/cluster"
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
"sync"
"github.com/cloudreve/Cloudreve/v4/application/dependency"
"github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/cloudreve/Cloudreve/v4/pkg/cluster"
"github.com/cloudreve/Cloudreve/v4/pkg/downloader"
"github.com/cloudreve/Cloudreve/v4/pkg/request"
"github.com/cloudreve/Cloudreve/v4/pkg/serializer"
"github.com/cloudreve/Cloudreve/v4/routers/controllers"
"github.com/gin-gonic/gin"
"strconv"
)
// MasterMetadata 解析主机节点发来请求的包含主机节点信息的元数据
func MasterMetadata() gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("MasterSiteID", c.GetHeader(auth.CrHeaderPrefix+"Site-Id"))
c.Set("MasterSiteURL", c.GetHeader(auth.CrHeaderPrefix+"Site-Url"))
c.Set("MasterVersion", c.GetHeader(auth.CrHeaderPrefix+"Cloudreve-Version"))
c.Next()
}
type SlaveNodeSettingGetter interface {
// GetNodeSetting returns the node settings and its hash
GetNodeSetting() (*types.NodeSetting, string)
}
// UseSlaveAria2Instance 从机用于获取对应主机节点的Aria2实例
func UseSlaveAria2Instance(clusterController cluster.Controller) gin.HandlerFunc {
return func(c *gin.Context) {
if siteID, exist := c.Get("MasterSiteID"); exist {
// 获取对应主机节点的从机Aria2实例
caller, err := clusterController.GetAria2Instance(siteID.(string))
if err != nil {
c.JSON(200, serializer.Err(serializer.CodeNotSet, "Failed to get Aria2 instance", err))
c.Abort()
return
}
var downloaderPool = sync.Map{}
c.Set("MasterAria2Instance", caller)
// PrepareSlaveDownloader creates or resume a downloader based on input node settings
func PrepareSlaveDownloader(dep dependency.Dep, ctxKey interface{}) gin.HandlerFunc {
return func(c *gin.Context) {
nodeSettings, hash := controllers.ParametersFromContext[SlaveNodeSettingGetter](c, ctxKey).GetNodeSetting()
// try to get downloader from pool
if d, ok := downloaderPool.Load(hash); ok {
c.Set(downloader.DownloaderCtxKey, d)
c.Next()
return
}
c.JSON(200, serializer.ParamErr("Unknown master node ID", nil))
c.Abort()
}
}
func SlaveRPCSignRequired(nodePool cluster.Pool) gin.HandlerFunc {
return func(c *gin.Context) {
nodeID, err := strconv.ParseUint(c.GetHeader(auth.CrHeaderPrefix+"Node-Id"), 10, 64)
// create a new downloader
d, err := cluster.NewDownloader(c, dep.RequestClient(request.WithContext(c), request.WithLogger(dep.Logger())), dep.SettingProvider(), nodeSettings)
if err != nil {
c.JSON(200, serializer.ParamErr("Unknown master node ID", err))
c.JSON(200, serializer.ParamErr(c, "Failed to create downloader", err))
c.Abort()
return
}
slaveNode := nodePool.GetNodeByID(uint(nodeID))
if slaveNode == nil {
c.JSON(200, serializer.ParamErr("Unknown master node ID", err))
c.Abort()
return
}
SignRequired(slaveNode.MasterAuthInstance())(c)
// save downloader to pool
downloaderPool.Store(hash, d)
c.Set(downloader.DownloaderCtxKey, d)
c.Next()
}
}
func SlaveRPCSignRequired() gin.HandlerFunc {
return func(c *gin.Context) {
nodeId := cluster.NodeIdFromContext(c)
if nodeId == 0 {
c.JSON(200, serializer.ParamErr(c, "Unknown node ID", nil))
c.Abort()
return
}
np, err := dependency.FromContext(c).NodePool(c)
if err != nil {
c.JSON(200, serializer.NewError(serializer.CodeInternalSetting, "Failed to get node pool", err))
c.Abort()
return
}
slaveNode, err := np.Get(c, types.NodeCapabilityNone, nodeId)
if slaveNode == nil || slaveNode.IsMaster() {
c.JSON(200, serializer.ParamErr(c, "Unknown node ID", err))
c.Abort()
return
}
SignRequired(slaveNode.AuthInstance())(c)
}
}