Skip to content

Commit

Permalink
feat(webdav): support setting download proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
HFO4 committed Jul 29, 2023
1 parent ad6c6bc commit a174707
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 19 deletions.
5 changes: 5 additions & 0 deletions middleware/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ func WebDAVAuth() gin.HandlerFunc {
return
}

// 用户组已启用WebDAV代理?
if !expectedUser.Group.OptionsSerialized.WebDAVProxy {
webdav.UseProxy = false
}

c.Set("user", &expectedUser)
c.Set("webdav", webdav)
c.Next()
Expand Down
1 change: 1 addition & 0 deletions models/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type GroupOption struct {
RedirectedSource bool `json:"redirected_source,omitempty"`
Aria2BatchSize int `json:"aria2_batch,omitempty"`
AdvanceDelete bool `json:"advance_delete,omitempty"`
WebDAVProxy bool `json:"webdav_proxy,omitempty"`
}

// GetGroupByID 用ID获取用户组
Expand Down
7 changes: 4 additions & 3 deletions models/webdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Webdav struct {
UserID uint `gorm:"unique_index:password_only_on"` // 用户ID
Root string `gorm:"type:text"` // 根目录
Readonly bool `gorm:"type:bool"` // 是否只读
UseProxy bool `gorm:"type:bool"` // 是否进行反代
}

// Create 创建账户
Expand Down Expand Up @@ -41,7 +42,7 @@ func DeleteWebDAVAccountByID(id, uid uint) {
DB.Where("user_id = ? and id = ?", uid, id).Delete(&Webdav{})
}

// UpdateWebDAVAccountReadonlyByID 根据账户ID和UID更新账户的只读性
func UpdateWebDAVAccountReadonlyByID(id, uid uint, readonly bool) {
DB.Model(&Webdav{Model: gorm.Model{ID: id}, UserID: uid}).UpdateColumn("readonly", readonly)
// UpdateWebDAVAccountByID 根据账户ID和UID更新账户
func UpdateWebDAVAccountByID(id, uid uint, updates map[string]interface{}) {
DB.Model(&Webdav{Model: gorm.Model{ID: id}, UserID: uid}).Updates(updates)
}
4 changes: 4 additions & 0 deletions pkg/filesystem/fsctx/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ const (
SlaveSrcPath
// Webdav目标名称
WebdavDstName
// WebDAVCtx WebDAV
WebDAVCtx
// WebDAV反代Url
WebDAVProxyUrlCtx
)
2 changes: 2 additions & 0 deletions pkg/serializer/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type group struct {
WebDAVEnabled bool `json:"webdav"`
SourceBatchSize int `json:"sourceBatch"`
AdvanceDelete bool `json:"advanceDelete"`
AllowWebDAVProxy bool `json:"allowWebDAVProxy"`
}

type tag struct {
Expand Down Expand Up @@ -100,6 +101,7 @@ func BuildUser(user model.User) User {
ShareDownload: user.Group.OptionsSerialized.ShareDownload,
CompressEnabled: user.Group.OptionsSerialized.ArchiveTask,
WebDAVEnabled: user.Group.WebDAVEnabled,
AllowWebDAVProxy: user.Group.OptionsSerialized.WebDAVProxy,
SourceBatchSize: user.Group.OptionsSerialized.SourceBatchSize,
AdvanceDelete: user.Group.OptionsSerialized.AdvanceDelete,
},
Expand Down
36 changes: 35 additions & 1 deletion pkg/webdav/webdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"net/http"
"net/http/httputil"
"net/url"
"path"
"strconv"
Expand Down Expand Up @@ -241,6 +242,23 @@ func (h *Handler) handleOptions(w http.ResponseWriter, r *http.Request, fs *file
return 0, nil
}

var proxy = &httputil.ReverseProxy{
Director: func(request *http.Request) {
if target, ok := request.Context().Value(fsctx.WebDAVProxyUrlCtx).(*url.URL); ok {
request.URL.Scheme = target.Scheme
request.URL.Host = target.Host
request.URL.Path = target.Path
request.URL.RawPath = target.RawPath
request.URL.RawQuery = target.RawQuery
request.Host = target.Host
request.Header.Del("Authorization")
}
},
ErrorHandler: func(writer http.ResponseWriter, request *http.Request, err error) {
writer.WriteHeader(http.StatusInternalServerError)
},
}

// OK
func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request, fs *filesystem.FileSystem) (status int, err error) {
defer fs.Recycle()
Expand Down Expand Up @@ -279,7 +297,23 @@ func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request, fs *
return 0, nil
}

http.Redirect(w, r, rs.URL, 301)
if application, ok := r.Context().Value(fsctx.WebDAVCtx).(*model.Webdav); ok && application.UseProxy {
target, err := url.Parse(rs.URL)
if err != nil {
return http.StatusInternalServerError, err
}

r = r.Clone(context.WithValue(r.Context(), fsctx.WebDAVProxyUrlCtx, target))
// 忽略反向代理在传输错误时报错
defer func() {
if err := recover(); err != nil && err != http.ErrAbortHandler {
panic(err)
}
}()
proxy.ServeHTTP(w, r)
} else {
http.Redirect(w, r, rs.URL, 301)
}

return 0, nil
}
Expand Down
11 changes: 8 additions & 3 deletions routers/controllers/webdav.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package controllers

import (
"context"
model "github.com/cloudreve/Cloudreve/v3/models"
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem"
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx"
"github.com/cloudreve/Cloudreve/v3/pkg/util"
"github.com/cloudreve/Cloudreve/v3/pkg/webdav"
"github.com/cloudreve/Cloudreve/v3/service/setting"
Expand Down Expand Up @@ -49,6 +51,9 @@ func ServeWebDAV(c *gin.Context) {
return
}
}

// 更新Context
c.Request = c.Request.WithContext(context.WithValue(c.Request.Context(), fsctx.WebDAVCtx, application))
}

handler.ServeHTTP(c.Writer, c.Request, fs)
Expand Down Expand Up @@ -76,9 +81,9 @@ func DeleteWebDAVAccounts(c *gin.Context) {
}
}

// UpdateWebDAVAccountsReadonly 更改WebDAV账户只读性
func UpdateWebDAVAccountsReadonly(c *gin.Context) {
var service setting.WebDAVAccountUpdateReadonlyService
// UpdateWebDAVAccounts 更改WebDAV账户只读性和是否使用代理服务
func UpdateWebDAVAccounts(c *gin.Context) {
var service setting.WebDAVAccountUpdateService
if err := c.ShouldBindJSON(&service); err == nil {
res := service.Update(c, CurrentUser(c))
c.JSON(200, res)
Expand Down
4 changes: 2 additions & 2 deletions routers/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -721,8 +721,8 @@ func InitMasterRouter() *gin.Engine {
webdav.POST("accounts", controllers.CreateWebDAVAccounts)
// 删除账号
webdav.DELETE("accounts/:id", controllers.DeleteWebDAVAccounts)
// 更新账号可读性
webdav.PATCH("accounts", controllers.UpdateWebDAVAccountsReadonly)
// 更新账号可读性和是否使用代理服务
webdav.PATCH("accounts", controllers.UpdateWebDAVAccounts)
}

}
Expand Down
26 changes: 16 additions & 10 deletions service/setting/webdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ type WebDAVAccountCreateService struct {
Name string `json:"name" binding:"required,min=1,max=255"`
}

// WebDAVAccountUpdateReadonlyService WebDAV 修改只读性服务
type WebDAVAccountUpdateReadonlyService struct {
ID uint `json:"id" binding:"required,min=1"`
Readonly bool `json:"readonly"`
// WebDAVAccountUpdateService WebDAV 修改只读性和是否使用代理服务
type WebDAVAccountUpdateService struct {
ID uint `json:"id" binding:"required,min=1"`
Readonly *bool `json:"readonly" binding:"required_without=UseProxy"`
UseProxy *bool `json:"use_proxy" binding:"required_without=Readonly"`
}

// WebDAVMountCreateService WebDAV 挂载创建服务
Expand Down Expand Up @@ -62,12 +63,17 @@ func (service *WebDAVAccountService) Delete(c *gin.Context, user *model.User) se
return serializer.Response{}
}

// Update 修改WebDAV账户的只读性
func (service *WebDAVAccountUpdateReadonlyService) Update(c *gin.Context, user *model.User) serializer.Response {
model.UpdateWebDAVAccountReadonlyByID(service.ID, user.ID, service.Readonly)
return serializer.Response{Data: map[string]bool{
"readonly": service.Readonly,
}}
// Update 修改WebDAV账户只读性和是否使用代理服务
func (service *WebDAVAccountUpdateService) Update(c *gin.Context, user *model.User) serializer.Response {
var updates = make(map[string]interface{})
if service.Readonly != nil {
updates["readonly"] = *service.Readonly
}
if service.UseProxy != nil {
updates["use_proxy"] = *service.UseProxy
}
model.UpdateWebDAVAccountByID(service.ID, user.ID, updates)
return serializer.Response{Data: updates}
}

// Accounts 列出WebDAV账号
Expand Down

0 comments on commit a174707

Please sign in to comment.