Skip to content

Commit

Permalink
New Reverse Proxy feature
Browse files Browse the repository at this point in the history
Signed-off-by: Quentin Guidée <[email protected]>
  • Loading branch information
quentinguidee committed Aug 27, 2023
1 parent 547cad8 commit a59dde5
Show file tree
Hide file tree
Showing 9 changed files with 425 additions and 56 deletions.
24 changes: 14 additions & 10 deletions init.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ func main() {
return
}

err = os.MkdirAll(storage.PathProxy, os.ModePerm)
if err != nil && !os.IsExist(err) {
logger.Error(fmt.Errorf("failed to create directory: %v", err)).
AddKeyValue("message", "failed to create directory").
AddKeyValue("path", storage.PathProxy).
Print()

return
}

err = setupDependencies()
if err != nil {
logger.Error(fmt.Errorf("failed to setup dependencies: %v", err)).Print()
Expand All @@ -51,30 +61,24 @@ func main() {
return
}

r := router.Create(router.About{
router := router.NewRouter(types.About{
Version: version,
Commit: commit,
Date: date,

OS: runtime.GOOS,
Arch: runtime.GOARCH,
})
defer router.Unload()
defer router.Stop()

// Logs
url := fmt.Sprintf("http://%s", config.Current.Host)

fmt.Printf("\n-- Vertex Client :: %s\n\n", url)

logger.Log("Vertex started").
AddKeyValue("url", url).
Print()

err = r.Run(fmt.Sprintf(":%s", config.Current.Port))
if err != nil {
logger.Error(fmt.Errorf("error while starting server: %v", err)).Print()
}

logger.Log("Vertex stopped").Print()
router.Start(fmt.Sprintf(":%s", config.Current.Port))
}

func parseArgs() {
Expand Down
30 changes: 30 additions & 0 deletions pkg/ginutils/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ginutils

import (
"strings"

"github.com/gin-gonic/gin"
"github.com/vertex-center/vertex/pkg/logger"
)

func Logger(router string) gin.HandlerFunc {
return gin.LoggerWithFormatter(func(params gin.LogFormatterParams) string {
l := logger.Request().
AddKeyValue("router", router).
AddKeyValue("method", params.Method).
AddKeyValue("status", params.StatusCode).
AddKeyValue("path", params.Path).
AddKeyValue("latency", params.Latency).
AddKeyValue("ip", params.ClientIP).
AddKeyValue("size", params.BodySize)

if params.ErrorMessage != "" {
err, _ := strings.CutSuffix(params.ErrorMessage, "\n")
l.AddKeyValue("error", err)
}

l.PrintInExternalFiles()

return l.String()
})
}
1 change: 1 addition & 0 deletions pkg/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
const (
PathClient = "live/client"
PathPackages = "live/packages"
PathProxy = "live/proxy"
PathInstances = "live/instances"
PathServices = "live/services"
PathUpdates = "live/updates"
Expand Down
82 changes: 82 additions & 0 deletions repository/proxy_fs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package repository

import (
"encoding/json"
"errors"
"os"
"path"

"github.com/google/uuid"
"github.com/vertex-center/vertex/pkg/logger"
"github.com/vertex-center/vertex/pkg/storage"
"github.com/vertex-center/vertex/types"
)

type ProxyFSRepository struct {
redirects types.ProxyRedirects
proxyPath string
}

type ProxyRepositoryParams struct {
proxyPath string
}

func NewProxyFSRepository(params *ProxyRepositoryParams) ProxyFSRepository {
if params == nil {
params = &ProxyRepositoryParams{}
}
if params.proxyPath == "" {
params.proxyPath = storage.PathProxy
}

repo := ProxyFSRepository{
redirects: types.ProxyRedirects{},
proxyPath: params.proxyPath,
}
repo.read()

return repo
}

func (r *ProxyFSRepository) GetRedirects() types.ProxyRedirects {
return r.redirects
}

func (r *ProxyFSRepository) AddRedirect(id uuid.UUID, redirect types.ProxyRedirect) error {
r.redirects[id] = redirect
return r.write()
}

func (r *ProxyFSRepository) RemoveRedirect(id uuid.UUID) error {
delete(r.redirects, id)
return r.write()
}

func (r *ProxyFSRepository) read() {
p := path.Join(r.proxyPath, "redirects.json")
file, err := os.ReadFile(p)

if errors.Is(err, os.ErrNotExist) {
logger.Log("redirects.json doesn't exists or could not be found").Print()
} else if err != nil {
logger.Error(err).Print()
return
}

err = json.Unmarshal(file, &r.redirects)
if err != nil {
logger.Error(err).Print()
return
}
}

func (r *ProxyFSRepository) write() error {
p := path.Join(r.proxyPath, "redirects.json")

bytes, err := json.MarshalIndent(r.redirects, "", "\t")
if err != nil {
return err
}

return os.WriteFile(p, bytes, os.ModePerm)
}
71 changes: 71 additions & 0 deletions router/proxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package router

import (
"errors"
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/vertex-center/vertex/types"
)

func addProxyRoutes(r *gin.RouterGroup) {
r.GET("/redirects", handleGetRedirects)
r.POST("/redirect", handleAddRedirect)
r.DELETE("/redirect/:id", handleRemoveRedirect)
}

func handleGetRedirects(c *gin.Context) {
redirects := proxyService.GetRedirects()
c.JSON(http.StatusOK, redirects)
}

type handleAddRedirectBody struct {
Source string `json:"source"`
Target string `json:"target"`
}

func handleAddRedirect(c *gin.Context) {
var body handleAddRedirectBody
err := c.BindJSON(&body)
if err != nil {
_ = c.AbortWithError(http.StatusBadRequest, fmt.Errorf("failed to parse body: %v", err))
return
}

redirect := types.ProxyRedirect{
Source: body.Source,
Target: body.Target,
}

err = proxyService.AddRedirect(redirect)
if err != nil {
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}

c.Status(http.StatusOK)
}

func handleRemoveRedirect(c *gin.Context) {
idString := c.Param("id")
if idString == "" {
_ = c.AbortWithError(http.StatusBadRequest, errors.New("failed to get redirection uuid"))
return
}

id, err := uuid.Parse(idString)
if err != nil {
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}

err = proxyService.RemoveRedirect(id)
if err != nil {
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}

c.Status(http.StatusOK)
}
Loading

0 comments on commit a59dde5

Please sign in to comment.