feat: update

This commit is contained in:
sujit
2025-08-11 10:15:45 +05:45
parent da122615fd
commit bb57692cbb
13 changed files with 1376 additions and 1 deletions

View File

@@ -0,0 +1,16 @@
{
"prefix": "/",
"middlewares": [
{"name": "cors"}
],
"static": {
"dir": "./public",
"prefix": "/",
"options": {
"byte_range": true,
"browse": true,
"compress": true,
"index_file": "index.html"
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>RAM LIMO LLC.</title>
<script type="module" crossorigin src="/assets/index-B0w5Q249.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Bc6Em-gk.css">
</head>
<body>
<div id="root"></div>
</body>
</html>

Binary file not shown.

View File

@@ -0,0 +1,38 @@
package rewrite
import (
"regexp"
"github.com/gofiber/fiber/v2"
)
// Config defines the config for middleware.
type Config struct {
// Next defines a function to skip middleware.
// Optional. Default: nil
Next func(*fiber.Ctx) bool
// Rules defines the URL path rewrite rules. The values captured in asterisk can be
// retrieved by index e.g. $1, $2 and so on.
// Required. Example:
// "/old": "/new",
// "/api/*": "/$1",
// "/js/*": "/public/javascripts/$1",
// "/users/*/orders/*": "/user/$1/order/$2",
Rules map[string]string
rulesRegex map[*regexp.Regexp]string
}
// Helper function to set default values
func configDefault(config ...Config) Config {
// Return default config if nothing provided
if len(config) < 1 {
return Config{}
}
// Override default config
cfg := config[0]
return cfg
}

View File

@@ -0,0 +1,62 @@
package rewrite
import (
"fmt"
"log"
"regexp"
"strconv"
"strings"
"github.com/gofiber/fiber/v2"
)
// New creates a new middleware handler
func New(config ...Config) fiber.Handler {
cfg := configDefault(config...)
cfg.rulesRegex = map[*regexp.Regexp]string{}
for k, v := range cfg.Rules {
fmt.Printf("Rewriting \033[32m%s\033[0m ~> \033[33m%s\033[0m\n", k, v)
escaped := regexp.QuoteMeta(k)
pattern := strings.ReplaceAll(escaped, `\*`, `(.*)`)
pattern = "^" + pattern + "$"
rx, err := regexp.Compile(pattern)
if err != nil {
log.Printf("Unable to compile regex: %v, %s", err, pattern)
} else {
cfg.rulesRegex[rx] = v
}
}
// Middleware function
return func(c *fiber.Ctx) error {
// Next request to skip middleware
if cfg.Next != nil && cfg.Next(c) {
return c.Next()
}
// Rewrite
for k, v := range cfg.rulesRegex {
replacer := captureTokens(k, c.Path())
if replacer != nil {
c.Path(replacer.Replace(v))
break
}
}
return c.Next()
}
}
// https://github.com/labstack/echo/blob/master/middleware/rewrite.go
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {
groups := pattern.FindAllStringSubmatch(input, -1)
if groups == nil {
return nil
}
values := groups[0][1:]
replace := make([]string, 2*len(values))
for i, v := range values {
j := 2 * i
replace[j] = "$" + strconv.Itoa(i+1)
replace[j+1] = v
}
return strings.NewReplacer(replace...)
}

View File

@@ -0,0 +1,103 @@
package renderer
import (
"fmt"
"mime"
"os"
"path/filepath"
"strings"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/compress"
"github.com/oarkflow/jet"
"github.com/oarkflow/mq/services/middlewares/rewrite"
)
type Config struct {
Prefix string `json:"prefix"`
Root string `json:"root"`
Index string `json:"index"`
UseIndex bool `json:"use_index"`
Compress bool `json:"compress"`
}
func New(router fiber.Router, cfg ...Config) error {
var config Config
if len(cfg) > 0 {
config = cfg[0]
}
if config.Root == "" {
config.Root = "./"
}
if config.Prefix == "/" {
config.Prefix = ""
}
if config.UseIndex && config.Index == "" {
config.Index = "index.html"
}
if config.Compress {
router.Use(compress.New(compress.Config{
Level: compress.LevelBestSpeed,
}))
}
rules := make(map[string]string)
root := filepath.Clean(config.Root)
err := filepath.WalkDir(config.Root, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() {
path = strings.TrimPrefix(path, root)
rules[path] = filepath.Join(config.Prefix, path)
}
return nil
})
if err != nil {
return err
}
router.Use(rewrite.New(rewrite.Config{Rules: rules}))
router.Get(config.Prefix+"/*", handleStaticFile(config))
return nil
}
func handleStaticFile(config Config) fiber.Handler {
return func(c *fiber.Ctx) error {
fullPath := c.Params("*")
filePath := filepath.Join(config.Root, fullPath)
fileInfo, err := os.Stat(filePath)
if err != nil {
return c.Status(fiber.StatusNotFound).SendString(fmt.Sprintf("File %s not found", filePath))
}
isIndex := false
if fileInfo.IsDir() {
if !config.UseIndex {
return c.Status(fiber.StatusNotFound).SendString("Invalid file")
}
isIndex = true
filePath = filepath.Join(filePath, config.Index)
}
fileContent, err := os.ReadFile(filePath)
if err != nil {
return c.Status(fiber.StatusNotFound).SendString(fmt.Sprintf("File %s not found", filePath))
}
if isIndex {
parser := jet.NewWithMemory(jet.WithDelims("{{", "}}"))
content, err := parser.ParseTemplate(string(fileContent), map[string]any{
"json_data": map[string]any{},
})
if err != nil {
return c.Status(fiber.StatusNotFound).SendString(err.Error())
}
fileContent = []byte(content)
}
ext := filepath.Ext(filePath)
mimeType := mime.TypeByExtension(ext)
if mimeType == "" {
mimeType = "application/octet-stream"
}
c.Set("Content-Type", mimeType)
c.Set("Cache-Control", "public, max-age=31536000")
return c.Send(fileContent)
}
}

View File

@@ -25,6 +25,7 @@ import (
"github.com/oarkflow/mq/dag"
"github.com/oarkflow/mq/services/http/responses"
"github.com/oarkflow/mq/services/middlewares"
"github.com/oarkflow/mq/services/renderer"
"github.com/oarkflow/mq/services/utils"
)
@@ -34,7 +35,10 @@ func Setup(loader *Loader, serverApp *fiber.App, brokerAddr string) {
if loader.UserConfig == nil {
return
}
SetupServices(loader.Prefix(), serverApp, brokerAddr)
err := SetupServices(loader.Prefix(), serverApp, brokerAddr)
if err != nil {
panic(err)
}
}
func SetupHandler(handler Handler, brokerAddr string, async ...bool) *dag.DAG {
@@ -213,6 +217,23 @@ func SetupServices(prefix string, router fiber.Router, brokerAddr string) error
if err != nil {
return err
}
static := userConfig.Policy.Web.Static
if static != nil && static.Dir != "" {
router.Static(
static.Prefix,
static.Dir,
fiber.Static{
Compress: static.Options.Compress,
ByteRange: static.Options.ByteRange,
Browse: static.Options.Browse,
Index: static.Options.IndexFile,
},
)
}
err = setupRender(prefix, router)
if err != nil {
return fmt.Errorf("failed to setup render: %w", err)
}
return SetupAPI(prefix, router, brokerAddr)
}
@@ -441,6 +462,24 @@ func ruleMiddleware(rules map[string]string) fiber.Handler {
}
}
func setupRender(_ string, clientRoutes fiber.Router) error {
for _, cfg := range userConfig.Policy.Web.Render {
if cfg.Root != "" && cfg.ID != "" {
err := renderer.New(clientRoutes, renderer.Config{
Prefix: cfg.Prefix,
Root: cfg.Root,
Index: cfg.Index,
UseIndex: cfg.UseIndex,
Compress: cfg.Compress,
})
if err != nil {
return err
}
}
}
return nil
}
// requestMiddleware validates the request body in the original form of byte array
// against the provided request JSON schema to ensure that the request body is valid.
func requestMiddleware(prefix string, route *Route) fiber.Handler {