Publish

This commit is contained in:
LittleSheep 2023-11-18 14:30:35 +08:00
parent 61ab586f4f
commit 5ae31d8a07
10 changed files with 150 additions and 7 deletions

View File

@ -8,7 +8,7 @@ A blazing fast reverse proxy with a lot of shining features.
2. Static file hosting
3. ~~Analytics and Metrics~~
4. Integrate with CI/CD
5. ~~Webhook integration~~
5. Webhook integration
6. ~~Web management panel~~
7. **Blazing fast ⚡**

View File

@ -12,6 +12,7 @@
],
"upstreams": [
{
"id": "example",
"name": "Example Upstream",
"uri": "file://C:\\site"
}

View File

@ -13,8 +13,14 @@ func InitAdministration() *fiber.App {
ServerHeader: fmt.Sprintf("RoadSign Administration v%s", roadsign.AppVersion),
DisableStartupMessage: true,
EnableIPValidation: true,
EnablePrintRoutes: viper.GetBool("debug.print_routes"),
TrustedProxies: viper.GetStringSlice("security.administration_trusted_proxies"),
})
webhooks := app.Group("/webhooks").Name("WebHooks")
{
webhooks.Put("/publish/:site/:upstream", doPublish)
}
return app
}

View File

@ -0,0 +1,63 @@
package administration
import (
"code.smartsheep.studio/goatworks/roadsign/pkg/fs"
"code.smartsheep.studio/goatworks/roadsign/pkg/sign"
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
"os"
"path/filepath"
)
func doPublish(ctx *fiber.Ctx) error {
var upstream *sign.UpstreamConfig
for _, item := range sign.App.Sites {
if item.ID == ctx.Params("site") {
for _, stream := range item.Upstreams {
if stream.ID == ctx.Params("upstream") {
upstream = &stream
break
}
}
break
}
}
if upstream == nil {
return fiber.ErrNotFound
} else if upstream.GetType() != sign.UpstreamTypeFile {
return fiber.ErrUnprocessableEntity
}
workdir, _ := upstream.GetRawURI()
if ctx.Query("overwrite", "yes") == "yes" {
files, _ := filepath.Glob(filepath.Join(workdir, "*"))
for _, file := range files {
_ = os.Remove(file)
}
}
if form, err := ctx.MultipartForm(); err == nil {
files := form.File["attachments"]
for _, file := range files {
mimetype := file.Header["Content-Type"][0]
switch mimetype {
case "application/zip":
dst := filepath.Join(os.TempDir(), uuid.NewString()+".zip")
if err := ctx.SaveFile(file, dst); err != nil {
return err
} else {
_ = fs.Unzip(dst, workdir)
}
default:
dst := filepath.Join(workdir, file.Filename)
if err := ctx.SaveFile(file, dst); err != nil {
return err
}
}
}
}
return ctx.SendStatus(fiber.StatusOK)
}

View File

@ -34,7 +34,7 @@ func main() {
if err := sign.ReadInConfig(viper.GetString("paths.configs")); err != nil {
log.Panic().Err(err).Msg("An error occurred when loading configurations.")
} else {
log.Debug().Any("sites", sign.C).Msg("All configuration has been loaded.")
log.Debug().Any("sites", sign.App).Msg("All configuration has been loaded.")
}
// Init hypertext server

72
pkg/fs/zip.go Normal file
View File

@ -0,0 +1,72 @@
package fs
import (
"archive/zip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
func Unzip(src, dest string) error {
r, err := zip.OpenReader(src)
if err != nil {
return err
}
defer func() {
if err := r.Close(); err != nil {
panic(err)
}
}()
_ = os.MkdirAll(dest, 0755)
extract := func(f *zip.File) error {
rc, err := f.Open()
if err != nil {
return err
}
defer func() {
if err := rc.Close(); err != nil {
panic(err)
}
}()
path := filepath.Join(dest, f.Name)
if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) {
return fmt.Errorf("illegal file path: %s", path)
}
if f.FileInfo().IsDir() {
_ = os.MkdirAll(path, f.Mode())
} else {
_ = os.MkdirAll(filepath.Dir(path), f.Mode())
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return err
}
defer func() {
if err := f.Close(); err != nil {
panic(err)
}
}()
_, err = io.Copy(f, rc)
if err != nil {
return err
}
}
return nil
}
for _, f := range r.File {
err := extract(f)
if err != nil {
return err
}
}
return nil
}

View File

@ -16,7 +16,6 @@ func InitServer() *fiber.App {
ServerHeader: fmt.Sprintf("RoadSign v%s", roadsign.AppVersion),
DisableStartupMessage: true,
EnableIPValidation: true,
EnablePrintRoutes: viper.GetBool("debug.print_routes"),
Prefork: viper.GetBool("performance.prefork"),
BodyLimit: viper.GetInt("hypertext.limitation.max_body_size"),
})

View File

@ -15,7 +15,7 @@ func UseProxies(app *fiber.App) {
headers := ctx.GetReqHeaders()
// Filtering sites
for _, site := range sign.C.Sites {
for _, site := range sign.App.Sites {
// Matching rules
for _, rule := range site.Rules {
if !lo.Contains(rule.Host, host) {
@ -95,7 +95,7 @@ func makeResponse(ctx *fiber.Ctx, site sign.SiteConfig) error {
}
// Forward
err := sign.C.Forward(ctx, site)
err := sign.App.Forward(ctx, site)
// Modify response
for _, transformer := range site.Transformers {

View File

@ -8,7 +8,7 @@ import (
"strings"
)
var C *AppConfig
var App *AppConfig
func ReadInConfig(root string) error {
cfg := &AppConfig{
@ -37,7 +37,7 @@ func ReadInConfig(root string) error {
return err
}
C = cfg
App = cfg
return nil
}

View File

@ -15,6 +15,8 @@ const (
)
type UpstreamConfig struct {
ID string `json:"id"`
Name string `json:"name"`
URI string `json:"uri"`
}