Skip to content

GeraldWodni/kern.go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

kern.go

Web-framework for web-applications. The biggest implementation of kern is currently written for node.js.

As I needed a framework in go for developing kubernetes controllers, I decided to start this minimalistic port.

Demo

A simple demo application can be found in the demo-repository

tl;dr demo

package main
import (
    "github.com/GeraldWodni/kern.go"
    "github.com/GeraldWodni/kern.go/view"
)
func main() {
    app := kern.New(":5000")
    view.Globals["AppName"] = "kern.go demo app"
    app.Router.Get("/", view.NewHandler( "index.gohtml" ) )
    app.Run()
}

Fresh looks (fully responsive):

login

logout


Documentation


kern

kern.go main include, see the demo repository for a full demo.

Usage

type Kern

type Kern struct {
	Router    *router.Router
	Hierarchy *hierarchy.Hierarchy
	BindAddr  string
}

func New

func New(bindAddr string, hierarchyPrefixes []string) (kern *Kern)

Kern instance hosted on bindAddr Hint: mounts /favicon.ico, /css, /js, /images, /files from /default/*

func (*Kern) Run

func (kern *Kern) Run()

Run http.ListenAndServe for Kern instance


router

Routers provide simple separation of mountable modules. This provides a reusability of code, i.e. a webshop can run standalone when mounted under "/", or by mounted under "/shop" of a full featured website.

Usage

func Err

func Err(res http.ResponseWriter, err error)

Render an error as status code 500

type Route

type Route struct {
	Method  string
	Path    string
	Handler RouteHandler
}

type RouteHandler

type RouteHandler func(res http.ResponseWriter, req *http.Request, next RouteNext)

Extend the (res, req) handler interface with a resume-route callback

func ErrHandler

func ErrHandler(err error) RouteHandler

Wrapper for Err, provides a RouteHandler for convenience see view/view.go for example usage

type RouteNext

type RouteNext func()

Callback function if a RouteHandler was a match but routing should continue

type Router

type Router struct {
	// optionally identify router per name
	Name            string
	MountPoint      string
	Routes          []Route
	NotFoundHandler RouteHandler
}

func New

func New(mountPoint string) (router *Router)

New router with it's mountpoint fixed. Hint: use this function when creating mountable modules which return their own router.

func (*Router) Add

func (router *Router) Add(method string, path string, handler RouteHandler)

Add RouteHandler with explicit method mounted at path. Use All, Get OR Post unless crazy methods are required

func (*Router) All

func (router *Router) All(path string, handler RouteHandler)

Match all methods on path

func (*Router) Get

func (router *Router) Get(path string, handler RouteHandler)

Match all GET requests on path

func (*Router) HierarchyDir

func (router *Router) HierarchyDir(h *hierarchy.Hierarchy, path string)

Serve file after hierarchy lookup

func (*Router) Mount

func (router *Router) Mount(subRouter *Router)

Mount router created by New on existing router i.e. app.Router

func (*Router) NewMounted

func (router *Router) NewMounted(mountPoint string) (subRouter *Router)

Wrapper to create a mounted router. Hint: use when implementing a simple tree-navigation in an app

func (*Router) Post

func (router *Router) Post(path string, handler RouteHandler)

Match all POST requests on path

func (*Router) ServeHTTP

func (router *Router) ServeHTTP(res http.ResponseWriter, req *http.Request)

Gets called by http, not to be used by app

func (*Router) StaticDir

func (router *Router) StaticDir(path string, dir string)

FileServer wrapper for exposing the contents of dir under path

func (*Router) StaticFile

func (router *Router) StaticFile(path string, contentType string, filename string)

Provide a static file. Kern automatically provides a favicon via this function:

kern.Router.StaticFile( "/favicon.ico", "image/x-icon", "./default/images/favicon.ico" )

func (*Router) StaticHtml

func (router *Router) StaticHtml(path string, html string)

Send html with the correct mimetype Example:

router.StaticHtml( '<html><body><h1>Oh noes!, something went terribly wrong</h1></body></html>' )

Hint: usefull for static error messages which need a bit of formatting, use view.View for all else.

func (*Router) StaticText

func (router *Router) StaticText(path string, text string)

Send text with the correct mimetype


view

Provides a wrapper class around html.template. Loaded templates are kept in cache but watched with fsnotify which invalidates the cache and forces a read on the next Render

Usage

var Globals = make(InterfaceMap)

Available to all templates, i.e. `{{.Globals.FooBar}}

func Handler

func Handler(view ViewInterface) (routeHandler router.RouteHandler)

Wrapper for Render using a router.RouteHandler

func NewCssHandler

func NewCssHandler(filenames ...string) (routeHandler router.RouteHandler)

func NewHtmlHandler

func NewHtmlHandler(filenames ...string) (routeHandler router.RouteHandler)

Load a view and directly return router.RouteHandler Hint: useful for views without locals

func NewTextHandler

func NewTextHandler(contentType string, filenames ...string) (routeHandler router.RouteHandler)

type FuncMap

type FuncMap map[string]any

Pipeline functions exposed to template

type HtmlView

type HtmlView struct {
	View
	Template *htmlTemplate.Template
}

func NewHtml

func NewHtml(filenames ...string) (view *HtmlView, err error)

Creates a new View which is immidiatly loaded and watched for file changes

func (*HtmlView) Render

func (view *HtmlView) Render(res http.ResponseWriter, req *http.Request, next router.RouteNext, locals interface{})

Render view using Globals as well as values passed via locals

type InterfaceMap

type InterfaceMap map[string]interface{}

type Message

type Message struct {
	Type  string // TODO: make enum?
	Title string
	Text  string
}

type TextView

type TextView struct {
	View
	Template *textTemplate.Template
}

func NewText

func NewText(contentType string, filenames ...string) (view *TextView, err error)

func (*TextView) Render

func (view *TextView) Render(res http.ResponseWriter, req *http.Request, next router.RouteNext, locals interface{})

type View

type View struct {
	Filenames      []string
	ReloadRequired bool
	TemplateName   string

	ContentType string
}

type ViewInterface

type ViewInterface interface {
	Render(http.ResponseWriter, *http.Request, router.RouteNext, interface{})
	// contains filtered or unexported methods
}

type ViewTemplate

type ViewTemplate interface {
	Execute(w io.Writer, data any) error
	ExecuteTemplate(w io.Writer, template string, data any) error
}

hierarchy

Hierarchical lookup for pathes. Instead of a hardcoded path, a list of directories is traversed to allow for easy extension and subvolume-mounting.

Usage

type Hierarchy

type Hierarchy struct {
	Prefixes []string
}

func New

func New(prefixes []string) (hierarchy *Hierarchy, err error)

Creates a new Hierarchy with a list of prefixes; hint: default is automatically appended.

func (*Hierarchy) Exists

func (hierarchy *Hierarchy) Exists(prefix string, suffix string) (ok bool)

func (*Hierarchy) Lookup

func (hierarchy *Hierarchy) Lookup(suffixes ...string) (filename string, ok bool)

lookup with optional fail

func (*Hierarchy) LookupDirectory

func (hierarchy *Hierarchy) LookupDirectory(suffixes ...string) (filenames []string, ok bool)

load contents of folder and allow hierarchical overwriting

func (*Hierarchy) LookupFatal

func (hierarchy *Hierarchy) LookupFatal(suffixes ...string) (filename string)

lookup with fatal fail

func (*Hierarchy) LookupFile

func (hierarchy *Hierarchy) LookupFile(prefix string, suffix string) (filename string, ok bool)

redis

provides a redis connection wrapper around each request

Hint: this module is implitly loaded by session.

Usage

func Of

func Of(req *http.Request) (rdb redis.Conn, ok bool)

get redis connection from request-context i.e. redis.Of( req ).Do( "SET", "Lana", "aaaaaaaaa" )


filter

sanitize input - all unwanted characters are removed

HINT: always use theese functions for receiving user input. Only access the input directly if you are certain there is no other way.

Usage

func Address

func Address(t string) string

func Allocnum

func Allocnum(t string) string

func Alnum

func Alnum(t string) string

func AlnumList

func AlnumList(t string) string

func Alpha

func Alpha(t string) string

func Boolean

func Boolean(t string) string

func Color

func Color(t string) string

func DateTime

func DateTime(t string) string

func Decimal

func Decimal(t string) string

func Email

func Email(t string) string

func EscapedLink

func EscapedLink(t string) string

func Filename

func Filename(t string) string

func Filepath

func Filepath(t string) string

func Hex

func Hex(t string) string

func Id

func Id(t string) string

func Int

func Int(t string) string

func Link

func Link(t string) string

func LinkItem

func LinkItem(t string) string

func LinkList

func LinkList(t string) string

func Password

func Password(t string) string

func Post

func Post(req *http.Request, filter Filter) string

Get PostValue from request, using the lowecase filter-name as name

func PostName

func PostName(req *http.Request, name string, filter Filter) string

Get PostValue from request and sanizie it )

func Raw

func Raw(t string) string

func SingleLine

func SingleLine(t string) string

func Telephone

func Telephone(t string) string

func Text

func Text(t string) string

func Uint

func Uint(t string) string

func Url

func Url(t string) string

func Username

func Username(t string) string

type Filter

type Filter func(text string) string

session

session management - via a single cookie

Usage

func Destroy

func Destroy(res http.ResponseWriter, req *http.Request)

Destroy existing session

func NewSessionId

func NewSessionId() (sessionId string)

type Session

type Session struct {
	Id     string
	Values map[string]string

	// logged in username
	Username    string
	LoggedIn    bool
	Permissions string
}

func New

func New(res http.ResponseWriter, req *http.Request) (session *Session)

Start a new session

func Of

func Of(req *http.Request) (session *Session, ok bool)

get session for request-context i.e. session.Of( req ).Id


module

module interfaces - implement proper module for easy extension of kern.go

see session.sessionModule for a simple example

Usage

func ExecuteEndRequest

func ExecuteEndRequest(res http.ResponseWriter, req *http.Request)

Called internally by Router

func ExecuteStartRequest

func ExecuteStartRequest(res http.ResponseWriter, reqIn *http.Request) (reqOut *http.Request, ok bool)

Called internally by Router

func RegisterRequest

func RegisterRequest(requestModule Request)

type Request

type Request interface {
	// Executed upon request start. Returns a new `http.request` - usually `reqIn` wrapped in a new `Context`.
	// if `ok` is false, all further request handling will be stopped, handler needs to write `res` himself
	StartRequest(res http.ResponseWriter, reqIn *http.Request) (reqOut *http.Request, ok bool)
	// Executed upon exit of request
	EndRequest(res http.ResponseWriter, req *http.Request)
}

Request-modules are invoked upon every request


login

environment variable based login credentials (useful for docker images in i.e. kubernetes)

login - handler rejects further routing and displays login form

static credentials, recommended only for developement purposes

Usage

func NewEnvironmentCredentialChecker

func NewEnvironmentCredentialChecker() *envCredentials

Load users from environment variables, the prefixes are KERN_USER_ and KERN_PREMISSIONS_. Example values: KERN_USER_bob=soopersecret KERN_PERMISSIONS_bob=view,add,peel For usage call: login.Register( login.NewEnvironmentCredentialChecker() )

func NewStaticCredentials

func NewStaticCredentials(username string, password string, permissions string) *staticCredentials

Static credentials (recommended for developement purposes only) Example: ``

func PermissionReqired

func PermissionReqired(path string, permission string) (loginRouter *router.Router)

Stops all further routing when permission is not held by current session. Displays loginView (login.gohtml) when no session is found

func Register

func Register(credentialChecker CredentialChecker)

type CredentialChecker

type CredentialChecker interface {
	Check(username string, password string) (permissions string, ok bool)
}

type User

type User struct {
	Username    string
	Password    string
	Permissions string
}

user management (static)

func (*User) String

func (user *User) String() string

logout

logout - router destroys any session and warns otherwise

Usage

func Logout

func Logout(path string) (logoutRouter *router.Router)

Stops all further routing when permission is not held by current session. Displays logoutView (logout.gohtml) when no session is found


log

Colorful logger interface which UTC timestampts and multi-level severity

Usage

var Colors = map[string]string{
	"Reset": "\x1b[0m",

	"Black":   "\x1b[30m",
	"Red":     "\x1b[31m",
	"Green":   "\x1b[32m",
	"Yellow":  "\x1b[33m",
	"Blue":    "\x1b[34m",
	"Magenta": "\x1b[35m",
	"Cyan":    "\x1b[36m",
	"White":   "\x1b[37m",

	"BrightBlack":   "\x1b[1;30m",
	"BrightRed":     "\x1b[1;31m",
	"BrightGreen":   "\x1b[1;32m",
	"BrightYellow":  "\x1b[1;33m",
	"BrightBlue":    "\x1b[1;34m",
	"BrightMagenta": "\x1b[1;35m",
	"BrightCyan":    "\x1b[1;36m",
	"BrightWhite":   "\x1b[1;37m",
}
var LevelDebug = Colors["BrightBlack"]
var LevelError = Colors["BrightRed"]
var LevelFatal = Colors["Red"]
var LevelInfo = Colors["BrightBlue"]
var LevelSection = Colors["BrightMagenta"]
var LevelSubSection = Colors["BrightCyan"]
var LevelSuccess = Colors["BrightGreen"]
var LevelWarning = Colors["BrightYellow"]

func Debug

func Debug(a ...interface{})

func Debugf

func Debugf(format string, a ...interface{})

func Error

func Error(a ...interface{})

func Errorf

func Errorf(format string, a ...interface{})

func Fatal

func Fatal(a ...interface{})

func Info

func Info(a ...interface{})

func Infof

func Infof(format string, a ...interface{})

func Log

func Log(level string, a ...interface{})

func Logf

func Logf(level string, format string, a ...interface{})

func Section

func Section(a ...interface{})

func Sectionf

func Sectionf(format string, a ...interface{})

func SubSection

func SubSection(a ...interface{})

func SubSectionf

func SubSectionf(format string, a ...interface{})

func Success

func Success(a ...interface{})

func Successf

func Successf(format string, a ...interface{})

func Warning

func Warning(a ...interface{})

func Warningf

func Warningf(format string, a ...interface{})

About

WebFramwork for WebApplications

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published