Documentation ¶
Index ¶
- Constants
- Variables
- func LoadTranslations()
- type Context
- func (c *Context) AddHeader(key, value string)
- func (c *Context) BodyJson() map[string]any
- func (c *Context) BodyText() string
- func (c *Context) DeleteCookie(key string)
- func (c *Context) DeleteFile(path string) error
- func (c *Context) Download(data_bytes []byte, asFilename string)
- func (c *Context) EnableTranslations()
- func (c *Context) GetCookie(key string) (string, error)
- func (c *Context) GetUserIP() string
- func (c *Context) Html(template_name string, data map[string]any)
- func (c *Context) IsAuthenticated() bool
- func (c *Context) Json(data any)
- func (c *Context) JsonIndent(data any)
- func (c *Context) ParseMultipartForm(size ...int64) (formData url.Values, formFiles map[string][]*multipart.FileHeader)
- func (c *Context) QueryParam(name string) string
- func (c *Context) Redirect(path string)
- func (c *Context) ServeEmbededFile(content_type string, embed_file []byte)
- func (c *Context) ServeFile(content_type, path_to_file string)
- func (c *Context) SetCookie(key, value string)
- func (c *Context) SetHeader(key, value string)
- func (c *Context) SetStatus(statusCode int)
- func (c *Context) Status(code int) *Context
- func (c *Context) StreamResponse(response string) error
- func (c *Context) Text(body string)
- func (c *Context) UploadFile(received_filename, folder_out string, acceptedFormats ...string) (string, []byte, error)
- func (c *Context) UploadFiles(received_filenames []string, folder_out string, acceptedFormats ...string) ([]string, [][]byte, error)
- func (c *Context) User() models.User
- type Handler
- type M
- type Route
- type Router
- func (router *Router) AddEmbededTemplates(template_embed embed.FS, rootDir string) error
- func (router *Router) AddLocalTemplates(pathToDir string) error
- func (router *Router) DELETE(pattern string, handler Handler, allowed_origines ...string)
- func (r *Router) Embed(staticDir *embed.FS, templateDir *embed.FS)
- func (router *Router) GET(pattern string, handler Handler)
- func (router *Router) HEAD(pattern string, handler Handler, allowed_origines ...string)
- func (router *Router) HandlerFunc(method string, pattern string, handler http.HandlerFunc, allowed ...string)
- func (router *Router) LoadEnv(files ...string)
- func (router *Router) NewFuncMap(funcName string, function any)
- func (router *Router) OPTIONS(pattern string, handler Handler, allowed_origines ...string)
- func (router *Router) PATCH(pattern string, handler Handler, allowed_origines ...string)
- func (router *Router) POST(pattern string, handler Handler, allowed_origines ...string)
- func (router *Router) PUT(pattern string, handler Handler, allowed_origines ...string)
- func (router *Router) Run()
- func (router *Router) SSE(pattern string, handler Handler, allowed_origines ...string)
- func (router *Router) ServeEmbededDir(pathLocalDir string, embeded embed.FS, webPath string)
- func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (router *Router) ServeLocalDir(dirPath, webPath string)
- func (router *Router) UseMiddlewares(midws ...func(http.Handler) http.Handler)
- func (router *Router) WS(pattern string, wsHandler WsHandler, allowed_origines ...string)
- type WsContext
- func (c *WsContext) AddClient(key string)
- func (c *WsContext) Broadcast(data any) error
- func (c *WsContext) BroadcastExceptCaller(data map[string]any) error
- func (c *WsContext) Json(data map[string]any) error
- func (c *WsContext) ReceiveJson() (map[string]any, error)
- func (c *WsContext) ReceiveText() (string, error)
- func (c *WsContext) RemoveRequester(name ...string)
- func (c *WsContext) Text(data string) error
- type WsHandler
Constants ¶
const ( GET int = iota POST PUT PATCH DELETE HEAD OPTIONS WS SSE )
Variables ¶
var ( CORSDebug = false ReadTimeout = 5 * time.Second WriteTimeout = 20 * time.Second IdleTimeout = 20 * time.Second )
var Admin = func(handler Handler) Handler { const key utils.ContextKey = "user" return func(c *Context) { session, err := c.GetCookie("session") if err != nil || session == "" { c.DeleteCookie("session") http.Redirect(c.ResponseWriter, c.Request, "/admin/login", http.StatusTemporaryRedirect) return } if SESSION_ENCRYPTION { session, err = encryptor.Decrypt(session) if err != nil { c.Status(http.StatusTemporaryRedirect).Redirect("/admin/login") return } } user, err := orm.Model[models.User]().Where("uuid = ?", session).One() if err != nil { c.Status(http.StatusTemporaryRedirect).Redirect("/admin/login") return } if !user.IsAdmin { c.Status(403).Text("Middleware : Not allowed to access this page") return } ctx := context.WithValue(c.Request.Context(), key, user) *c = Context{ ResponseWriter: c.ResponseWriter, Request: c.Request.WithContext(ctx), Params: c.Params, } handler(c) } }
var Auth = func(handler Handler) Handler { const key utils.ContextKey = "user" return func(c *Context) { session, err := c.GetCookie("session") if err != nil || session == "" { c.DeleteCookie("session") handler(c) return } if SESSION_ENCRYPTION { session, err = encryptor.Decrypt(session) if err != nil { handler(c) return } } user, err := orm.Model[models.User]().Where("uuid = ?", session).One() if err != nil { handler(c) return } ctx := context.WithValue(c.Request.Context(), key, user) *c = Context{ ResponseWriter: c.ResponseWriter, Request: c.Request.WithContext(ctx), Params: c.Params, } handler(c) } }
AuthMiddleware can be added to any handler to get user cookie authentication and pass it to handler and templates
var BasicAuth = func(next Handler, user, pass string) Handler { return func(c *Context) { username, password, ok := c.Request.BasicAuth() if ok { usernameHash := sha256.Sum256([]byte(username)) passwordHash := sha256.Sum256([]byte(password)) expectedUsernameHash := sha256.Sum256([]byte(user)) expectedPasswordHash := sha256.Sum256([]byte(pass)) usernameMatch := (subtle.ConstantTimeCompare(usernameHash[:], expectedUsernameHash[:]) == 1) passwordMatch := (subtle.ConstantTimeCompare(passwordHash[:], expectedPasswordHash[:]) == 1) if usernameMatch && passwordMatch { next(c) return } } c.ResponseWriter.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`) http.Error(c.ResponseWriter, "Unauthorized", http.StatusUnauthorized) } }
var COOKIE_EXPIRE = time.Now().Add(7 * 24 * time.Hour)
COOKIE_EXPIRE global cookie expiry time
var CORS = func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Headers:", "*") w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "*") if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) return } next.ServeHTTP(w, r) }) }
var CSRF = func(handler http.Handler) http.Handler { tokBytes := make([]byte, 64) _, err := io.ReadFull(rand.Reader, tokBytes) logger.CheckError(err) massToken := csrf.MaskToken(tokBytes) toSendToken := base64.StdEncoding.EncodeToString(massToken) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { token := r.Header.Get("X-CSRF-Token") if token == "" { http.SetCookie(w, &http.Cookie{ Name: "csrf_token", Value: toSendToken, Path: "/", Expires: time.Now().Add(1 * time.Hour), Secure: true, SameSite: http.SameSiteStrictMode, }) } } else if r.Method == "POST" { token := r.Header.Get("X-CSRF-Token") if !csrf.VerifyToken(token, toSendToken) { w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]interface{}{ "error": "CSRF not allowed", }) return } } handler.ServeHTTP(w, r) }) }
var GZIP = func(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if strings.Contains(r.URL.Path, "metrics") { handler.ServeHTTP(w, r) return } for _, header := range r.Header["Upgrade"] { if header == "websocket" { handler.ServeHTTP(w, r) return } } if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { gwriter := gzip.NewWrappedResponseWriter(w) defer gwriter.Flush() gwriter.Header().Set("Content-Encoding", "gzip") handler.ServeHTTP(gwriter, r) return } handler.ServeHTTP(w, r) }) }
var LIMITER = func(next http.Handler) http.Handler { var limiter = rate.NewLimiter(1, LIMITER_TOKENS) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { v, ok := banned.Load(r.RemoteAddr) if ok { if time.Since(v.(time.Time)) > LIMITER_TIMEOUT { banned.Delete(r.RemoteAddr) } else { w.WriteHeader(http.StatusTooManyRequests) w.Write([]byte("<h1>YOU DID TOO MANY REQUEST, YOU HAVE BEEN BANNED FOR 5 MINUTES </h1>")) banned.Store(r.RemoteAddr, time.Now()) return } } if !limiter.Allow() { w.WriteHeader(http.StatusTooManyRequests) w.Write([]byte("<h1>YOU DID TOO MANY REQUEST, YOU HAVE BEEN BANNED FOR 5 MINUTES </h1>")) banned.Store(r.RemoteAddr, time.Now()) return } next.ServeHTTP(w, r) }) }
var LIMITER_TIMEOUT = 5 * time.Minute
var LIMITER_TOKENS = 50
var LOGS = func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if utils.StringContains(r.URL.Path, "metrics", "sw.js", "favicon", "/static/", "/sse/", "/ws/", "/wss/") { h.ServeHTTP(w, r) return } for _, header := range r.Header["Upgrade"] { if header == "websocket" { h.ServeHTTP(w, r) return } } recorder := &logs.StatusRecorder{ ResponseWriter: w, Status: 200, } t := time.Now() h.ServeHTTP(recorder, r) res := fmt.Sprintf("[%s] --> '%s' --> [%d] from: %s ---------- Took: %v", r.Method, r.URL.Path, recorder.Status, r.RemoteAddr, time.Since(t)) if recorder.Status >= 200 && recorder.Status < 400 { fmt.Printf(logger.Green, res) } else if recorder.Status >= 400 || recorder.Status < 200 { fmt.Printf(logger.Red, res) } else { fmt.Printf(logger.Yellow, res) } if settings.Config.Logs { logger.StreamLogs = append(logger.StreamLogs, res) eventbus.Publish("internal-logs", map[string]string{}) } }) }
var MultipartSize = 10 << 20
var RECOVERY = func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { err := recover() if err != nil { logger.Error(err) jsonBody, _ := json.Marshal(map[string]string{ "error": "There was an internal server error", }) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) w.Write(jsonBody) } }() next.ServeHTTP(w, r) }) }
var SESSION_ENCRYPTION = true
var Static embed.FS
var Templates embed.FS
Functions ¶
func LoadTranslations ¶
func LoadTranslations()
Types ¶
type Context ¶
type Context struct { http.ResponseWriter *http.Request Params map[string]string // contains filtered or unexported fields }
Context is a wrapper of responseWriter, request, and params map
func (*Context) BodyJson ¶ added in v0.5.2
BodyJson get json body from request and return map USAGE : data := c.BodyJson(r)
func (*Context) DeleteCookie ¶
DeleteCookie delete cookie with specific key
func (*Context) Download ¶
Download download data_bytes(content) asFilename(test.json,data.csv,...) to the client
func (*Context) EnableTranslations ¶
func (c *Context) EnableTranslations()
EnableTranslations get user ip, then location country using nmap, so don't use it if u don't have it install, and then it parse csv file to find the language spoken in this country, to finaly set cookie 'lang' to 'en' or 'fr'...
func (*Context) IsAuthenticated ¶ added in v0.7.7
func (*Context) JsonIndent ¶ added in v0.6.0
JsonIndent return json indented to the client
func (*Context) ParseMultipartForm ¶ added in v1.0.9
func (*Context) QueryParam ¶
QueryParam get query param
func (*Context) Redirect ¶ added in v0.6.0
Redirect redirect the client to the specified path with a custom code
func (*Context) ServeEmbededFile ¶
ServeEmbededFile serve an embeded file from handler
func (*Context) SetHeader ¶ added in v0.6.5
SetHeader Set the header value to the new value, old removed
func (*Context) SetStatus ¶ added in v0.7.8
SetHeader Set the header value to the new value, old removed
func (*Context) StreamResponse ¶
StreamResponse send SSE Streaming Response
func (*Context) UploadFile ¶
func (c *Context) UploadFile(received_filename, folder_out string, acceptedFormats ...string) (string, []byte, error)
UploadFile upload received_filename into folder_out and return url,fileByte,error
func (*Context) UploadFiles ¶ added in v0.5.0
type Route ¶
type Route struct { Method string Pattern *regexp.Regexp Handler WsHandler Clients map[string]*websocket.Conn AllowedOrigines []string }
Route
type Router ¶
Router
func (*Router) AddEmbededTemplates ¶
func (*Router) AddLocalTemplates ¶
func (*Router) HandlerFunc ¶ added in v1.0.9
func (router *Router) HandlerFunc(method string, pattern string, handler http.HandlerFunc, allowed ...string)
HandlerFunc support standard library http.HandlerFunc
func (*Router) NewFuncMap ¶
func (*Router) ServeEmbededDir ¶
func (*Router) ServeHTTP ¶
func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP serveHTTP by handling methods,pattern,and params
func (*Router) ServeLocalDir ¶
func (*Router) UseMiddlewares ¶
UseMiddlewares chain global middlewares applied on the router
type WsContext ¶
func (*WsContext) BroadcastExceptCaller ¶
BroadcastExceptCaller send message to all clients in c.Clients
func (*WsContext) ReceiveJson ¶
ReceiveJson receive json from ws and disconnect when stop receiving
func (*WsContext) ReceiveText ¶
ReceiveText receive text from ws and disconnect when stop receiving
func (*WsContext) RemoveRequester ¶
RemoveRequester remove the client from Clients list in context