major rewrite work 1

This commit is contained in:
Sky Johnson 2025-06-05 22:18:21 -05:00
parent ddb1d7c9d7
commit a2d9b0ad9f
4 changed files with 132 additions and 120 deletions

View File

@ -12,7 +12,7 @@ type Config struct {
Port int Port int
Debug bool Debug bool
HTTPLogging bool HTTPLogging bool
StaticPrefix string PublicPrefix string
} }
Runner struct { Runner struct {
@ -21,7 +21,7 @@ type Config struct {
Dirs struct { Dirs struct {
Routes string Routes string
Static string Public string
FS string FS string
Data string Data string
Override string Override string
@ -40,12 +40,12 @@ func New(data *fin.Data) *Config {
config.Server.Port = data.GetOr("server.port", 3117).(int) config.Server.Port = data.GetOr("server.port", 3117).(int)
config.Server.Debug = data.GetOr("server.debug", false).(bool) config.Server.Debug = data.GetOr("server.debug", false).(bool)
config.Server.HTTPLogging = data.GetOr("server.http_logging", true).(bool) config.Server.HTTPLogging = data.GetOr("server.http_logging", true).(bool)
config.Server.StaticPrefix = data.GetOr("server.static_prefix", "public").(string) config.Server.PublicPrefix = data.GetOr("server.public_prefix", "public").(string)
config.Runner.PoolSize = data.GetOr("runner.pool_size", runtime.GOMAXPROCS(0)).(int) config.Runner.PoolSize = data.GetOr("runner.pool_size", runtime.GOMAXPROCS(0)).(int)
config.Dirs.Routes = data.GetOr("dirs.routes", "routes").(string) config.Dirs.Routes = data.GetOr("dirs.routes", "routes").(string)
config.Dirs.Static = data.GetOr("dirs.static", "public").(string) config.Dirs.Public = data.GetOr("dirs.public", "public").(string)
config.Dirs.FS = data.GetOr("dirs.fs", "fs").(string) config.Dirs.FS = data.GetOr("dirs.fs", "fs").(string)
config.Dirs.Data = data.GetOr("dirs.data", "data").(string) config.Dirs.Data = data.GetOr("dirs.data", "data").(string)
config.Dirs.Override = data.GetOr("dirs.override", "override").(string) config.Dirs.Override = data.GetOr("dirs.override", "override").(string)

View File

@ -2,17 +2,14 @@
package http package http
import ( import (
"bytes"
"context" "context"
"strings" "strings"
"sync"
"time" "time"
"Moonshark/color" "Moonshark/color"
"Moonshark/config" "Moonshark/config"
"Moonshark/logger" "Moonshark/logger"
"Moonshark/metadata" "Moonshark/metadata"
"Moonshark/router"
"Moonshark/runner" "Moonshark/runner"
"Moonshark/sessions" "Moonshark/sessions"
"Moonshark/utils" "Moonshark/utils"
@ -20,69 +17,11 @@ import (
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
) )
var ( var emptyMap = make(map[string]any)
debugPath = []byte("/debug/stats")
staticMethods = map[string]bool{"GET": true, "HEAD": true, "OPTIONS": true}
cached404, cached500 []byte
cacheMu sync.RWMutex
emptyMap = make(map[string]any)
)
type Server struct { func NewHttpServer(cfg *config.Config, handler fasthttp.RequestHandler, dbg bool) *fasthttp.Server {
luaRouter *router.Router return &fasthttp.Server{
staticHandler fasthttp.RequestHandler Handler: handler,
luaRunner *runner.Runner
fasthttpServer *fasthttp.Server
sessionManager *sessions.SessionManager
cfg *config.Config
debugMode bool
staticPrefixBytes []byte
}
func New(luaRouter *router.Router, runner *runner.Runner, cfg *config.Config, debugMode bool) *Server {
staticPrefix := cfg.Server.StaticPrefix
if !strings.HasPrefix(staticPrefix, "/") {
staticPrefix = "/" + staticPrefix
}
if !strings.HasSuffix(staticPrefix, "/") {
staticPrefix += "/"
}
s := &Server{
luaRouter: luaRouter,
luaRunner: runner,
debugMode: debugMode,
cfg: cfg,
sessionManager: sessions.GlobalSessionManager,
staticPrefixBytes: []byte(staticPrefix),
}
// Cache error pages
errorConfig := utils.ErrorPageConfig{
OverrideDir: cfg.Dirs.Override,
DebugMode: debugMode,
}
cacheMu.Lock()
cached404 = []byte(utils.NotFoundPage(errorConfig, ""))
cached500 = []byte(utils.InternalErrorPage(errorConfig, "", "Internal Server Error"))
cacheMu.Unlock()
// Setup static file serving
if cfg.Dirs.Static != "" {
staticFS := &fasthttp.FS{
Root: cfg.Dirs.Static,
IndexNames: []string{"index.html"},
AcceptByteRange: true,
Compress: true,
CompressedFileSuffix: ".gz",
CompressBrotli: true,
PathRewrite: fasthttp.NewPathPrefixStripper(len(staticPrefix) - 1),
}
s.staticHandler = staticFS.NewRequestHandler()
}
s.fasthttpServer = &fasthttp.Server{
Handler: s.handleRequest,
Name: "Moonshark/" + metadata.Version, Name: "Moonshark/" + metadata.Version,
ReadTimeout: 30 * time.Second, ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second, WriteTimeout: 30 * time.Second,
@ -93,8 +32,26 @@ func New(luaRouter *router.Router, runner *runner.Runner, cfg *config.Config, de
StreamRequestBody: true, StreamRequestBody: true,
NoDefaultServerHeader: true, NoDefaultServerHeader: true,
} }
}
return s func NewPublicHandler(pubDir, prefix string) fasthttp.RequestHandler {
if !strings.HasPrefix(prefix, "/") {
prefix = "/" + prefix
}
if !strings.HasSuffix(prefix, "/") {
prefix += "/"
}
fs := &fasthttp.FS{
Root: pubDir,
IndexNames: []string{"index.html"},
AcceptByteRange: true,
Compress: true,
CompressedFileSuffix: ".gz",
CompressBrotli: true,
PathRewrite: fasthttp.NewPathPrefixStripper(len(prefix) - 1),
}
return fs.NewRequestHandler()
} }
func (s *Server) ListenAndServe(addr string) error { func (s *Server) ListenAndServe(addr string) error {
@ -111,20 +68,6 @@ func (s *Server) handleRequest(ctx *fasthttp.RequestCtx) {
method := string(ctx.Method()) method := string(ctx.Method())
path := string(ctx.Path()) path := string(ctx.Path())
// Debug stats endpoint
if s.debugMode && bytes.Equal(ctx.Path(), debugPath) {
s.handleDebugStats(ctx)
s.logRequest(ctx, method, path, time.Since(start))
return
}
// Static file serving
if s.staticHandler != nil && bytes.HasPrefix(ctx.Path(), s.staticPrefixBytes) {
s.staticHandler(ctx)
s.logRequest(ctx, method, path, time.Since(start))
return
}
// Route lookup // Route lookup
bytecode, params, found := s.luaRouter.Lookup(method, path) bytecode, params, found := s.luaRouter.Lookup(method, path)
if !found { if !found {

105
main.go Normal file
View File

@ -0,0 +1,105 @@
package main
import (
"Moonshark/color"
"Moonshark/config"
"Moonshark/http"
"Moonshark/logger"
"Moonshark/metadata"
"Moonshark/router"
"Moonshark/runner"
"Moonshark/sessions"
"bytes"
"flag"
"fmt"
"os"
"time"
fin "git.sharkk.net/Sharkk/Fin"
"github.com/valyala/fasthttp"
)
var (
cfg *config.Config // Server config from Fin file
rtr *router.Router // Lua file router
rnr *runner.Runner // Lua runner
svr *fasthttp.Server // FastHTTP server
pub fasthttp.RequestHandler // Public asset handler
snm *sessions.SessionManager // Session data manager
dbg bool // Debug mode flag
pubPfx []byte // Cached public asset prefix
)
func main() {
cfgPath := flag.String("config", "config", "Path to Fin config file")
dbgFlag := flag.Bool("debug", false, "Force debug mode")
sptPath := flag.String("script", "", "Path to Lua script to execute once")
flag.Parse()
sptMode := *sptPath != ""
color.SetColors(color.DetectShellColors())
banner(sptMode)
cfg = config.New(readConfig(*cfgPath))
dbg = *dbgFlag || cfg.Server.Debug
logger.Debug(dbg)
if dbg {
logger.Debugf("Debug logging enabled")
}
svr = http.NewHttpServer(cfg, requestMux, dbg)
pub = http.NewPublicHandler(cfg.Dirs.Public, cfg.Server.PublicPrefix)
pubPfx = []byte(cfg.Server.PublicPrefix)
}
// This is the primary request handler mux - determines whether we need to handle a Lua
// route or if we're serving a static file.
func requestMux(ctx *fasthttp.RequestCtx) {
start := time.Now()
method := ctx.Method()
path := ctx.Path()
// Handle static file request
if bytes.HasPrefix(path, pubPfx) {
pub(ctx)
if cfg.Server.HTTPLogging {
logger.Request(ctx.Response.StatusCode(), string(method), string(path), time.Since(start))
}
return
}
}
// Attempt to read the given path for config, or return an empty struct for defaults
func readConfig(path string) *fin.Data {
file, err := os.Open(path)
if err != nil {
logger.Errorf("Failed to open config file %s, using defaults", color.Yellow(path))
return fin.NewData()
}
defer file.Close()
cfg, err := fin.Load(file)
if err != nil {
logger.Errorf("Failed to load config file %s, using defaults", color.Yellow(path))
}
return cfg
}
// Print our super-awesome banner with the current version!
func banner(scriptMode bool) {
if scriptMode {
fmt.Println(color.Blue(fmt.Sprintf("Moonshark %s << Script Mode >>", metadata.Version)))
return
}
banner := `
_____ _________.__ __
/ \ ____ ____ ____ / _____/| |__ _____ _______| | __
/ \ / \ / _ \ / _ \ / \ \_____ \ | | \\__ \\_ __ \ |/ /
/ Y ( <_> | <_> ) | \/ \| Y \/ __ \| | \/ <
\____|__ /\____/ \____/|___| /_______ /|___| (____ /__| |__|_ \ %s
\/ \/ \/ \/ \/ \/
`
fmt.Println(color.Blue(fmt.Sprintf(banner, metadata.Version)))
}

View File

@ -17,14 +17,11 @@ import (
"Moonshark/config" "Moonshark/config"
"Moonshark/http" "Moonshark/http"
"Moonshark/logger" "Moonshark/logger"
"Moonshark/metadata"
"Moonshark/router" "Moonshark/router"
"Moonshark/runner" "Moonshark/runner"
"Moonshark/runner/lualibs" "Moonshark/runner/lualibs"
"Moonshark/sessions" "Moonshark/sessions"
"Moonshark/watchers" "Moonshark/watchers"
fin "git.sharkk.net/Sharkk/Fin"
) )
type Moonshark struct { type Moonshark struct {
@ -282,36 +279,3 @@ func dirExists(path string) bool {
info, err := os.Stat(path) info, err := os.Stat(path)
return err == nil && info.IsDir() return err == nil && info.IsDir()
} }
func banner(scriptMode bool) {
if scriptMode {
fmt.Println(color.Blue(fmt.Sprintf("Moonshark %s << Script Mode >>", metadata.Version)))
return
}
banner := `
_____ _________.__ __
/ \ ____ ____ ____ / _____/| |__ _____ _______| | __
/ \ / \ / _ \ / _ \ / \ \_____ \ | | \\__ \\_ __ \ |/ /
/ Y ( <_> | <_> ) | \/ \| Y \/ __ \| | \/ <
\____|__ /\____/ \____/|___| /_______ /|___| (____ /__| |__|_ \ %s
\/ \/ \/ \/ \/ \/
`
fmt.Println(color.Blue(fmt.Sprintf(banner, metadata.Version)))
}
func readConfig(path string) *fin.Data {
file, err := os.Open(path)
if err != nil {
logger.Errorf("Failed to open config file %s, using defaults", color.Yellow(path))
return fin.NewData()
}
defer file.Close()
cfg, err := fin.Load(file)
if err != nil {
logger.Errorf("Failed to load config file %s, using defaults", color.Yellow(path))
}
return cfg
}