From b51b4e083d237612be878a37c104de17725270d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=87=89?= <927625802@qq.com> Date: Sat, 4 Sep 2021 19:52:56 +0800 Subject: [PATCH] :sparkles: add proxy --- bootstrap/config.go | 2 + conf.yml.example | 1 + conf/config.go | 15 +++---- conf/const.go | 1 + server/controllers/proxy.go | 84 +++++++++++++++++++++++++++++++++++++ server/router.go | 1 + utils/check.go | 10 +++++ 7 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 server/controllers/proxy.go diff --git a/bootstrap/config.go b/bootstrap/config.go index 788db079..4a5226b6 100644 --- a/bootstrap/config.go +++ b/bootstrap/config.go @@ -31,6 +31,7 @@ func ReadConf(config string) bool { log.Debugf("config:%+v", conf.Conf) conf.Conf.Info.Roots = utils.GetNames() conf.Origins = strings.Split(conf.Conf.Server.SiteUrl, ",") + conf.AllowProxies = strings.Split(conf.Conf.Server.AllowProxy,",") return true } func Write(path string) bool { @@ -63,6 +64,7 @@ server: static: dist site_url: '*' password: password #用于重建目录 + allow_proxy: vtt ali_drive: api_url: https://api.aliyundrive.com/v2 max_files_count: 100 diff --git a/conf.yml.example b/conf.yml.example index 2509e681..cb081584 100644 --- a/conf.yml.example +++ b/conf.yml.example @@ -17,6 +17,7 @@ server: static: dist site_url: '*' password: password #用于重建目录 + allow_proxy: vtt #允许代理的后缀,以,分割 ali_drive: api_url: https://api.aliyundrive.com/v2 max_files_count: 50 #重建目录时每次请求的文件 diff --git a/conf/config.go b/conf/config.go index b65070d7..d0051b64 100644 --- a/conf/config.go +++ b/conf/config.go @@ -31,13 +31,14 @@ type Config struct { } `yaml:"preview" json:"preview"` } `yaml:"info"` Server struct { - Address string `yaml:"address"` - Port string `yaml:"port"` //端口 - Search bool `yaml:"search"` //允许搜索 - Download bool `yaml:"download"` //允许下载 - Static string `yaml:"static"` - SiteUrl string `yaml:"site_url"` //网站url - Password string `yaml:"password"` + Address string `yaml:"address"` + Port string `yaml:"port"` //端口 + Search bool `yaml:"search"` //允许搜索 + Download bool `yaml:"download"` //允许下载 + Static string `yaml:"static"` + SiteUrl string `yaml:"site_url"` //网站url + Password string `yaml:"password"` + AllowProxy string `yaml:"allow_proxy"` // 允许代理的后缀 } `yaml:"server"` AliDrive struct { ApiUrl string `yaml:"api_url"` //阿里云盘api diff --git a/conf/const.go b/conf/const.go index 2e953d35..f04fd020 100644 --- a/conf/const.go +++ b/conf/const.go @@ -17,6 +17,7 @@ var ( DB *gorm.DB Origins []string // allow origins + AllowProxies []string ) var Conf = new(Config) diff --git a/server/controllers/proxy.go b/server/controllers/proxy.go new file mode 100644 index 00000000..fce54a0d --- /dev/null +++ b/server/controllers/proxy.go @@ -0,0 +1,84 @@ +package controllers + +import ( + "github.com/Xhofe/alist/alidrive" + "github.com/Xhofe/alist/conf" + "github.com/Xhofe/alist/server/models" + "github.com/Xhofe/alist/utils" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" + "net/http/httputil" + url2 "net/url" + "path/filepath" + "strings" +) + +type ProxyReq struct { + Password string `form:"pw"` +} + +// Down handle download request +func Proxy(c *gin.Context) { + if !conf.Conf.Server.Download { + c.JSON(200, MetaResponse(403, "不允许下载或预览.")) + return + } + filePath := c.Param("path")[1:] + if !utils.HasSuffixes(filePath, conf.AllowProxies) { + c.JSON(200, MetaResponse(403, "该类型文件不允许代理.")) + return + } + var down ProxyReq + if err := c.ShouldBindQuery(&down); err != nil { + c.JSON(200, MetaResponse(400, "错误的请求.")) + return + } + log.Debugf("down:%s", filePath) + dir, name := filepath.Split(filePath) + fileModel, err := models.GetFileByDirAndName(dir, name) + if err != nil { + if fileModel == nil { + c.JSON(200, MetaResponse(404, "文件不存在.")) + return + } + c.JSON(200, MetaResponse(500, err.Error())) + return + } + if fileModel.Password != "" && down.Password != utils.Get16MD5Encode(fileModel.Password) { + if down.Password == "" { + c.JSON(200, MetaResponse(401, "需要密码.")) + } else { + c.JSON(200, MetaResponse(401, "密码错误.")) + } + return + } + if fileModel.Type == "folder" { + c.JSON(200, MetaResponse(406, "无法代理目录.")) + return + } + drive := utils.GetDriveByName(strings.Split(filePath, "/")[0]) + if drive == nil { + c.JSON(200, MetaResponse(500, "找不到drive.")) + return + } + file, err := alidrive.GetDownLoadUrl(fileModel.FileId, drive) + if err != nil { + c.JSON(200, MetaResponse(500, err.Error())) + return + } + url, err := url2.Parse(file.Url) + if err != nil { + c.JSON(200, MetaResponse(500, err.Error())) + return + } + target, err := url2.Parse("https://" + url.Host) + if err != nil { + c.JSON(200, MetaResponse(500, err.Error())) + return + } + proxy := httputil.NewSingleHostReverseProxy(target) + c.Request.URL = url + c.Request.Host = url.Host + c.Request.Header.Del("Origin") + proxy.ServeHTTP(c.Writer, c.Request) +} diff --git a/server/router.go b/server/router.go index d597e14e..d6de1c8e 100644 --- a/server/router.go +++ b/server/router.go @@ -34,5 +34,6 @@ func InitApiRouter(engine *gin.Engine) { apiV2.POST("/video_preview/:drive", controllers.VideoPreview) apiV2.POST("/video_preview_play_info/:drive", controllers.VideoPreviewPlayInfo) engine.GET("/d/*path", controllers.Down) + engine.GET("/p/*path",controllers.Proxy) } } diff --git a/utils/check.go b/utils/check.go index 06122bc6..4274eea3 100644 --- a/utils/check.go +++ b/utils/check.go @@ -56,3 +56,13 @@ func VersionCompare(version1, version2 string) int { } return 0 } + +// HasSuffixes check string has suffixes in string array. +func HasSuffixes(str string, suffixes []string) bool { + for _, suffix := range suffixes { + if strings.HasSuffix(str,suffix) { + return true + } + } + return false +} \ No newline at end of file