goku: github.com/QLeelulu/goku Index | Files | Directories

package goku

import "github.com/QLeelulu/goku"

a golang web mvc framework, mostly like asp.net mvc. Base Features:

+ mvc (Lightweight model)
+ route
+ multi template engine and layout
+ simple database api
+ form validation
+ filter for controller or action
+ middleware

Example:

package main

import (
    "github.com/QLeelulu/goku"
    "log"
    "path"
    "runtime"
)

/**
 * Controller & Action
 */
var _ = goku.Controller("home").
    Get("index", func(ctx *goku.HttpContext) goku.ActionResulter {
    return ctx.Html("Hello World")
})

// routes
var routes []*goku.Route = []*goku.Route{
    &goku.Route{
        Name:    "default",
        Pattern: "/{controller}/{action}/",
        Default: map[string]string{"controller": "home", "action": "index"},
    },
}

// server config
var config *goku.ServerConfig = &goku.ServerConfig{Addr: ":8080"}

func init() {
    // project root dir, this code can not put to main func
    _, filename, _, _ := runtime.Caller(1)
    config.RootDir = path.Dir(filename)
}

func main() {
    rt := &goku.RouteTable{Routes: routes}
    s := goku.CreateServer(rt, nil, config)

    goku.Logger().Logln("Server start on", s.Addr)
    log.Fatal(s.ListenAndServe())
}

Index

Package Files

db.go filter.go viewengine.go middleware.go doc.go controller.go route.go actionresult.go httpcontext.go log.go server.go devhelper.go

Constants

const (
    LOG_LEVEL_NO = iota
    LOG_LEVEL_ERROR
    LOG_LEVEL_WARN
    LOG_LEVEL_NOTICE
    LOG_LEVEL_LOG
)

func GetVersion

func GetVersion() string

func Logger

func Logger() logger

func SetGlobalViewData

func SetGlobalViewData(key string, val interface{})

add a view data to the global, that all the view can use it by {{.Global.key}}

func SetLogger

func SetLogger(l logger)

type ActionInfo

type ActionInfo struct {
    Name       string
    Controller *ControllerInfo
    Handler    func(ctx *HttpContext) ActionResulter
    Filters    []Filter
}

info about the action

func (*ActionInfo) AddFilters

func (ai *ActionInfo) AddFilters(filters ...Filter)

add filters to the action

type ActionResult

type ActionResult struct {
    StatusCode int
    Headers    map[string]string
    Body       *bytes.Buffer
    // contains filtered or unexported fields
}

func (*ActionResult) ExecuteResult

func (ar *ActionResult) ExecuteResult(ctx *HttpContext)

type ActionResulter

type ActionResulter interface {
    ExecuteResult(ctx *HttpContext)
}

type ContentResult

type ContentResult struct {
    FilePath string
}

func (*ContentResult) ExecuteResult

func (cr *ContentResult) ExecuteResult(ctx *HttpContext)

type ControllerBuilder

type ControllerBuilder struct {
    // contains filtered or unexported fields
}

for build controller and action

func Controller

func Controller(name string) *ControllerBuilder

get a controller builder that the controller named "name" for reg actions and filters

func (*ControllerBuilder) Action

func (cb *ControllerBuilder) Action(httpMethod string, actionName string,
    handler func(ctx *HttpContext) ActionResulter) *ControllerBuilder

@param httpMethod: if "all", will match all http method, but Priority is low The return value is the ControllerBuilder, so calls can be chained

func (*ControllerBuilder) Delete

func (cb *ControllerBuilder) Delete(httpMethod string, actionName string,
    handler func(ctx *HttpContext) ActionResulter) *ControllerBuilder

reg http "delete" method action The return value is the ControllerBuilder, so calls can be chained

func (*ControllerBuilder) Filters

func (cb *ControllerBuilder) Filters(filters ...Filter) *ControllerBuilder

The return value is the ControllerBuilder, so calls can be chained

func (*ControllerBuilder) Get

func (cb *ControllerBuilder) Get(actionName string,
    handler func(ctx *HttpContext) ActionResulter) *ControllerBuilder

reg http "get" method action The return value is the ControllerBuilder, so calls can be chained

func (*ControllerBuilder) Post

func (cb *ControllerBuilder) Post(actionName string,
    handler func(ctx *HttpContext) ActionResulter) *ControllerBuilder

reg http "post" method action The return value is the ControllerBuilder, so calls can be chained

func (*ControllerBuilder) Put

func (cb *ControllerBuilder) Put(httpMethod string, actionName string,
    handler func(ctx *HttpContext) ActionResulter) *ControllerBuilder

reg http "put" method action The return value is the ControllerBuilder, so calls can be chained

type ControllerFactory

type ControllerFactory struct {
    Controllers map[string]*ControllerInfo
}

for get action in the registered controllers

func (*ControllerFactory) GetAction

func (cf *ControllerFactory) GetAction(httpMethod string, controller string, action string) *ActionInfo

type ControllerInfo

type ControllerInfo struct {
    Name    string
    Actions map[string]*ActionInfo
    Filters []Filter
}

hold the info about controller's actions and filters

func (*ControllerInfo) AddActionFilters

func (ci *ControllerInfo) AddActionFilters(httpMethod string, actionName string, filters ...Filter)

add filters for the controller

func (*ControllerInfo) AddFilters

func (ci *ControllerInfo) AddFilters(filters ...Filter)

add filters for the controller

func (*ControllerInfo) GetAction

func (ci *ControllerInfo) GetAction(method string, name string) *ActionInfo

get a action e.g. ci.GetAction("get", "index"), will found the registered action "index" for http method "get" in this controller, if not found, will found the action "index" for all the http method

func (*ControllerInfo) Init

func (ci *ControllerInfo) Init() *ControllerInfo

func (*ControllerInfo) RegAction

func (ci *ControllerInfo) RegAction(httpMethod string, actionName string,
    handler func(ctx *HttpContext) ActionResulter) *ActionInfo

register a action to the controller

type DB

type DB struct {
    sql.DB
    // if Debug set to true,
    // will print the sql
    Debug bool
}

base db

func (*DB) Count

func (db *DB) Count(table string, where string, whereParams ...interface{}) (count int64, err error)

func (*DB) Delete

func (db *DB) Delete(table string, where string, params ...interface{}) (result sql.Result, err error)

func (*DB) Exec

func (db *DB) Exec(query string, args ...interface{}) (sql.Result, error)

func (*DB) GetStruct

func (db *DB) GetStruct(s interface{}, where string, params ...interface{}) error

query by s and set the result value to s field mapping rule is: HelloWorld => hello_world mean that struct's field "HelloWorld" in database table's field is "hello_world" table name mapping use the same rule as field

func (*DB) GetStructs

func (db *DB) GetStructs(slicePtr interface{}, qi SqlQueryInfo) error

query by s and return a slice by type s field mapping rule is: HelloWorld => hello_world mean that struct's field "HelloWorld" in database table's field is "hello_world" table name mapping use the same rule as field @param slicePtr: a pointer to a slice

var blogs []Blog
err := db.GetStructs(&blogs, SqlQueryInfo{})

func (*DB) Insert

func (db *DB) Insert(table string, vals map[string]interface{}) (result sql.Result, err error)

insert into table with values from vals Example:

data := map[string]interface{}{
    "title": "hello golang",
    "content": "just wonderful",
}
rerult, err := db.Insert("blog", data)
id, err := result.LastInsertId()

func (*DB) InsertStruct

func (db *DB) InsertStruct(i interface{}) (sql.Result, error)

insert struct to database if i is pointer to struct and has a int type field named "Id" the field "Id" will set to the last insert id if has LastInsertId

field mapping rule is: HelloWorld => hello_world mean that struct's field "HelloWorld" in database table's field is "hello_world" table name mapping use the same rule as field

func (*DB) Query

func (db *DB) Query(query string, args ...interface{}) (*sql.Rows, error)

func (*DB) QueryRow

func (db *DB) QueryRow(query string, args ...interface{}) *sql.Row

func (*DB) Select

func (db *DB) Select(table string, qi SqlQueryInfo) (*sql.Rows, error)

select from db.table with qi Example:

qi := &SqlQueryInfo{
        Fields: "*",
        Where: "id > ?",
        Params: []interface{}{ 3 }
        Limit: 10,
        Offset: 0,
        Group: "age",
        Order: "id desc",
}
rows, err := db.Select("blog", qi)

func (*DB) Update

func (db *DB) Update(table string, vals map[string]interface{}, where string, whereParams ...interface{}) (result sql.Result, err error)

type DefaultLogger

type DefaultLogger struct {
    Logger    *log.Logger
    LOG_LEVEL int
}

func (*DefaultLogger) Error

func (l *DefaultLogger) Error(args ...interface{})

func (*DefaultLogger) Errorf

func (l *DefaultLogger) Errorf(format string, args ...interface{})

func (*DefaultLogger) Errorln

func (l *DefaultLogger) Errorln(args ...interface{})

func (*DefaultLogger) Log

func (l *DefaultLogger) Log(args ...interface{})

func (*DefaultLogger) LogLevel

func (l *DefaultLogger) LogLevel() int

func (*DefaultLogger) Logf

func (l *DefaultLogger) Logf(format string, args ...interface{})

func (*DefaultLogger) Logln

func (l *DefaultLogger) Logln(args ...interface{})

func (*DefaultLogger) Notice

func (l *DefaultLogger) Notice(args ...interface{})

func (*DefaultLogger) Noticef

func (l *DefaultLogger) Noticef(format string, args ...interface{})

func (*DefaultLogger) Noticeln

func (l *DefaultLogger) Noticeln(args ...interface{})

func (*DefaultLogger) Warn

func (l *DefaultLogger) Warn(args ...interface{})

func (*DefaultLogger) Warnf

func (l *DefaultLogger) Warnf(format string, args ...interface{})

func (*DefaultLogger) Warnln

func (l *DefaultLogger) Warnln(args ...interface{})

type DefaultMiddlewareHandle

type DefaultMiddlewareHandle struct {
    Middlewares []Middlewarer
}

the defaultmiddleware handler

func (*DefaultMiddlewareHandle) AddMiddleware

func (mh *DefaultMiddlewareHandle) AddMiddleware(mw Middlewarer)

func (*DefaultMiddlewareHandle) BeginMvcHandle

func (mh *DefaultMiddlewareHandle) BeginMvcHandle(ctx *HttpContext) (ar ActionResulter, err error)

func (*DefaultMiddlewareHandle) BeginRequest

func (mh *DefaultMiddlewareHandle) BeginRequest(ctx *HttpContext) (ar ActionResulter, err error)

func (*DefaultMiddlewareHandle) EndMvcHandle

func (mh *DefaultMiddlewareHandle) EndMvcHandle(ctx *HttpContext) (ar ActionResulter, err error)

func (*DefaultMiddlewareHandle) EndRequest

func (mh *DefaultMiddlewareHandle) EndRequest(ctx *HttpContext) (ar ActionResulter, err error)

type DefaultTemplateEngine

type DefaultTemplateEngine struct {
    ExtName       string
    UseCache      bool
    TemplateCache map[string]*template.Template
}

DefaultTemplateEngine

func CreateDefaultTemplateEngine

func CreateDefaultTemplateEngine(useCache bool) *DefaultTemplateEngine

create a default TemplateEnginer.

func (*DefaultTemplateEngine) Ext

func (te *DefaultTemplateEngine) Ext() string

template file ext name, default is ".html"

func (*DefaultTemplateEngine) Render

func (te *DefaultTemplateEngine) Render(filepath string, layoutPath string, viewData *ViewData, wr io.Writer)

func (*DefaultTemplateEngine) SupportLayout

func (te *DefaultTemplateEngine) SupportLayout() bool

return whether the tempalte support layout

type DefaultViewEngine

type DefaultViewEngine struct {
    ExtName               string // template file ext name, default is ".html"
    RootDir               string // view's root dir, must set
    Layout                string // template layout name, default is "layout"
    ViewLocationFormats   []string
    LayoutLocationFormats []string
    UseCache              bool              // whether cache the viewfile
    Caches                map[string]string // controller & action & view to the real-file-path cache
}

DefaultViewEngine

func CreateDefaultViewEngine

func CreateDefaultViewEngine(viewDir, layout, extName string, useCache bool) *DefaultViewEngine

create a default ViewEnginer. some default value:

		+ Layout: "layout"
     + ExtName: ".html"
		+ ViewLocationFormats:   []string{"{1}/{0}", "shared/{0}"} , {1} is controller, {0} is action or a viewName
		+ LayoutLocationFormats: []string{"{1}/{0}", "shared/{0}"}

func (*DefaultViewEngine) FindView

func (ve *DefaultViewEngine) FindView(vi *ViewInfo) (viewPath string, layoutPath string)

type Filter

type Filter interface {
    OnActionExecuting(ctx *HttpContext) (ActionResulter, error)
    OnActionExecuted(ctx *HttpContext) (ActionResulter, error)
    OnResultExecuting(ctx *HttpContext) (ActionResulter, error)
    OnResultExecuted(ctx *HttpContext) (ActionResulter, error)
}

Order of the filters execution is:

1. OnActionExecuting
2. -> Execute Action -> return ActionResulter
3. OnActionExecuted
4. OnResultExecuting
5. -> ActionResulter.ExecuteResult
6. OnResultExecuted

type HttpContext

type HttpContext struct {
    Request *http.Request // http request

    Method string // http method

    //self fields
    RouteData *RouteData             // route data
    ViewData  map[string]interface{} // view data for template
    Data      map[string]interface{} // data for httpcontex
    Result    ActionResulter         // action result
    Err       error                  // process error
    User      string                 // user name
    Canceled  bool                   // cancel continue process the request and return
    // contains filtered or unexported fields
}

http context

func (*HttpContext) AddHeader

func (ctx *HttpContext) AddHeader(key string, value string)

add response header

func (*HttpContext) ContentType

func (ctx *HttpContext) ContentType(ctype string)

func (*HttpContext) Error

func (ctx *HttpContext) Error(err interface{}) ActionResulter

func (*HttpContext) Get

func (ctx *HttpContext) Get(name string) string

get the requert param, get from RouteData first, if no, get from Requet.FormValue

func (*HttpContext) GetHeader

func (ctx *HttpContext) GetHeader(key string) string

func (*HttpContext) Header

func (ctx *HttpContext) Header() http.Header

get the response header

func (*HttpContext) Html

func (ctx *HttpContext) Html(data string) ActionResulter

func (*HttpContext) IsAjax

func (ctx *HttpContext) IsAjax() bool

get whether the request is by ajax

func (*HttpContext) Json

func (ctx *HttpContext) Json(data interface{}, contentType ...string) ActionResulter

return json string result ctx.Json(obj) or ctx.Json(obj, "text/html")

func (*HttpContext) NotFound

func (ctx *HttpContext) NotFound(message string) ActionResulter

page not found

func (*HttpContext) NotModified

func (ctx *HttpContext) NotModified() ActionResulter

content not modified

func (*HttpContext) Raw

func (ctx *HttpContext) Raw(data string) ActionResulter

func (*HttpContext) Redirect

func (ctx *HttpContext) Redirect(url_ string) ActionResulter

func (*HttpContext) RedirectPermanent

func (ctx *HttpContext) RedirectPermanent(url_ string) ActionResulter

func (*HttpContext) Render

func (ctx *HttpContext) Render(viewName string, viewModel interface{}) *ViewResult

render the view and return a *ViewResult. it will find the view in these rules:

1. /{ViewPath}/{Controller}/{viewName}
2. /{ViewPath}/shared/{viewName}

if viewName start with '/', it will find the view direct by viewpath:

1. /{ViewPath}/{viewName}

func (*HttpContext) RenderPartial

func (ctx *HttpContext) RenderPartial(viewName string, viewModel interface{}) *ViewResult

render a Partial view and return a *ViewResult. this is not use layout. it will find the view in these rules:

1. /{ViewPath}/{Controller}/{viewName}
2. /{ViewPath}/shared/{viewName}

func (*HttpContext) RenderWithLayout

func (ctx *HttpContext) RenderWithLayout(viewName, layout string, viewModel interface{}) *ViewResult

render the view and return a *ViewResult it will find the view in these rules:

1. /{ViewPath}/{Controller}/{viewName}
2. /{ViewPath}/shared/{viewName}

func (*HttpContext) ResponseWriter

func (ctx *HttpContext) ResponseWriter() http.ResponseWriter

Try not to use this unless you know exactly what you are doing

func (*HttpContext) RootDir

func (ctx *HttpContext) RootDir() string

func (*HttpContext) SetCookie

func (ctx *HttpContext) SetCookie(cookie *http.Cookie)

set response cookie header

func (*HttpContext) SetHeader

func (ctx *HttpContext) SetHeader(key string, value string)

set the response header

func (*HttpContext) StaticPath

func (ctx *HttpContext) StaticPath() string

func (*HttpContext) Status

func (ctx *HttpContext) Status(code int)

func (*HttpContext) View

func (ctx *HttpContext) View(viewData interface{}) *ViewResult

render the view and return a *ViewResult it will find the view in these rules:

1. /{ViewPath}/{Controller}/{action}
2. /{ViewPath}/shared/{action}

func (*HttpContext) ViewPath

func (ctx *HttpContext) ViewPath() string

func (*HttpContext) Write

func (ctx *HttpContext) Write(b []byte) (int, error)

func (*HttpContext) WriteBuffer

func (ctx *HttpContext) WriteBuffer(bf *bytes.Buffer)

func (*HttpContext) WriteHeader

func (ctx *HttpContext) WriteHeader(code int)

func (*HttpContext) WriteString

func (ctx *HttpContext) WriteString(content string)

type MiddlewareHandler

type MiddlewareHandler interface {
    BeginRequest(ctx *HttpContext) (ar ActionResulter, err error)
    BeginMvcHandle(ctx *HttpContext) (ar ActionResulter, err error)
    EndMvcHandle(ctx *HttpContext) (ar ActionResulter, err error)
    EndRequest(ctx *HttpContext) (ar ActionResulter, err error)
}

middleware handler, handle the middleware how tu execute

type Middlewarer

type Middlewarer interface {
    OnBeginRequest(ctx *HttpContext) (ActionResulter, error)
    OnBeginMvcHandle(ctx *HttpContext) (ActionResulter, error)
    OnEndMvcHandle(ctx *HttpContext) (ActionResulter, error)
    OnEndRequest(ctx *HttpContext) (ActionResulter, error)
}

middlewarer interface execute order: OnBeginRequest -> OnBeginMvcHandle -> {controller} -> OnEndMvcHandle -> OnEndRequest notice:

OnBeginRequest & OnEndRequest: All requests will be through these
OnBeginMvcHandle & OnEndMvcHandle: not matched route & static file are not through these

type MysqlDB

type MysqlDB struct {
    DB
}

mysql db

func OpenMysql

func OpenMysql(driverName, dataSourceName string) (db *MysqlDB, err error)

open mysql db, and return MysqlDB struct

type RequestHandler

type RequestHandler struct {
    RouteTable        *RouteTable
    MiddlewareHandler MiddlewareHandler
    ServerConfig      *ServerConfig
    ViewEnginer       ViewEnginer
    TemplateEnginer   TemplateEnginer
}

request handler, the main handler for all the requests

func (*RequestHandler) ServeHTTP

func (rh *RequestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

implement the http.Handler interface the main entrance of the request handler

type Route

type Route struct {
    Name       string            // the router name
    Pattern    string            // url pattern config, eg. /{controller}/{action}/{id}
    Default    map[string]string // default value for Pattern
    Constraint map[string]string // constraint for Pattern, value is regexp str
    IsStatic   bool              // whether the route is for static file
    // contains filtered or unexported fields
}

Route config

var rt = &Route {
    Name: "default",
    Pattern: "/{controller}/{action}/{id}",
    Default: map[string]string { "controller": "home", "action": "index", "id": "0", },
    Constraint: map[string]string { "id": "\\d+" }
}

and then, must init the router

rt.Init()

and then, you can use it

rt.Match("/home/index")

func (*Route) Init

func (router *Route) Init()

func (*Route) Match

func (router *Route) Match(url string) (rd *RouteData, matched bool)

type RouteData

type RouteData struct {
    Url        string
    Route      *Route // is this field need ?
    Controller string
    Action     string
    Params     map[string]string
    FilePath   string // if is a static file route, this will be set
}

func (*RouteData) Get

func (rd *RouteData) Get(name string) (val string, ok bool)

type RouteTable

type RouteTable struct {
    Routes []*Route
}

func (*RouteTable) AddRoute

func (rt *RouteTable) AddRoute(route *Route)

func (*RouteTable) Map

func (rt *RouteTable) Map(name string, url string, args ...interface{})

add a new route params:

	+ name: route name
 + url:  url pattern
 + default: map[string]string, default value for url pattern
 + constraint: map[string]string, constraint for url pattern

func (*RouteTable) Match

func (rt *RouteTable) Match(url string) (rd *RouteData, matched bool)

func (*RouteTable) Static

func (rt *RouteTable) Static(name string, pattern string)

static file route match if has group ,return group 1, else return the url e.g.

pattern: /static/.*  , url: /static/logo.gif , static path: /static/logo.gif
pattern: /static/(.*)  , url: /static/logo.gif , static path: logo.gif

type SQLLiteral

type SQLLiteral string

type Server

type Server struct {
    http.Server
}

server inherit from http.Server

func CreateServer

func CreateServer(routeTable *RouteTable, middlewares []Middlewarer, sc *ServerConfig) *Server

create a server to handle the request routeTable is about the rule map a url to a controller action middlewares are the way you can process request during handle request sc is the config how the server work

type ServerConfig

type ServerConfig struct {
    Addr           string        // TCP address to listen on, ":http" if empty
    ReadTimeout    time.Duration // maximum duration before timing out read of the request
    WriteTimeout   time.Duration // maximum duration before timing out write of the response
    MaxHeaderBytes int           // maximum size of request headers, DefaultMaxHeaderBytes if 0

    RootDir    string // project root dir
    StaticPath string // static file dir, "static" if empty
    ViewPath   string // view file dir, "views" if empty
    Layout     string // template layout, "layout" if empty

    ViewEnginer     ViewEnginer
    TemplateEnginer TemplateEnginer

    Logger   *log.Logger
    LogLevel int

    Debug bool
}

all the config to the web server

type SqlQueryInfo

type SqlQueryInfo struct {
    Fields string
    Join   string
    Where  string
    Params []interface{}
    Limit  int
    Offset int
    Group  string
    Order  string
}

type TemplateEnginer

type TemplateEnginer interface {
    // render the view with viewData and write to w
    Render(viewpath string, layoutPath string, viewData *ViewData, w io.Writer)
    // return whether the tempalte support layout
    SupportLayout() bool
    // template file ext name, default is ".html"
    Ext() string
}

TemplateEnginer interface

type ViewData

type ViewData struct {
    Data    map[string]interface{}
    Model   interface{}
    Globals map[string]interface{}
    Body    interface{} // if in layout template, this will set
}

type ViewEnginer

type ViewEnginer interface {
    // find the view and layout
    // if template engine not suppot layout, just return empty string
    FindView(vi *ViewInfo) (viewPath string, layoutPath string)
}

ViewEnginer interface. For how to find the view file.

type ViewInfo

type ViewInfo struct {
    Controller, Action, View, Layout string
    IsPartial                        bool
}

type ViewResult

type ViewResult struct {
    ActionResult

    ViewEngine     ViewEnginer
    TemplateEngine TemplateEnginer
    ViewData       map[string]interface{}
    ViewModel      interface{}
    ViewName       string
    Layout         string
    IsPartial      bool // if is Partial, not use layout
}

func (*ViewResult) ExecuteResult

func (vr *ViewResult) ExecuteResult(ctx *HttpContext)

func (*ViewResult) Render

func (vr *ViewResult) Render(ctx *HttpContext, wr io.Writer)

Directories

PathSynopsis
examples
examples/todo
examples/todo/todo
examples/todo/todo/models
form
utils

Package goku imports 20 packages (graph) and is imported by 13 packages. Updated 2013-03-23. Refresh now. Tools for package owners.