🎉 Initial Commit
This commit is contained in:
7
pkg/http/api/check_ip.go
Normal file
7
pkg/http/api/check_ip.go
Normal file
@ -0,0 +1,7 @@
|
||||
package api
|
||||
|
||||
import "github.com/gofiber/fiber/v2"
|
||||
|
||||
func getClientIP(c *fiber.Ctx) error {
|
||||
return c.SendString(c.IP())
|
||||
}
|
54
pkg/http/api/directory.go
Normal file
54
pkg/http/api/directory.go
Normal file
@ -0,0 +1,54 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/spf13/viper"
|
||||
"strings"
|
||||
|
||||
"git.solsynth.dev/hypernet/nexus/pkg/directory"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/proxy"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func listExistsService(c *fiber.Ctx) error {
|
||||
services := directory.ListServiceInstance()
|
||||
|
||||
return c.JSON(lo.Map(services, func(item *directory.ServiceInstance, index int) map[string]any {
|
||||
return map[string]any{
|
||||
"id": item.ID,
|
||||
"type": item.Type,
|
||||
"label": item.Label,
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
func forwardServiceRequest(c *fiber.Ctx) error {
|
||||
serviceType := c.Params("service")
|
||||
ogKeyword := serviceType
|
||||
|
||||
aliasingMap := viper.GetStringMapString("services.aliases")
|
||||
if val, ok := aliasingMap[serviceType]; ok {
|
||||
serviceType = val
|
||||
}
|
||||
|
||||
service := directory.GetServiceInstanceByType(serviceType)
|
||||
|
||||
if service == nil || service.HttpAddr == nil {
|
||||
return fiber.NewError(fiber.StatusNotFound, "service not found")
|
||||
}
|
||||
|
||||
ogUrl := c.Request().URI().String()
|
||||
url := c.OriginalURL()
|
||||
url = strings.Replace(url, "/cgi/"+ogKeyword, "/api", 1)
|
||||
url = "http://" + *service.HttpAddr + url
|
||||
|
||||
log.Debug().
|
||||
Str("from", ogUrl).
|
||||
Str("to", url).
|
||||
Str("service", serviceType).
|
||||
Str("id", service.ID).
|
||||
Msg("Forwarding request for service...")
|
||||
|
||||
return proxy.Do(c, url)
|
||||
}
|
33
pkg/http/api/index.go
Normal file
33
pkg/http/api/index.go
Normal file
@ -0,0 +1,33 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/contrib/websocket"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func MapAPIs(app *fiber.App) {
|
||||
wellKnown := app.Group("/.well-known").Name("Well Known")
|
||||
{
|
||||
wellKnown.Get("/", func(c *fiber.Ctx) error {
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
})
|
||||
wellKnown.Get("/check-ip", getClientIP)
|
||||
wellKnown.Get("/directory/services", listExistsService)
|
||||
}
|
||||
|
||||
app.All("/cgi/:service/*", forwardServiceRequest)
|
||||
|
||||
api := app.Group("/api").Name("API")
|
||||
{
|
||||
api.Use(func(c *fiber.Ctx) error {
|
||||
/*if err := exts.EnsureAuthenticated(c); err != nil {
|
||||
return err
|
||||
}*/
|
||||
return c.Next()
|
||||
}).Get("/ws", websocket.New(listenWebsocket))
|
||||
|
||||
api.All("/*", func(c *fiber.Ctx) error {
|
||||
return fiber.ErrNotFound
|
||||
})
|
||||
}
|
||||
}
|
86
pkg/http/api/ws.go
Normal file
86
pkg/http/api/ws.go
Normal file
@ -0,0 +1,86 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"git.solsynth.dev/hypernet/nexus/pkg/internal/models"
|
||||
"git.solsynth.dev/hypernet/nexus/pkg/internal/services"
|
||||
"git.solsynth.dev/hypernet/nexus/pkg/nex"
|
||||
"github.com/gofiber/contrib/websocket"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func listenWebsocket(c *websocket.Conn) {
|
||||
user := c.Locals("user").(models.Account)
|
||||
|
||||
// Push connection
|
||||
clientId := services.ClientRegister(user, c)
|
||||
log.Debug().
|
||||
Uint("user", user.ID).
|
||||
Uint64("clientId", clientId).
|
||||
Msg("New websocket connection established...")
|
||||
|
||||
// Event loop
|
||||
var mt int
|
||||
var data []byte
|
||||
var err error
|
||||
|
||||
var packet nex.WebSocketPackage
|
||||
|
||||
for {
|
||||
if mt, data, err = c.ReadMessage(); err != nil {
|
||||
break
|
||||
} else if err := jsoniter.Unmarshal(data, &packet); err != nil {
|
||||
_ = c.WriteMessage(mt, nex.WebSocketPackage{
|
||||
Action: "error",
|
||||
Message: "unable to unmarshal your command, requires json request",
|
||||
}.Marshal())
|
||||
continue
|
||||
}
|
||||
|
||||
aliasingMap := viper.GetStringMapString("services.aliases")
|
||||
if val, ok := aliasingMap[packet.Endpoint]; ok {
|
||||
packet.Endpoint = val
|
||||
}
|
||||
|
||||
/*
|
||||
service := directory.GetServiceInstanceByType(packet.Endpoint)
|
||||
if service == nil {
|
||||
_ = c.WriteMessage(mt, nex.NetworkPackage{
|
||||
Action: "error",
|
||||
Message: "service not found",
|
||||
}.Marshal())
|
||||
continue
|
||||
}
|
||||
pc, err := service.GetGrpcConn()
|
||||
if err != nil {
|
||||
_ = c.WriteMessage(mt, nex.NetworkPackage{
|
||||
Action: "error",
|
||||
Message: fmt.Sprintf("unable to connect to service: %v", err.Error()),
|
||||
}.Marshal())
|
||||
continue
|
||||
}
|
||||
|
||||
sc := proto.NewStreamControllerClient(pc)
|
||||
_, err = sc.EmitStreamEvent(context.Background(), &proto.StreamEventRequest{
|
||||
Event: packet.Action,
|
||||
UserId: uint64(user.ID),
|
||||
ClientId: uint64(clientId),
|
||||
Payload: packet.RawPayload(),
|
||||
})
|
||||
if err != nil {
|
||||
_ = c.WriteMessage(mt, nex.NetworkPackage{
|
||||
Action: "error",
|
||||
Message: fmt.Sprintf("unable send message to service: %v", err.Error()),
|
||||
}.Marshal())
|
||||
continue
|
||||
}*/
|
||||
}
|
||||
|
||||
// Pop connection
|
||||
services.ClientUnregister(user, clientId)
|
||||
log.Debug().
|
||||
Uint("user", user.ID).
|
||||
Uint64("clientId", clientId).
|
||||
Msg("A websocket connection disconnected...")
|
||||
}
|
18
pkg/http/exts/request.go
Normal file
18
pkg/http/exts/request.go
Normal file
@ -0,0 +1,18 @@
|
||||
package exts
|
||||
|
||||
import (
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
var validation = validator.New(validator.WithRequiredStructEnabled())
|
||||
|
||||
func BindAndValidate(c *fiber.Ctx, out any) error {
|
||||
if err := c.BodyParser(out); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
} else if err := validation.Struct(out); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
54
pkg/http/server.go
Normal file
54
pkg/http/server.go
Normal file
@ -0,0 +1,54 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"git.solsynth.dev/hypernet/nexus/pkg/http/api"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
"github.com/gofiber/fiber/v2/middleware/idempotency"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type HTTPApp struct {
|
||||
app *fiber.App
|
||||
}
|
||||
|
||||
func NewServer() *HTTPApp {
|
||||
app := fiber.New(fiber.Config{
|
||||
DisableStartupMessage: true,
|
||||
EnableIPValidation: true,
|
||||
ServerHeader: "Hydrogen.Nexus",
|
||||
AppName: "Hydrogen.Nexus",
|
||||
ProxyHeader: fiber.HeaderXForwardedFor,
|
||||
JSONEncoder: json.Marshal,
|
||||
JSONDecoder: json.Unmarshal,
|
||||
BodyLimit: 512 * 1024 * 1024 * 1024, // 512 TiB
|
||||
EnablePrintRoutes: viper.GetBool("debug.print_routes"),
|
||||
})
|
||||
|
||||
app.Use(idempotency.New())
|
||||
app.Use(cors.New(cors.Config{
|
||||
AllowCredentials: true,
|
||||
AllowMethods: "GET,POST,HEAD,PUT,DELETE,PATCH",
|
||||
AllowOriginsFunc: func(origin string) bool {
|
||||
return true
|
||||
},
|
||||
}))
|
||||
|
||||
app.Use(logger.New(logger.Config{
|
||||
Format: "${status} | ${latency} | ${method} ${path}\n",
|
||||
Output: log.Logger,
|
||||
}))
|
||||
|
||||
api.MapAPIs(app)
|
||||
|
||||
return &HTTPApp{app}
|
||||
}
|
||||
|
||||
func (v *HTTPApp) Listen() {
|
||||
if err := v.app.Listen(viper.GetString("bind")); err != nil {
|
||||
log.Fatal().Err(err).Msg("An error occurred when starting server...")
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user