Skip to content

Latest commit

History

147 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

knot Logo

Knot is a web server and application container for Golang Web Based App. It is still on experimental version

Background

I've been working with Golang for sometime. While some stack are build on either command line or REST, I always use web based application as main UI. Most of the time, our application will be proxied by Nginx, and to be honest, it is complicated effort, because we have to change nginx config file and restart it whenever we have new application developed. These then inspired me to build Knot.

Usage

Load Knot

goget-ugithub.com/eaciit/knot

FnContent

In knot, we handle function based on FnContent contract. Where contract of FnContent is as follow

varFnContentfunc(*WebContext)interface{}

knot.WebContext is wrapper of KnotServer object, HttpRequest, Writer and other related context of Knot. Any data returned by this function will be used as body of the response depend on OutputType defined.

Route

To do routing in knot, is simply by invoke Route function

funcmain(){
knot.DefaultOutputType=knot.OutputHtmlks:=new(knot.Server)
ks.Route("hi",Hi)
ks.Listen()
}
funcHi(r*knot.WebContext)interface{}{
return"Hello World!"
}

Route to static folder

ks.RouteStatic("static","/Users/ariefdarmawan/Temp/knot/app1/static")

Start Knot as Single App Container

Below code will run knot on locahost:13000 and add 2 web method / and /stop

Manual Route

package main
import (
. "github.com/eaciit/knot/knot.v1"
)
funcmain() {
ks:=new(Server)
ks.Address="localhost:13000"DefaultOutputType=OutputHtmlks.Route("/", func(wc*WebContext) interface{} {
return"Welcome to Knot Server"
})
ks.Route("/stop", func(wc*WebContext) interface{} {
deferwc.Server.Stop()
return"Server will be stopped. Bye"
})
ks.Listen()
}

AutoRoute

Controller is a struct with sets of FnContent. Knot have ability to scan registered controller for FnContent function and autoregister them

Below code will define controller called as Hello with 3 functions: Morning, Evening and Night. But since Morning and Evening are only function match with FnContent contract, those 2 functions will be registered as RouteHandler.

// here is our controllertypeHellostruct{
}
// http://servername/hello/morningfunc (h*Hello) Morning(r*knot.WebContext) interface{}{
return"Good morning"
}
// http://servername/hello/eveningfunc (h*Hello) Evening(r*knot.WebContext) interface{}{
return"Good evening"
}
func (h*Hello) Night() interface{}{
return"Good Night"
}
funcmain(){
ks:=new(knot.Server)
ks.Register(new(Hello),"")
ks.Listen()
}

Start Knot as Single Application

To run knot as Single Application Container we need to do following:

  • Register application to run in Application Container
  • Start the app

appcontainer

package main
import (
"github.com/eaciit/kingpin""github.com/eaciit/knot/knot.v1"
)
typeHellostruct{
}
func (h*Hello) Say(k*knot.WebContext) interface{}{
return"Hello World"
}
funcmain() {
app:=knot.NewApplication("")
app.DefaultOutputType=knot.OutputHtmlapp.Register(&Hello{})
knot.RegisterApp(app)
knot.StartApp(app,"localhost:12345")
}

Start Knot as Multi Application Container

To run knot as Multiple Application Container we need to do following:

  • Register application to run in Application Container
  • Start the knot server

appcontainer

package main
import (
"github.com/eaciit/kingpin""github.com/eaciit/knot/knot.v1"// KnotApp Start// This is where we need to write down all application namespace // need to be run
_ "github.com/eaciit/knot/example/hello"// KnotApp End
)
var (
ks*knot.ServerflagAddress=kingpin.Flag("address",
"Address to be used by Knot Server. It normally formatted as SERVERNAME:PORTNUMBER").Default("localhost:9876").String()
)
funcmain() {
kingpin.Parse()
knot.DefaultOutputType=knot.OutputTemplate//--- it will run all application registered in namespaceknot.StartContainer(&knot.AppContainerConfig{
Address: *flagAddress,
})
}

create knot application

Now we need to create knot application that will be read by above daemon

package hello
import (
"github.com/eaciit/knot/knot.v1""github.com/eaciit/toolkit""os""time"
)
var (
//appViewsPath = "/Users/ariefdarmawan/goapp/src/github.com/eaciit/knot/example/hello/views/"appViewsPath=func() string {
d, _:=os.Getwd()
returnd
}() +"/../example/hello/views/"
)
funcinit() {
app:=knot.NewApp("Hello")
app.ViewsPath=appViewsPathapp.Register(&WorldController{})
app.Static("static", "/Users/ariefdarmawan/Temp")
app.LayoutTemplate="_template.html"knot.RegisterApp(app)
}
typeWorldControllerstruct {
}
func (w*WorldController) Say(r*knot.WebContext) interface{} {
r.Config.OutputType=knot.OutputHtmls:="<b>Hello World</b>&nbsp;"name:=r.Query("name")
ifname!="" {
s=s+" "+name
}
s+="</br>"returns
}
func (w*WorldController) Index(r*knot.WebContext) interface{} {
r.Config.ViewName="hello.html"return (toolkit.M{}).Set("message", "This data is sent to knot controller method")
}
...

Handling Session

typeTestControllerstruct{
}
func (c*TestController) Session(r*knot.WebContext) interface{}{
t0:=time.Now()
visitLength:=r.Session("VisitLength", 0).(int)
newVisitLength=visitLength+int(time.Since(t0))
r.SetSession("VisitLength",newVisitLength)
returnfmt.Sprintf("Old length: %v, new length: %v", time.Duration(visitLenght), time.Duration(newVisitLength))
}

Handling Cookie

typeWorldControllerstruct{
}
func (w*WorldController) Cookie(r*knot.WebContext) interface{} {
r.Config.OutputType=knot.OutputHtmlcvalue:=""cookiename:="mycookie"c, _:=r.Cookie(cookiename, "")
ifc==nil {
r.SetCookie(cookiename, "Arief Darmawan ", 30*24*time.Hour)
} else {
cvalue=c.Valuec.Value="Arief Darmawan "+time.Now().String()
c.Expires=time.Now().Add(24*30*time.Hour)
}
return"Cookie value is "+cvalue
}

Controller Validation

To enable validation

/* SetValidation enable session validation on a controller EnableDisable bool fnValidate validation process fnUrl url to be redirected if validation fail*/app.SetValidation(true, func(k*knot.WebContext)bool{
session:=k.Session("ecappsessionid")
ifsession==nil {
k.SetData("validationresult","nosession")
returnfalse
} elseif!checkSomething(session){
k.SetData("validationresult","noaccess")
returnfalse
}
returntrue
}, func(k*knot.WebContext) string {
vr:=k.Data("validationresult","").(string)
ifvr=="nosession" {
return"/home/login"
} else {
return"/page/noaccess"
}
}) 

and to ignore validation on specific controller

func (c*AController) MethodName(k*knot.WebContext)interface{}{
k.Config.IgnoreValidation=true...
}

Undocumented Feature

Below feature are available already on Knot, but not documented properly yet

  • Template
  • Json

About

Knot is a web server and application container for Golang Web Based App. It is still on experimental version

Resources

Stars

0 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages