2020-11-13 15:51:07 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2020-11-13 15:51:07 +03:00
2021-06-09 02:33:54 +03:00
package web
2020-11-13 15:51:07 +03:00
import (
"errors"
"fmt"
"net/http"
"os"
"path"
"strings"
2020-11-18 01:44:52 +03:00
"code.gitea.io/gitea/modules/httpcache"
2020-11-13 15:51:07 +03:00
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
2023-03-08 15:17:39 +03:00
"code.gitea.io/gitea/modules/util"
2022-01-20 14:41:25 +03:00
"code.gitea.io/gitea/modules/web/routing"
2020-11-13 15:51:07 +03:00
)
2023-06-14 06:42:38 +03:00
func storageHandler ( storageSetting * setting . Storage , prefix string , objStore storage . ObjectStorage ) func ( next http . Handler ) http . Handler {
2022-03-23 00:02:26 +03:00
prefix = strings . Trim ( prefix , "/" )
2022-01-20 14:41:25 +03:00
funcInfo := routing . GetFuncInfo ( storageHandler , prefix )
2020-11-13 15:51:07 +03:00
return func ( next http . Handler ) http . Handler {
2023-06-14 06:42:38 +03:00
if storageSetting . MinioConfig . ServeDirect {
2020-11-13 15:51:07 +03:00
return http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
if req . Method != "GET" && req . Method != "HEAD" {
next . ServeHTTP ( w , req )
return
}
2022-03-23 00:02:26 +03:00
if ! strings . HasPrefix ( req . URL . Path , "/" + prefix + "/" ) {
2020-11-13 15:51:07 +03:00
next . ServeHTTP ( w , req )
return
}
2022-01-20 14:41:25 +03:00
routing . UpdateFuncInfo ( req . Context ( ) , funcInfo )
2020-11-13 15:51:07 +03:00
2022-03-23 00:02:26 +03:00
rPath := strings . TrimPrefix ( req . URL . Path , "/" + prefix + "/" )
2023-03-21 23:02:49 +03:00
rPath = util . PathJoinRelX ( rPath )
2022-03-23 00:02:26 +03:00
2020-11-13 15:51:07 +03:00
u , err := objStore . URL ( rPath , path . Base ( rPath ) )
if err != nil {
if os . IsNotExist ( err ) || errors . Is ( err , os . ErrNotExist ) {
log . Warn ( "Unable to find %s %s" , prefix , rPath )
2022-03-23 07:54:07 +03:00
http . Error ( w , "file not found" , http . StatusNotFound )
2020-11-13 15:51:07 +03:00
return
}
log . Error ( "Error whilst getting URL for %s %s. Error: %v" , prefix , rPath , err )
2022-03-23 07:54:07 +03:00
http . Error ( w , fmt . Sprintf ( "Error whilst getting URL for %s %s" , prefix , rPath ) , http . StatusInternalServerError )
2020-11-13 15:51:07 +03:00
return
}
2022-03-23 00:02:26 +03:00
2023-04-27 09:06:45 +03:00
http . Redirect ( w , req , u . String ( ) , http . StatusTemporaryRedirect )
2020-11-13 15:51:07 +03:00
} )
}
return http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
if req . Method != "GET" && req . Method != "HEAD" {
next . ServeHTTP ( w , req )
return
}
2022-03-23 00:02:26 +03:00
if ! strings . HasPrefix ( req . URL . Path , "/" + prefix + "/" ) {
2020-11-13 15:51:07 +03:00
next . ServeHTTP ( w , req )
return
}
2022-01-20 14:41:25 +03:00
routing . UpdateFuncInfo ( req . Context ( ) , funcInfo )
2020-11-13 15:51:07 +03:00
2022-03-23 00:02:26 +03:00
rPath := strings . TrimPrefix ( req . URL . Path , "/" + prefix + "/" )
2023-03-21 23:02:49 +03:00
rPath = util . PathJoinRelX ( rPath )
if rPath == "" || rPath == "." {
2022-03-23 07:54:07 +03:00
http . Error ( w , "file not found" , http . StatusNotFound )
2021-03-23 20:20:24 +03:00
return
}
2020-11-18 01:44:52 +03:00
fi , err := objStore . Stat ( rPath )
2020-11-13 15:51:07 +03:00
if err != nil {
if os . IsNotExist ( err ) || errors . Is ( err , os . ErrNotExist ) {
log . Warn ( "Unable to find %s %s" , prefix , rPath )
2022-03-23 07:54:07 +03:00
http . Error ( w , "file not found" , http . StatusNotFound )
2020-11-13 15:51:07 +03:00
return
}
log . Error ( "Error whilst opening %s %s. Error: %v" , prefix , rPath , err )
2022-03-23 07:54:07 +03:00
http . Error ( w , fmt . Sprintf ( "Error whilst opening %s %s" , prefix , rPath ) , http . StatusInternalServerError )
2020-11-13 15:51:07 +03:00
return
}
2023-05-13 17:04:57 +03:00
fr , err := objStore . Open ( rPath )
2020-11-13 15:51:07 +03:00
if err != nil {
2023-05-13 17:04:57 +03:00
log . Error ( "Error whilst opening %s %s. Error: %v" , prefix , rPath , err )
http . Error ( w , fmt . Sprintf ( "Error whilst opening %s %s" , prefix , rPath ) , http . StatusInternalServerError )
2020-11-13 15:51:07 +03:00
return
}
2023-05-13 17:04:57 +03:00
defer fr . Close ( )
httpcache . ServeContentWithCacheControl ( w , req , path . Base ( rPath ) , fi . ModTime ( ) , fr )
2020-11-13 15:51:07 +03:00
} )
}
}