major rewrite work 1
This commit is contained in:
parent
ddb1d7c9d7
commit
a2d9b0ad9f
@ -12,7 +12,7 @@ type Config struct {
|
||||
Port int
|
||||
Debug bool
|
||||
HTTPLogging bool
|
||||
StaticPrefix string
|
||||
PublicPrefix string
|
||||
}
|
||||
|
||||
Runner struct {
|
||||
@ -21,7 +21,7 @@ type Config struct {
|
||||
|
||||
Dirs struct {
|
||||
Routes string
|
||||
Static string
|
||||
Public string
|
||||
FS string
|
||||
Data string
|
||||
Override string
|
||||
@ -40,12 +40,12 @@ func New(data *fin.Data) *Config {
|
||||
config.Server.Port = data.GetOr("server.port", 3117).(int)
|
||||
config.Server.Debug = data.GetOr("server.debug", false).(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.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.Data = data.GetOr("dirs.data", "data").(string)
|
||||
config.Dirs.Override = data.GetOr("dirs.override", "override").(string)
|
||||
|
103
http/server.go
103
http/server.go
@ -2,17 +2,14 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"Moonshark/color"
|
||||
"Moonshark/config"
|
||||
"Moonshark/logger"
|
||||
"Moonshark/metadata"
|
||||
"Moonshark/router"
|
||||
"Moonshark/runner"
|
||||
"Moonshark/sessions"
|
||||
"Moonshark/utils"
|
||||
@ -20,69 +17,11 @@ import (
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
var (
|
||||
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)
|
||||
)
|
||||
var emptyMap = make(map[string]any)
|
||||
|
||||
type Server struct {
|
||||
luaRouter *router.Router
|
||||
staticHandler fasthttp.RequestHandler
|
||||
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,
|
||||
func NewHttpServer(cfg *config.Config, handler fasthttp.RequestHandler, dbg bool) *fasthttp.Server {
|
||||
return &fasthttp.Server{
|
||||
Handler: handler,
|
||||
Name: "Moonshark/" + metadata.Version,
|
||||
ReadTimeout: 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,
|
||||
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 {
|
||||
@ -111,20 +68,6 @@ func (s *Server) handleRequest(ctx *fasthttp.RequestCtx) {
|
||||
method := string(ctx.Method())
|
||||
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
|
||||
bytecode, params, found := s.luaRouter.Lookup(method, path)
|
||||
if !found {
|
||||
|
105
main.go
Normal file
105
main.go
Normal 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)))
|
||||
}
|
36
moonshark.go
36
moonshark.go
@ -17,14 +17,11 @@ import (
|
||||
"Moonshark/config"
|
||||
"Moonshark/http"
|
||||
"Moonshark/logger"
|
||||
"Moonshark/metadata"
|
||||
"Moonshark/router"
|
||||
"Moonshark/runner"
|
||||
"Moonshark/runner/lualibs"
|
||||
"Moonshark/sessions"
|
||||
"Moonshark/watchers"
|
||||
|
||||
fin "git.sharkk.net/Sharkk/Fin"
|
||||
)
|
||||
|
||||
type Moonshark struct {
|
||||
@ -282,36 +279,3 @@ func dirExists(path string) bool {
|
||||
info, err := os.Stat(path)
|
||||
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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user