137 lines
3.4 KiB
Go
137 lines
3.4 KiB
Go
package runner
|
|
|
|
import (
|
|
"Moonshark/router"
|
|
"Moonshark/runner/lualibs"
|
|
"Moonshark/sessions"
|
|
"Moonshark/utils"
|
|
"sync"
|
|
|
|
"maps"
|
|
|
|
"github.com/valyala/fasthttp"
|
|
)
|
|
|
|
// A prebuilt, ready-to-go context for HTTP requests to the runner.
|
|
type HTTPContext struct {
|
|
Values map[string]any // Contains all context data for Lua
|
|
|
|
// Separate maps for efficient access during context building
|
|
headers map[string]string
|
|
cookies map[string]string
|
|
query map[string]string
|
|
params map[string]string
|
|
form map[string]any
|
|
session map[string]any
|
|
env map[string]any
|
|
}
|
|
|
|
// HTTP context pool to reduce allocations
|
|
var httpContextPool = sync.Pool{
|
|
New: func() any {
|
|
return &HTTPContext{
|
|
Values: make(map[string]any, 32),
|
|
headers: make(map[string]string, 16),
|
|
cookies: make(map[string]string, 8),
|
|
query: make(map[string]string, 8),
|
|
params: make(map[string]string, 4),
|
|
form: make(map[string]any, 8),
|
|
session: make(map[string]any, 4),
|
|
env: make(map[string]any, 16),
|
|
}
|
|
},
|
|
}
|
|
|
|
// Get a clean HTTP context from the pool and build it up with an HTTP request, router params and session data
|
|
func NewHTTPContext(httpCtx *fasthttp.RequestCtx, params *router.Params, session *sessions.Session) *HTTPContext {
|
|
ctx := httpContextPool.Get().(*HTTPContext)
|
|
|
|
// Extract headers
|
|
httpCtx.Request.Header.VisitAll(func(key, value []byte) {
|
|
ctx.headers[string(key)] = string(value)
|
|
})
|
|
|
|
// Extract cookies
|
|
httpCtx.Request.Header.VisitAllCookie(func(key, value []byte) {
|
|
ctx.cookies[string(key)] = string(value)
|
|
})
|
|
|
|
// Extract query params
|
|
httpCtx.QueryArgs().VisitAll(func(key, value []byte) {
|
|
ctx.query[string(key)] = string(value)
|
|
})
|
|
|
|
// Extract route parameters
|
|
if params != nil {
|
|
for i := range min(len(params.Keys), len(params.Values)) {
|
|
ctx.params[params.Keys[i]] = params.Values[i]
|
|
}
|
|
}
|
|
|
|
// Extract form data if present
|
|
if httpCtx.IsPost() || httpCtx.IsPut() || httpCtx.IsPatch() {
|
|
if form, err := utils.ParseForm(httpCtx); err == nil {
|
|
maps.Copy(ctx.form, form)
|
|
}
|
|
}
|
|
|
|
// Extract session data
|
|
session.AdvanceFlash()
|
|
ctx.session["id"] = session.ID
|
|
if session.IsEmpty() {
|
|
ctx.session["data"] = emptyMap
|
|
ctx.session["flash"] = emptyMap
|
|
} else {
|
|
ctx.session["data"] = session.GetAll()
|
|
ctx.session["flash"] = session.GetAllFlash()
|
|
}
|
|
|
|
// Add environment vars
|
|
if envMgr := lualibs.GetGlobalEnvManager(); envMgr != nil {
|
|
maps.Copy(ctx.env, envMgr.GetAll())
|
|
}
|
|
|
|
// Populate Values with all context data
|
|
ctx.Values["method"] = string(httpCtx.Method())
|
|
ctx.Values["path"] = string(httpCtx.Path())
|
|
ctx.Values["host"] = string(httpCtx.Host())
|
|
ctx.Values["headers"] = ctx.headers
|
|
ctx.Values["cookies"] = ctx.cookies
|
|
ctx.Values["query"] = ctx.query
|
|
ctx.Values["params"] = ctx.params
|
|
ctx.Values["form"] = ctx.form
|
|
ctx.Values["session"] = ctx.session
|
|
ctx.Values["env"] = ctx.env
|
|
|
|
return ctx
|
|
}
|
|
|
|
// Clear out all the request data from the context and give it back to the pool.
|
|
func (c *HTTPContext) Release() {
|
|
clear(c.Values)
|
|
clear(c.headers)
|
|
clear(c.cookies)
|
|
clear(c.query)
|
|
clear(c.params)
|
|
clear(c.form)
|
|
clear(c.session)
|
|
clear(c.env)
|
|
|
|
httpContextPool.Put(c)
|
|
}
|
|
|
|
// Add a value to the extras section
|
|
func (c *HTTPContext) Set(key string, value any) {
|
|
c.Values[key] = value
|
|
}
|
|
|
|
// Get a value from the context
|
|
func (c *HTTPContext) Get(key string) any {
|
|
return c.Values[key]
|
|
}
|
|
|
|
// Returns the Values map directly - zero overhead
|
|
func (c *HTTPContext) ToMap() map[string]any {
|
|
return c.Values
|
|
}
|