🎨 change link interface

pull/548/head v2.0.1
微凉 2021-12-09 19:24:34 +08:00
parent b36eaf08f0
commit a295e7024a
14 changed files with 189 additions and 146 deletions

View File

@ -1,8 +1,3 @@
// We support the GET, POST, HEAD, and OPTIONS methods from any origin,
// and allow any header on requests. These headers must be present
// on all responses to all CORS preflight requests. In practice, this means
// all responses to OPTIONS requests.
const HOST = "YOUR_HOST";
const TOKEN = "YOUR_TOKEN";
@ -26,8 +21,6 @@ async function handleRequest(request) {
JSON.stringify({
code: 401,
message: `sign mismatch`,
you: sign,
right: right,
}),
{
headers: {
@ -49,18 +42,17 @@ async function handleRequest(request) {
path: decodeURI(path),
}),
});
let data = await resp.json();
if (data.code != 200) {
return new Response(JSON.stringify(data));
let res = await resp.json();
if (res.code !== 200) {
return new Response(JSON.stringify(res));
}
let headers = {};
if (data.data.header) {
headers[data.data.header.name] = data.data.header.value;
request = new Request(res.data.url, request);
if (res.data.headers) {
for(const header of res.data.headers){
request.headers.set(header.name, header.value);
}
}
let response = await fetch(data.data.url, {
method: "GET",
headers: headers,
});
let response = await fetch(request);
// Recreate the response so we can modify the headers
response = new Response(response.body, response);

View File

@ -119,10 +119,10 @@ func (driver Pan123) Files(path string, account *model.Account) ([]model.File, e
return files, nil
}
func (driver Pan123) Link(path string, account *model.Account) (string, error) {
func (driver Pan123) Link(path string, account *model.Account) (*base.Link, error) {
file, err := driver.GetFile(utils.ParsePath(path), account)
if err != nil {
return "", err
return nil, err
}
var resp Pan123DownResp
_, err = pan123Client.R().SetResult(&resp).SetHeader("authorization", "Bearer "+account.AccessToken).
@ -136,32 +136,35 @@ func (driver Pan123) Link(path string, account *model.Account) (string, error) {
"type": file.Type,
}).Post("https://www.123pan.com/api/file/download_info")
if err != nil {
return "", err
return nil, err
}
if resp.Code != 0 {
if resp.Code == 401 {
err := driver.Login(account)
if err != nil {
return "", err
return nil, err
}
return driver.Link(path, account)
}
return "", fmt.Errorf(resp.Message)
return nil, fmt.Errorf(resp.Message)
}
u, err := url.Parse(resp.Data.DownloadUrl)
if err != nil {
return "", err
return nil, err
}
u_ := fmt.Sprintf("https://%s%s", u.Host, u.Path)
res, err := base.NoRedirectClient.R().SetQueryParamsFromValues(u.Query()).Get(u_)
if err != nil {
return "", err
return nil, err
}
log.Debug(res.String())
link := base.Link{}
if res.StatusCode() == 302 {
return res.Header().Get("location"), nil
link.Url = res.Header().Get("location")
}else {
link.Url = resp.Data.DownloadUrl
}
return resp.Data.DownloadUrl, nil
return &link, nil
}
func (driver Pan123) Path(path string, account *model.Account) (*model.File, []model.File, error) {
@ -171,8 +174,12 @@ func (driver Pan123) Path(path string, account *model.Account) (*model.File, []m
if err != nil {
return nil, nil, err
}
if file.Type != conf.FOLDER {
file.Url, _ = driver.Link(path, account)
if !file.IsDir() {
link, err := driver.Link(path, account)
if err != nil {
return nil, nil, err
}
file.Url = link.Url
return file, nil, nil
}
files, err := driver.Files(path, account)

View File

@ -127,17 +127,17 @@ func (driver Cloud189) Files(path string, account *model.Account) ([]model.File,
return files, nil
}
func (driver Cloud189) Link(path string, account *model.Account) (string, error) {
func (driver Cloud189) Link(path string, account *model.Account) (*base.Link, error) {
file, err := driver.File(utils.ParsePath(path), account)
if err != nil {
return "", err
return nil, err
}
if file.Type == conf.FOLDER {
return "", base.ErrNotFile
return nil, base.ErrNotFile
}
client, ok := client189Map[account.Name]
if !ok {
return "", fmt.Errorf("can't find [%s] client", account.Name)
return nil, fmt.Errorf("can't find [%s] client", account.Name)
}
var e Cloud189Error
var resp Cloud189Down
@ -148,28 +148,31 @@ func (driver Cloud189) Link(path string, account *model.Account) (string, error)
"fileId": file.Id,
}).Get("https://cloud.189.cn/api/open/file/getFileDownloadUrl.action")
if err != nil {
return "", err
return nil, err
}
if e.ErrorCode != "" {
if e.ErrorCode == "InvalidSessionKey" {
err = driver.Login(account)
if err != nil {
return "", err
return nil, err
}
return driver.Link(path, account)
}
}
if resp.ResCode != 0 {
return "", fmt.Errorf(resp.ResMessage)
return nil, fmt.Errorf(resp.ResMessage)
}
res, err := base.NoRedirectClient.R().Get(resp.FileDownloadUrl)
if err != nil {
return "", err
return nil, err
}
link := base.Link{}
if res.StatusCode() == 302 {
return res.Header().Get("location"), nil
link.Url = res.Header().Get("location")
}else {
link.Url = resp.FileDownloadUrl
}
return resp.FileDownloadUrl, nil
return &link, nil
}
func (driver Cloud189) Path(path string, account *model.Account) (*model.File, []model.File, error) {
@ -179,8 +182,12 @@ func (driver Cloud189) Path(path string, account *model.Account) (*model.File, [
if err != nil {
return nil, nil, err
}
if file.Type != conf.FOLDER {
file.Url, _ = driver.Link(path, account)
if !file.IsDir() {
link, err := driver.Link(path, account)
if err != nil {
return nil, nil, err
}
file.Url = link.Url
return file, nil, nil
}
files, err := driver.Files(path, account)

View File

@ -158,10 +158,10 @@ func (driver AliDrive) Files(path string, account *model.Account) ([]model.File,
return files, nil
}
func (driver AliDrive) Link(path string, account *model.Account) (string, error) {
func (driver AliDrive) Link(path string, account *model.Account) (*base.Link, error) {
file, err := driver.File(path, account)
if err != nil {
return "", err
return nil, err
}
var resp base.Json
var e AliRespError
@ -174,21 +174,23 @@ func (driver AliDrive) Link(path string, account *model.Account) (string, error)
"expire_sec": 14400,
}).Post("https://api.aliyundrive.com/v2/file/get_download_url")
if err != nil {
return "", err
return nil, err
}
if e.Code != "" {
if e.Code == "AccessTokenInvalid" {
err = driver.RefreshToken(account)
if err != nil {
return "", err
return nil, err
} else {
_ = model.SaveAccount(account)
return driver.Link(path, account)
}
}
return "", fmt.Errorf("%s", e.Message)
return nil, fmt.Errorf("%s", e.Message)
}
return resp["url"].(string), nil
return &base.Link{
Url: resp["url"].(string),
}, nil
}
func (driver AliDrive) Path(path string, account *model.Account) (*model.File, []model.File, error) {
@ -198,8 +200,12 @@ func (driver AliDrive) Path(path string, account *model.Account) (*model.File, [
if err != nil {
return nil, nil, err
}
if file.Type != conf.FOLDER {
file.Url, _ = driver.Link(path, account)
if !file.IsDir() {
link, err := driver.Link(path, account)
if err != nil {
return nil, nil, err
}
file.Url = link.Url
return file, nil, nil
}
files, err := driver.Files(path, account)
@ -414,20 +420,20 @@ func (driver AliDrive) Upload(file *model.FileStream, account *model.Account) er
if DEFAULT < byteSize {
byteSize = DEFAULT
}
log.Debugf("%d,%d",byteSize,finish)
log.Debugf("%d,%d", byteSize, finish)
byteData := make([]byte, byteSize)
n, err := io.ReadFull(file, byteData)
//n, err := file.Read(byteData)
//byteData, err := io.ReadAll(file)
//n := len(byteData)
log.Debug(err,n)
log.Debug(err, n)
if err != nil {
return err
}
finish += uint64(n)
req,err := http.NewRequest("PUT", resp.PartInfoList[i].UploadUrl, bytes.NewBuffer(byteData))
req, err := http.NewRequest("PUT", resp.PartInfoList[i].UploadUrl, bytes.NewBuffer(byteData))
if err != nil {
return err
}
@ -445,13 +451,13 @@ func (driver AliDrive) Upload(file *model.FileStream, account *model.Account) er
//log.Debugf("put to %s : %d,%s", resp.PartInfoList[i].UploadUrl, res.StatusCode(),res.String())
}
var resp2 base.Json
_,err = aliClient.R().SetResult(&resp2).SetError(&e).
_, err = aliClient.R().SetResult(&resp2).SetError(&e).
SetHeader("authorization", "Bearer\t"+account.AccessToken).
SetBody(base.Json{
"drive_id": account.DriveId,
"file_id": resp.FileId,
"upload_id": resp.UploadId,
}).Post("https://api.aliyundrive.com/v2/file/complete")
"drive_id": account.DriveId,
"file_id": resp.FileId,
"upload_id": resp.UploadId,
}).Post("https://api.aliyundrive.com/v2/file/complete")
if e.Code != "" {
//if e.Code == "AccessTokenInvalid" {
// err = driver.RefreshToken(account)

View File

@ -101,14 +101,16 @@ func (driver Alist) Files(path string, account *model.Account) ([]model.File, er
return files, nil
}
func (driver Alist) Link(path string, account *model.Account) (string, error) {
func (driver Alist) Link(path string, account *model.Account) (*base.Link, error) {
path = utils.ParsePath(path)
name := utils.Base(path)
flag := "d"
if utils.GetFileType(filepath.Ext(path)) == conf.TEXT {
flag = "p"
}
return fmt.Sprintf("%s/%s%s?sign=%s", account.SiteUrl, flag, path, utils.SignWithToken(name, conf.Token)), nil
link := base.Link{}
link.Url = fmt.Sprintf("%s/%s%s?sign=%s", account.SiteUrl, flag, path, utils.SignWithToken(name, conf.Token))
return &link, nil
}
func (driver Alist) Path(path string, account *model.Account) (*model.File, []model.File, error) {

View File

@ -9,9 +9,9 @@ import (
)
type DriverConfig struct {
Name string
OnlyProxy bool
NeedHeader bool
Name string
OnlyProxy bool
NoLink bool // 必须本机返回的
}
type Driver interface {
@ -20,7 +20,7 @@ type Driver interface {
Save(account *model.Account, old *model.Account) error
File(path string, account *model.Account) (*model.File, error)
Files(path string, account *model.Account) ([]model.File, error)
Link(path string, account *model.Account) (string, error)
Link(path string, account *model.Account) (*Link, error)
Path(path string, account *model.Account) (*model.File, []model.File, error)
Proxy(c *gin.Context, account *model.Account)
Preview(path string, account *model.Account) (interface{}, error)
@ -84,13 +84,16 @@ func GetDrivers() map[string][]Item {
},
}, v.Items()...)
}
res[k] = append(res[k], Item{
Name: "proxy_url",
Label: "proxy_url",
Type: TypeString,
Required: false,
Description: "proxy url",
})
// 不支持给本地文件添加中转
if v.Config().Name != "Native" {
res[k] = append(res[k], Item{
Name: "proxy_url",
Label: "proxy_url",
Type: TypeString,
Required: false,
Description: "proxy url",
})
}
}
return res
}

View File

@ -25,3 +25,13 @@ type TokenResp struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
}
type Header struct{
Name string `json:"name"`
Value string `json:"value"`
}
type Link struct {
Url string `json:"url"`
Headers []Header `json:"headers"`
}

View File

@ -17,7 +17,6 @@ func (driver GoogleDrive) Config() base.DriverConfig {
return base.DriverConfig{
Name: "GoogleDrive",
OnlyProxy: true,
NeedHeader: true,
}
}
@ -117,31 +116,40 @@ func (driver GoogleDrive) Files(path string, account *model.Account) ([]model.Fi
return files, nil
}
func (driver GoogleDrive) Link(path string, account *model.Account) (string, error) {
func (driver GoogleDrive) Link(path string, account *model.Account) (*base.Link, error) {
file, err := driver.File(path, account)
if err != nil {
return "", err
return nil, err
}
if file.Type == conf.FOLDER {
return "", base.ErrNotFile
return nil, base.ErrNotFile
}
link := fmt.Sprintf("https://www.googleapis.com/drive/v3/files/%s?includeItemsFromAllDrives=true&supportsAllDrives=true", file.Id)
url := fmt.Sprintf("https://www.googleapis.com/drive/v3/files/%s?includeItemsFromAllDrives=true&supportsAllDrives=true", file.Id)
var e GoogleError
_, _ = googleClient.R().SetError(&e).
SetHeader("Authorization", "Bearer "+account.AccessToken).
Get(link)
Get(url)
if e.Error.Code != 0 {
if e.Error.Code == 401 {
err = driver.RefreshToken(account)
if err != nil {
_ = model.SaveAccount(account)
return "", err
return nil, err
}
return driver.Link(path, account)
}
return "", fmt.Errorf("%s: %v", e.Error.Message, e.Error.Errors)
return nil, fmt.Errorf("%s: %v", e.Error.Message, e.Error.Errors)
}
return link + "&alt=media", nil
link := base.Link{
Url: url + "&alt=media",
Headers: []base.Header{
{
Name: "Authorization",
Value: "Bearer " + account.AccessToken,
},
},
}
return &link, nil
}
func (driver GoogleDrive) Path(path string, account *model.Account) (*model.File, []model.File, error) {

View File

@ -114,24 +114,27 @@ func (driver Lanzou) Files(path string, account *model.Account) ([]model.File, e
return files, nil
}
func (driver Lanzou) Link(path string, account *model.Account) (string, error) {
func (driver Lanzou) Link(path string, account *model.Account) (*base.Link, error) {
file, err := driver.File(path, account)
if err != nil {
return "", err
return nil, err
}
log.Debugf("down file: %+v", file)
downId := file.Id
if account.OnedriveType == "cookie" {
downId, err = driver.GetDownPageId(file.Id, account)
if err != nil {
return "", err
return nil, err
}
}
link, err := driver.GetLink(downId)
url, err := driver.GetLink(downId)
if err != nil {
return "", err
return nil, err
}
return link, nil
link := base.Link{
Url: url,
}
return &link, nil
}
func (driver Lanzou) Path(path string, account *model.Account) (*model.File, []model.File, error) {
@ -141,8 +144,12 @@ func (driver Lanzou) Path(path string, account *model.Account) (*model.File, []m
if err != nil {
return nil, nil, err
}
if file.Type != conf.FOLDER {
file.Url, _ = driver.Link(path, account)
if !file.IsDir() {
link, err := driver.Link(path, account)
if err != nil {
return nil, nil, err
}
file.Url = link.Url
return file, nil, nil
}
files, err := driver.Files(path, account)

View File

@ -21,6 +21,7 @@ func (driver Native) Config() base.DriverConfig {
return base.DriverConfig{
Name: "Native",
OnlyProxy: true,
NoLink: true,
}
}
@ -122,16 +123,19 @@ func (driver Native) Files(path string, account *model.Account) ([]model.File, e
return files, nil
}
func (driver Native) Link(path string, account *model.Account) (string, error) {
func (driver Native) Link(path string, account *model.Account) (*base.Link, error) {
fullPath := filepath.Join(account.RootFolder, path)
s, err := os.Stat(fullPath)
if err != nil {
return "", err
return nil, err
}
if s.IsDir() {
return "", fmt.Errorf("can't down folder")
return nil, base.ErrNotFile
}
return fullPath, nil
link := base.Link{
Url: fullPath,
}
return &link, nil
}
func (driver Native) Path(path string, account *model.Account) (*model.File, []model.File, error) {
@ -140,7 +144,7 @@ func (driver Native) Path(path string, account *model.Account) (*model.File, []m
if err != nil {
return nil, nil, err
}
if file.Type != conf.FOLDER {
if !file.IsDir() {
//file.Url, _ = driver.Link(path, account)
return file, nil, nil
}
@ -205,7 +209,7 @@ func (driver Native) Delete(path string, account *model.Account) error {
func (driver Native) Upload(file *model.FileStream, account *model.Account) error {
fullPath := filepath.Join(account.RootFolder, file.ParentPath, file.Name)
_, err := driver.File(filepath.Join(file.ParentPath,file.Name), account)
_, err := driver.File(filepath.Join(file.ParentPath, file.Name), account)
if err == nil {
// TODO overwrite?
}

View File

@ -173,15 +173,18 @@ func (driver Onedrive) Files(path string, account *model.Account) ([]model.File,
return files, nil
}
func (driver Onedrive) Link(path string, account *model.Account) (string, error) {
func (driver Onedrive) Link(path string, account *model.Account) (*base.Link, error) {
file, err := driver.GetFile(account, path)
if err != nil {
return "", err
return nil, err
}
if file.File.MimeType == "" {
return "", fmt.Errorf("can't down folder")
return nil, base.ErrNotFile
}
return file.Url, nil
link := base.Link{
Url: file.Url,
}
return &link, nil
}
func (driver Onedrive) Path(path string, account *model.Account) (*model.File, []model.File, error) {
@ -190,7 +193,7 @@ func (driver Onedrive) Path(path string, account *model.Account) (*model.File, [
if err != nil {
return nil, nil, err
}
if file.Type != conf.FOLDER {
if !file.IsDir() {
//file.Url, _ = driver.Link(path, account)
return file, nil, nil
}

View File

@ -3,6 +3,7 @@ package controllers
import (
"fmt"
"github.com/Xhofe/alist/conf"
"github.com/Xhofe/alist/drivers/base"
"github.com/Xhofe/alist/server/common"
"github.com/Xhofe/alist/utils"
"github.com/gin-gonic/gin"
@ -34,7 +35,7 @@ func Down(c *gin.Context) {
common.ErrorResp(c, err, 500)
return
}
c.Redirect(302, link)
c.Redirect(302, link.Url)
return
}
@ -71,7 +72,7 @@ func Proxy(c *gin.Context) {
if account.Type == "Native" {
// 对于名称为index.html的文件需要特殊处理
if utils.Base(rawPath) == "index.html" {
file, err := os.Open(link)
file, err := os.Open(link.Url)
if err != nil {
common.ErrorResp(c, err, 500)
return
@ -79,7 +80,7 @@ func Proxy(c *gin.Context) {
defer func() {
_ = file.Close()
}()
fileStat, err := os.Stat(link)
fileStat, err := os.Stat(link.Url)
if err != nil {
common.ErrorResp(c, err, 500)
return
@ -87,7 +88,7 @@ func Proxy(c *gin.Context) {
http.ServeContent(c.Writer, c.Request, utils.Base(rawPath), fileStat.ModTime(), file)
return
}
c.File(link)
c.File(link.Url)
return
} else {
if utils.GetFileType(filepath.Ext(rawPath)) == conf.TEXT {
@ -97,13 +98,13 @@ func Proxy(c *gin.Context) {
driver.Proxy(c, account)
r := c.Request
w := c.Writer
target, err := url.Parse(link)
target, err := url.Parse(link.Url)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
protocol := "http://"
if strings.HasPrefix(link, "https://") {
if strings.HasPrefix(link.Url, "https://") {
protocol = "https://"
}
targetHost, err := url.Parse(fmt.Sprintf("%s%s", protocol, target.Host))
@ -121,8 +122,8 @@ func init() {
client.SetRetryCount(3)
}
func Text(c *gin.Context, link string) {
res, err := client.R().Get(link)
func Text(c *gin.Context, link *base.Link) {
res, err := client.R().Get(link.Url)
if err != nil {
common.ErrorResp(c, err, 500)
return

View File

@ -3,6 +3,7 @@ package controllers
import (
"fmt"
"github.com/Xhofe/alist/conf"
"github.com/Xhofe/alist/drivers/base"
"github.com/Xhofe/alist/model"
"github.com/Xhofe/alist/server/common"
"github.com/Xhofe/alist/utils"
@ -42,7 +43,7 @@ func Path(c *gin.Context) {
if driver.Config().OnlyProxy || account.Proxy {
if account.ProxyUrl != "" {
file.Url = fmt.Sprintf("%s%s?sign=%s", account.ProxyUrl, req.Path, utils.SignWithToken(file.Name, conf.Token))
}else {
} else {
file.Url = fmt.Sprintf("//%s/d%s", c.Request.Host, req.Path)
}
}
@ -71,7 +72,7 @@ func Path(c *gin.Context) {
}
}
// 返回真实的链接,非中转
// 返回真实的链接,且携带头,只提供给中转程序使用
func Link(c *gin.Context) {
var req common.PathReq
if err := c.ShouldBind(&req); err != nil {
@ -92,25 +93,13 @@ func Link(c *gin.Context) {
common.ErrorResp(c, err, 500)
return
}
if driver.Config().NeedHeader {
common.SuccessResp(c, gin.H{
"url": link,
"header": gin.H{
"name": "Authorization",
"value": "Bearer " + account.AccessToken,
},
})
return
}
if driver.Config().OnlyProxy {
common.SuccessResp(c, gin.H{
"url": fmt.Sprintf("//%s/d%s", c.Request.Host, req.Path),
if driver.Config().NoLink {
common.SuccessResp(c, base.Link{
Url: fmt.Sprintf("//%s/d%s?sign=%s", c.Request.Host, req.Path, utils.SignWithToken(utils.Base(rawPath), conf.Token)),
})
return
} else {
common.SuccessResp(c, gin.H{
"url": link,
})
common.SuccessResp(c, link)
return
}
}

View File

@ -80,26 +80,26 @@ func (fs *FileSystem) Files(rawPath string) ([]model.File, error) {
return driver.Files(path_, account)
}
func GetPW(path string, name string) string {
if !conf.CheckDown {
return ""
}
meta, err := model.GetMetaByPath(path)
if err == nil {
if meta.Password != "" {
return utils.SignWithPassword(name, meta.Password)
}
return ""
} else {
if !conf.CheckParent {
return ""
}
if path == "/" {
return ""
}
return GetPW(utils.Dir(path), name)
}
}
//func GetPW(path string, name string) string {
// if !conf.CheckDown {
// return ""
// }
// meta, err := model.GetMetaByPath(path)
// if err == nil {
// if meta.Password != "" {
// return utils.SignWithPassword(name, meta.Password)
// }
// return ""
// } else {
// if !conf.CheckParent {
// return ""
// }
// if path == "/" {
// return ""
// }
// return GetPW(utils.Dir(path), name)
// }
//}
func (fs *FileSystem) Link(r *http.Request, rawPath string) (string, error) {
rawPath = utils.ParsePath(rawPath)
@ -119,11 +119,15 @@ func (fs *FileSystem) Link(r *http.Request, rawPath string) (string, error) {
if driver.Config().OnlyProxy || account.WebdavProxy {
link = fmt.Sprintf("%s://%s/p%s", protocol, r.Host, rawPath)
if conf.CheckDown {
pw := GetPW(utils.Dir(rawPath), utils.Base(rawPath))
link += "?pw" + pw
sign := utils.SignWithToken(utils.Base(rawPath), conf.Token)
link += "?sign" + sign
}
} else {
link, err = driver.Link(path_, account)
link_, err := driver.Link(path_, account)
if err != nil {
return "", err
}
link = link_.Url
}
log.Debugf("webdav get link: %s", link)
return link, err