major rewrite work 1
This commit is contained in:
parent
ddb1d7c9d7
commit
a2d9b0ad9f
@ -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)
|
||||||
|
103
http/server.go
103
http/server.go
@ -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
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/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
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user