Support downloading remote files to a server via the API
Co-authored-by: Dane Everitt <dane@daneeveritt.com>
This commit is contained in:
parent
84c05efaa5
commit
8f26c31df6
|
@ -1,6 +1,7 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
|
@ -60,6 +61,9 @@ func AuthorizationMiddleware(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to fetch a server out of the servers collection stored in memory.
|
// Helper function to fetch a server out of the servers collection stored in memory.
|
||||||
|
//
|
||||||
|
// This function should not be used in new controllers, prefer ExtractServer where
|
||||||
|
// possible.
|
||||||
func GetServer(uuid string) *server.Server {
|
func GetServer(uuid string) *server.Server {
|
||||||
return server.GetServers().Find(func(s *server.Server) bool {
|
return server.GetServers().Find(func(s *server.Server) bool {
|
||||||
return uuid == s.Id()
|
return uuid == s.Id()
|
||||||
|
@ -70,12 +74,24 @@ func GetServer(uuid string) *server.Server {
|
||||||
// locate it.
|
// locate it.
|
||||||
func ServerExists(c *gin.Context) {
|
func ServerExists(c *gin.Context) {
|
||||||
u, err := uuid.Parse(c.Param("server"))
|
u, err := uuid.Parse(c.Param("server"))
|
||||||
if err != nil || GetServer(u.String()) == nil {
|
if err == nil {
|
||||||
|
if s := GetServer(u.String()); s != nil {
|
||||||
|
c.Set("server", s)
|
||||||
|
c.Next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{
|
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{
|
||||||
"error": "The resource you requested does not exist.",
|
"error": "The resource you requested does not exist.",
|
||||||
})
|
})
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Next()
|
// Returns the server instance from the gin context. If there is no server set in the
|
||||||
|
// context (e.g. calling from a controller not protected by ServerExists) this function
|
||||||
|
// will panic.
|
||||||
|
func ExtractServer(c *gin.Context) *server.Server {
|
||||||
|
if s, ok := c.Get("server"); ok {
|
||||||
|
return s.(*server.Server)
|
||||||
|
}
|
||||||
|
panic(errors.New("cannot extract server, missing on gin context"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ func Configure() *gin.Engine {
|
||||||
files.PUT("/rename", putServerRenameFiles)
|
files.PUT("/rename", putServerRenameFiles)
|
||||||
files.POST("/copy", postServerCopyFile)
|
files.POST("/copy", postServerCopyFile)
|
||||||
files.POST("/write", postServerWriteFile)
|
files.POST("/write", postServerWriteFile)
|
||||||
|
files.POST("/writeUrl", postServerDownloadRemoteFile)
|
||||||
files.POST("/create-directory", postServerCreateDirectory)
|
files.POST("/create-directory", postServerCreateDirectory)
|
||||||
files.POST("/delete", postServerDeleteFiles)
|
files.POST("/delete", postServerDeleteFiles)
|
||||||
files.POST("/compress", postServerCompressFiles)
|
files.POST("/compress", postServerCompressFiles)
|
||||||
|
|
|
@ -225,6 +225,51 @@ func postServerWriteFile(c *gin.Context) {
|
||||||
c.Status(http.StatusNoContent)
|
c.Status(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes the contents of the remote URL to a file on a server.
|
||||||
|
func postServerDownloadRemoteFile(c *gin.Context) {
|
||||||
|
s := ExtractServer(c)
|
||||||
|
var data struct {
|
||||||
|
URL string `binding:"required" json:"url"`
|
||||||
|
BasePath string `json:"path"`
|
||||||
|
}
|
||||||
|
if err := c.BindJSON(&data); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := url.Parse(data.URL)
|
||||||
|
if err != nil {
|
||||||
|
if e, ok := err.(*url.Error); ok {
|
||||||
|
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": "An error occurred while parsing that URL: " + e.Err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
TrackedServerError(err, s).AbortWithServerError(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.Get(u.String())
|
||||||
|
if err != nil {
|
||||||
|
TrackedServerError(err, s).AbortWithServerError(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
filename := strings.Split(u.Path, "/")
|
||||||
|
if err := s.Filesystem().Writefile(filepath.Join(data.BasePath, filename[len(filename)-1]), resp.Body); err != nil {
|
||||||
|
if errors.Is(err, filesystem.ErrIsDirectory) {
|
||||||
|
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": "Cannot write file, name conflicts with an existing directory by the same name.",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
TrackedServerError(err, s).AbortFilesystemError(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Status(http.StatusNoContent)
|
||||||
|
}
|
||||||
|
|
||||||
// Create a directory on a server.
|
// Create a directory on a server.
|
||||||
func postServerCreateDirectory(c *gin.Context) {
|
func postServerCreateDirectory(c *gin.Context) {
|
||||||
s := GetServer(c.Param("server"))
|
s := GetServer(c.Param("server"))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user