mirror of https://github.com/cloudreve/Cloudreve
parent
865a801fa8
commit
3948ee7f3a
2
assets
2
assets
|
@ -1 +1 @@
|
||||||
Subproject commit e3d3e790f1a44ed38eaa6e2d636867c1b1418983
|
Subproject commit 691e82868d69963d7620e758833ffdbcbf9936b5
|
|
@ -10,9 +10,9 @@ import (
|
||||||
// MasterMetadata 解析主机节点发来请求的包含主机节点信息的元数据
|
// MasterMetadata 解析主机节点发来请求的包含主机节点信息的元数据
|
||||||
func MasterMetadata() gin.HandlerFunc {
|
func MasterMetadata() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
c.Set("MasterSiteID", c.GetHeader("X-Site-Id"))
|
c.Set("MasterSiteID", c.GetHeader("X-Cr-Site-Id"))
|
||||||
c.Set("MasterSiteURL", c.GetHeader("X-Site-Url"))
|
c.Set("MasterSiteURL", c.GetHeader("X-Cr-Site-Url"))
|
||||||
c.Set("MasterVersion", c.GetHeader("X-Cloudreve-Version"))
|
c.Set("MasterVersion", c.GetHeader("X-Cr-Cloudreve-Version"))
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ func UseSlaveAria2Instance(clusterController cluster.Controller) gin.HandlerFunc
|
||||||
|
|
||||||
func SlaveRPCSignRequired(nodePool cluster.Pool) gin.HandlerFunc {
|
func SlaveRPCSignRequired(nodePool cluster.Pool) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
nodeID, err := strconv.ParseUint(c.GetHeader("X-Node-Id"), 10, 64)
|
nodeID, err := strconv.ParseUint(c.GetHeader("X-Cr-Node-Id"), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, serializer.ParamErr("未知的主机节点ID", err))
|
c.JSON(200, serializer.ParamErr("未知的主机节点ID", err))
|
||||||
c.Abort()
|
c.Abort()
|
||||||
|
|
|
@ -22,9 +22,9 @@ func TestMasterMetadata(t *testing.T) {
|
||||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||||
|
|
||||||
c.Request.Header = map[string][]string{
|
c.Request.Header = map[string][]string{
|
||||||
"X-Site-Id": {"expectedSiteID"},
|
"X-Cr-Site-Id": {"expectedSiteID"},
|
||||||
"X-Site-Url": {"expectedSiteURL"},
|
"X-Cr-Site-Url": {"expectedSiteURL"},
|
||||||
"X-Cloudreve-Version": {"expectedMasterVersion"},
|
"X-Cr-Cloudreve-Version": {"expectedMasterVersion"},
|
||||||
}
|
}
|
||||||
masterMetaDataFunc(c)
|
masterMetaDataFunc(c)
|
||||||
siteID, _ := c.Get("MasterSiteID")
|
siteID, _ := c.Get("MasterSiteID")
|
||||||
|
@ -47,7 +47,7 @@ func TestSlaveRPCSignRequired(t *testing.T) {
|
||||||
{
|
{
|
||||||
c, _ := gin.CreateTestContext(rec)
|
c, _ := gin.CreateTestContext(rec)
|
||||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||||
c.Request.Header.Set("X-Node-Id", "unknown")
|
c.Request.Header.Set("X-Cr-Node-Id", "unknown")
|
||||||
slaveRPCSignRequiredFunc(c)
|
slaveRPCSignRequiredFunc(c)
|
||||||
a.True(c.IsAborted())
|
a.True(c.IsAborted())
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ func TestSlaveRPCSignRequired(t *testing.T) {
|
||||||
{
|
{
|
||||||
c, _ := gin.CreateTestContext(rec)
|
c, _ := gin.CreateTestContext(rec)
|
||||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||||
c.Request.Header.Set("X-Node-Id", "38")
|
c.Request.Header.Set("X-Cr-Node-Id", "38")
|
||||||
slaveRPCSignRequiredFunc(c)
|
slaveRPCSignRequiredFunc(c)
|
||||||
a.True(c.IsAborted())
|
a.True(c.IsAborted())
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ func TestSlaveRPCSignRequired(t *testing.T) {
|
||||||
|
|
||||||
c, _ := gin.CreateTestContext(rec)
|
c, _ := gin.CreateTestContext(rec)
|
||||||
c.Request = httptest.NewRequest("POST", "/", nil)
|
c.Request = httptest.NewRequest("POST", "/", nil)
|
||||||
c.Request.Header.Set("X-Node-Id", "38")
|
c.Request.Header.Set("X-Cr-Node-Id", "38")
|
||||||
c.Request = auth.SignRequest(authInstance, c.Request, 0)
|
c.Request = auth.SignRequest(authInstance, c.Request, 0)
|
||||||
slaveRPCSignRequiredFunc(c)
|
slaveRPCSignRequiredFunc(c)
|
||||||
a.False(c.IsAborted())
|
a.False(c.IsAborted())
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/util"
|
"github.com/cloudreve/Cloudreve/v3/pkg/util"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DBScript interface {
|
type DBScript interface {
|
||||||
|
@ -29,7 +30,7 @@ func Register(name string, script DBScript) {
|
||||||
func ListPrefix(prefix string) []string {
|
func ListPrefix(prefix string) []string {
|
||||||
var scripts []string
|
var scripts []string
|
||||||
for name := range availableScripts {
|
for name := range availableScripts {
|
||||||
if name[:len(prefix)] == prefix {
|
if strings.HasPrefix(name, prefix) {
|
||||||
scripts = append(scripts, name)
|
scripts = append(scripts, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ type Auth interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignRequest 对PUT\POST等复杂HTTP请求签名,只会对URI部分、
|
// SignRequest 对PUT\POST等复杂HTTP请求签名,只会对URI部分、
|
||||||
// 请求正文、`X-`开头的header进行签名
|
// 请求正文、`X-Cr-`开头的header进行签名
|
||||||
func SignRequest(instance Auth, r *http.Request, expires int64) *http.Request {
|
func SignRequest(instance Auth, r *http.Request, expires int64) *http.Request {
|
||||||
// 处理有效期
|
// 处理有效期
|
||||||
if expires > 0 {
|
if expires > 0 {
|
||||||
|
@ -69,7 +69,7 @@ func CheckRequest(instance Auth, r *http.Request) error {
|
||||||
func getSignContent(r *http.Request) (rawSignString string) {
|
func getSignContent(r *http.Request) (rawSignString string) {
|
||||||
// 读取所有body正文
|
// 读取所有body正文
|
||||||
var body = []byte{}
|
var body = []byte{}
|
||||||
if _, ok := r.Header["X-Policy"]; !ok {
|
if _, ok := r.Header["X-Cr-Policy"]; !ok {
|
||||||
if r.Body != nil {
|
if r.Body != nil {
|
||||||
body, _ = ioutil.ReadAll(r.Body)
|
body, _ = ioutil.ReadAll(r.Body)
|
||||||
_ = r.Body.Close()
|
_ = r.Body.Close()
|
||||||
|
@ -80,7 +80,7 @@ func getSignContent(r *http.Request) (rawSignString string) {
|
||||||
// 决定要签名的header
|
// 决定要签名的header
|
||||||
var signedHeader []string
|
var signedHeader []string
|
||||||
for k, _ := range r.Header {
|
for k, _ := range r.Header {
|
||||||
if strings.HasPrefix(k, "X-") && k != "X-Filename" {
|
if strings.HasPrefix(k, "X-Cr-") && k != "X-Cr-Filename" {
|
||||||
signedHeader = append(signedHeader, fmt.Sprintf("%s=%s", k, r.Header.Get(k)))
|
signedHeader = append(signedHeader, fmt.Sprintf("%s=%s", k, r.Header.Get(k)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ func TestSignRequest(t *testing.T) {
|
||||||
strings.NewReader("I am body."),
|
strings.NewReader("I am body."),
|
||||||
)
|
)
|
||||||
asserts.NoError(err)
|
asserts.NoError(err)
|
||||||
req.Header["X-Policy"] = []string{"I am Policy"}
|
req.Header["X-Cr-Policy"] = []string{"I am Policy"}
|
||||||
req = SignRequest(General, req, 10)
|
req = SignRequest(General, req, 10)
|
||||||
asserts.NotEmpty(req.Header["Authorization"])
|
asserts.NotEmpty(req.Header["Authorization"])
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ func TestCheckRequest(t *testing.T) {
|
||||||
strings.NewReader("I am body."),
|
strings.NewReader("I am body."),
|
||||||
)
|
)
|
||||||
asserts.NoError(err)
|
asserts.NoError(err)
|
||||||
req.Header["X-Policy"] = []string{"I am Policy"}
|
req.Header["X-Cr-Policy"] = []string{"I am Policy"}
|
||||||
req = SignRequest(General, req, 0)
|
req = SignRequest(General, req, 0)
|
||||||
err = CheckRequest(General, req)
|
err = CheckRequest(General, req)
|
||||||
asserts.NoError(err)
|
asserts.NoError(err)
|
||||||
|
|
|
@ -44,7 +44,7 @@ var CaptchaConfig = &captcha{
|
||||||
var CORSConfig = &cors{
|
var CORSConfig = &cors{
|
||||||
AllowOrigins: []string{"UNSET"},
|
AllowOrigins: []string{"UNSET"},
|
||||||
AllowMethods: []string{"PUT", "POST", "GET", "OPTIONS"},
|
AllowMethods: []string{"PUT", "POST", "GET", "OPTIONS"},
|
||||||
AllowHeaders: []string{"Cookie", "X-Policy", "Authorization", "Content-Length", "Content-Type", "X-Path", "X-FileName"},
|
AllowHeaders: []string{"Cookie", "X-Cr-Policy", "Authorization", "Content-Length", "Content-Type", "X-Path", "X-FileName"},
|
||||||
AllowCredentials: false,
|
AllowCredentials: false,
|
||||||
ExposeHeaders: nil,
|
ExposeHeaders: nil,
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,9 +167,9 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s
|
||||||
handler.Policy.GetUploadURL(),
|
handler.Policy.GetUploadURL(),
|
||||||
file,
|
file,
|
||||||
request.WithHeader(map[string][]string{
|
request.WithHeader(map[string][]string{
|
||||||
"X-Policy": {credential.Policy},
|
"X-Cr-Policy": {credential.Policy},
|
||||||
"X-FileName": {fileName},
|
"X-Cr-FileName": {fileName},
|
||||||
"X-Overwrite": {overwrite},
|
"X-Cr-Overwrite": {overwrite},
|
||||||
}),
|
}),
|
||||||
request.WithContentLength(int64(size)),
|
request.WithContentLength(int64(size)),
|
||||||
request.WithTimeout(time.Duration(0)),
|
request.WithTimeout(time.Duration(0)),
|
||||||
|
@ -332,8 +332,8 @@ func (handler Driver) getUploadCredential(ctx context.Context, policy serializer
|
||||||
// 签名上传策略
|
// 签名上传策略
|
||||||
uploadRequest, _ := http.NewRequest("POST", "/api/v3/slave/upload", nil)
|
uploadRequest, _ := http.NewRequest("POST", "/api/v3/slave/upload", nil)
|
||||||
uploadRequest.Header = map[string][]string{
|
uploadRequest.Header = map[string][]string{
|
||||||
"X-Policy": {policyEncoded},
|
"X-Cr-Policy": {policyEncoded},
|
||||||
"X-Overwrite": {"false"},
|
"X-Cr-Overwrite": {"false"},
|
||||||
}
|
}
|
||||||
auth.SignRequest(handler.AuthInstance, uploadRequest, TTL)
|
auth.SignRequest(handler.AuthInstance, uploadRequest, TTL)
|
||||||
|
|
||||||
|
|
|
@ -97,13 +97,13 @@ func (c HTTPClient) Request(method, target string, body io.Reader, opts ...Optio
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.masterMeta && conf.SystemConfig.Mode == "master" {
|
if options.masterMeta && conf.SystemConfig.Mode == "master" {
|
||||||
req.Header.Add("X-Site-Url", model.GetSiteURL().String())
|
req.Header.Add("X-Cr-Site-Url", model.GetSiteURL().String())
|
||||||
req.Header.Add("X-Site-Id", model.GetSettingByName("siteID"))
|
req.Header.Add("X-Cr-Site-Id", model.GetSettingByName("siteID"))
|
||||||
req.Header.Add("X-Cloudreve-Version", conf.BackendVersion)
|
req.Header.Add("X-Cr-Cloudreve-Version", conf.BackendVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.slaveNodeID != "" && conf.SystemConfig.Mode == "slave" {
|
if options.slaveNodeID != "" && conf.SystemConfig.Mode == "slave" {
|
||||||
req.Header.Add("X-Node-Id", options.slaveNodeID)
|
req.Header.Add("X-Cr-Node-Id", options.slaveNodeID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.contentLength != -1 {
|
if options.contentLength != -1 {
|
||||||
|
|
|
@ -308,8 +308,8 @@ func FileUploadStream(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解码文件名和路径
|
// 解码文件名和路径
|
||||||
fileName, err := url.QueryUnescape(c.Request.Header.Get("X-FileName"))
|
fileName, err := url.QueryUnescape(c.Request.Header.Get("X-Cr-FileName"))
|
||||||
filePath, err := url.QueryUnescape(c.Request.Header.Get("X-Path"))
|
filePath, err := url.QueryUnescape(c.Request.Header.Get("X-Cr-Path"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, ErrorResponse(err))
|
c.JSON(200, ErrorResponse(err))
|
||||||
return
|
return
|
||||||
|
|
|
@ -32,7 +32,7 @@ func SlaveUpload(c *gin.Context) {
|
||||||
fs.Handler = local.Driver{}
|
fs.Handler = local.Driver{}
|
||||||
|
|
||||||
// 从请求中取得上传策略
|
// 从请求中取得上传策略
|
||||||
uploadPolicyRaw := c.GetHeader("X-Policy")
|
uploadPolicyRaw := c.GetHeader("X-Cr-Policy")
|
||||||
if uploadPolicyRaw == "" {
|
if uploadPolicyRaw == "" {
|
||||||
c.JSON(200, serializer.ParamErr("未指定上传策略", nil))
|
c.JSON(200, serializer.ParamErr("未指定上传策略", nil))
|
||||||
return
|
return
|
||||||
|
@ -54,7 +54,7 @@ func SlaveUpload(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解码文件名和路径
|
// 解码文件名和路径
|
||||||
fileName, err := url.QueryUnescape(c.Request.Header.Get("X-FileName"))
|
fileName, err := url.QueryUnescape(c.Request.Header.Get("X-Cr-FileName"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(200, ErrorResponse(err))
|
c.JSON(200, ErrorResponse(err))
|
||||||
return
|
return
|
||||||
|
@ -74,7 +74,7 @@ func SlaveUpload(c *gin.Context) {
|
||||||
fs.Use("AfterValidateFailed", filesystem.HookDeleteTempFile)
|
fs.Use("AfterValidateFailed", filesystem.HookDeleteTempFile)
|
||||||
|
|
||||||
// 是否允许覆盖
|
// 是否允许覆盖
|
||||||
if c.Request.Header.Get("X-Overwrite") == "false" {
|
if c.Request.Header.Get("X-Cr-Overwrite") == "false" {
|
||||||
ctx = context.WithValue(ctx, fsctx.DisableOverwrite, true)
|
ctx = context.WithValue(ctx, fsctx.DisableOverwrite, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ func TestLocalFileUpload(t *testing.T) {
|
||||||
strings.NewReader("2333"),
|
strings.NewReader("2333"),
|
||||||
)
|
)
|
||||||
req.Header.Add("Content-Length", "4")
|
req.Header.Add("Content-Length", "4")
|
||||||
req.Header.Add("X-FileName", "大地的%sfsf")
|
req.Header.Add("X-Cr-FileName", "大地的%sfsf")
|
||||||
return req
|
return req
|
||||||
},
|
},
|
||||||
ExpectCode: 40002,
|
ExpectCode: 40002,
|
||||||
|
@ -87,8 +87,8 @@ func TestLocalFileUpload(t *testing.T) {
|
||||||
strings.NewReader("2333"),
|
strings.NewReader("2333"),
|
||||||
)
|
)
|
||||||
req.Header.Add("Content-Length", "4")
|
req.Header.Add("Content-Length", "4")
|
||||||
req.Header.Add("X-FileName", "TestFileUploadRoute.txt")
|
req.Header.Add("X-Cr-FileName", "TestFileUploadRoute.txt")
|
||||||
req.Header.Add("X-Path", "/")
|
req.Header.Add("X-Cr-Path", "/")
|
||||||
return req
|
return req
|
||||||
},
|
},
|
||||||
ExpectCode: 0,
|
ExpectCode: 0,
|
||||||
|
|
Loading…
Reference in New Issue