mirror of
https://github.com/astaxie/beego.git
synced 2024-11-26 03:11:30 +00:00
Merge pull request #402 from fuxiaohei/master
add api comments in file memzipfile.go,reload.go,router.go,template.go and templatefunc.go
This commit is contained in:
commit
8ba6dbb9a0
22
app.go
22
app.go
@ -61,7 +61,7 @@ func (app *App) Run() {
|
|||||||
if nil != err {
|
if nil != err {
|
||||||
BeeLogger.Critical("ResolveTCPAddr:", err)
|
BeeLogger.Critical("ResolveTCPAddr:", err)
|
||||||
}
|
}
|
||||||
l, err = GetInitListner(laddr)
|
l, err = GetInitListener(laddr)
|
||||||
theStoppable = newStoppable(l)
|
theStoppable = newStoppable(l)
|
||||||
err = server.Serve(theStoppable)
|
err = server.Serve(theStoppable)
|
||||||
theStoppable.wg.Wait()
|
theStoppable.wg.Wait()
|
||||||
@ -92,19 +92,19 @@ func (app *App) Run() {
|
|||||||
// The c argument needs a controller handler implemented beego.ControllerInterface.
|
// The c argument needs a controller handler implemented beego.ControllerInterface.
|
||||||
// The mapping methods argument only need one string to define custom router rules.
|
// The mapping methods argument only need one string to define custom router rules.
|
||||||
// usage:
|
// usage:
|
||||||
// simple router
|
// simple router
|
||||||
// beego.Router("/admin", &admin.UserController{})
|
// beego.Router("/admin", &admin.UserController{})
|
||||||
// beego.Router("/admin/index", &admin.ArticleController{})
|
// beego.Router("/admin/index", &admin.ArticleController{})
|
||||||
//
|
//
|
||||||
// regex router
|
// regex router
|
||||||
//
|
//
|
||||||
// beego.Router(“/api/:id([0-9]+)“, &controllers.RController{})
|
// beego.Router(“/api/:id([0-9]+)“, &controllers.RController{})
|
||||||
//
|
//
|
||||||
// custom rules
|
// custom rules
|
||||||
// beego.Router("/api/list",&RestController{},"*:ListFood")
|
// beego.Router("/api/list",&RestController{},"*:ListFood")
|
||||||
// beego.Router("/api/create",&RestController{},"post:CreateFood")
|
// beego.Router("/api/create",&RestController{},"post:CreateFood")
|
||||||
// beego.Router("/api/update",&RestController{},"put:UpdateFood")
|
// beego.Router("/api/update",&RestController{},"put:UpdateFood")
|
||||||
// beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
|
// beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
|
||||||
func (app *App) Router(path string, c ControllerInterface, mappingMethods ...string) *App {
|
func (app *App) Router(path string, c ControllerInterface, mappingMethods ...string) *App {
|
||||||
app.Handlers.Add(path, c, mappingMethods...)
|
app.Handlers.Add(path, c, mappingMethods...)
|
||||||
return app
|
return app
|
||||||
@ -118,7 +118,7 @@ func (app *App) AutoRouter(c ControllerInterface) *App {
|
|||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
// UrlFor does another controller handler with params in current context.
|
// UrlFor creates a url with another registered controller handler with params.
|
||||||
// The endpoint is formed as path.controller.name to defined the controller method which will run.
|
// The endpoint is formed as path.controller.name to defined the controller method which will run.
|
||||||
// The values need key-pair data to assign into controller method.
|
// The values need key-pair data to assign into controller method.
|
||||||
func (app *App) UrlFor(endpoint string, values ...string) string {
|
func (app *App) UrlFor(endpoint string, values ...string) string {
|
||||||
|
@ -16,7 +16,8 @@ import (
|
|||||||
|
|
||||||
var gmfim map[string]*MemFileInfo = make(map[string]*MemFileInfo)
|
var gmfim map[string]*MemFileInfo = make(map[string]*MemFileInfo)
|
||||||
|
|
||||||
//TODO: 加锁保证数据完整性
|
// OpenMemZipFile returns MemFile object with a compressed static file.
|
||||||
|
// it's used for serve static file if gzip enable.
|
||||||
func OpenMemZipFile(path string, zip string) (*MemFile, error) {
|
func OpenMemZipFile(path string, zip string) (*MemFile, error) {
|
||||||
osfile, e := os.Open(path)
|
osfile, e := os.Open(path)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
@ -86,6 +87,8 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
|
|||||||
return &MemFile{fi: cfi, offset: 0}, nil
|
return &MemFile{fi: cfi, offset: 0}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MemFileInfo contains a compressed file bytes and file information.
|
||||||
|
// it implements os.FileInfo interface.
|
||||||
type MemFileInfo struct {
|
type MemFileInfo struct {
|
||||||
os.FileInfo
|
os.FileInfo
|
||||||
modTime time.Time
|
modTime time.Time
|
||||||
@ -94,49 +97,62 @@ type MemFileInfo struct {
|
|||||||
fileSize int64
|
fileSize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the compressed filename.
|
||||||
func (fi *MemFileInfo) Name() string {
|
func (fi *MemFileInfo) Name() string {
|
||||||
return fi.Name()
|
return fi.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Size returns the raw file content size, not compressed size.
|
||||||
func (fi *MemFileInfo) Size() int64 {
|
func (fi *MemFileInfo) Size() int64 {
|
||||||
return fi.contentSize
|
return fi.contentSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mode returns file mode.
|
||||||
func (fi *MemFileInfo) Mode() os.FileMode {
|
func (fi *MemFileInfo) Mode() os.FileMode {
|
||||||
return fi.Mode()
|
return fi.Mode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ModTime returns the last modified time of raw file.
|
||||||
func (fi *MemFileInfo) ModTime() time.Time {
|
func (fi *MemFileInfo) ModTime() time.Time {
|
||||||
return fi.modTime
|
return fi.modTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDir returns the compressing file is a directory or not.
|
||||||
func (fi *MemFileInfo) IsDir() bool {
|
func (fi *MemFileInfo) IsDir() bool {
|
||||||
return fi.IsDir()
|
return fi.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return nil. implement the os.FileInfo interface method.
|
||||||
func (fi *MemFileInfo) Sys() interface{} {
|
func (fi *MemFileInfo) Sys() interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MemFile contains MemFileInfo and bytes offset when reading.
|
||||||
|
// it implements io.Reader,io.ReadCloser and io.Seeker.
|
||||||
type MemFile struct {
|
type MemFile struct {
|
||||||
fi *MemFileInfo
|
fi *MemFileInfo
|
||||||
offset int64
|
offset int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close memfile.
|
||||||
func (f *MemFile) Close() error {
|
func (f *MemFile) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get os.FileInfo of memfile.
|
||||||
func (f *MemFile) Stat() (os.FileInfo, error) {
|
func (f *MemFile) Stat() (os.FileInfo, error) {
|
||||||
return f.fi, nil
|
return f.fi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read os.FileInfo of files in directory of memfile.
|
||||||
|
// it returns empty slice.
|
||||||
func (f *MemFile) Readdir(count int) ([]os.FileInfo, error) {
|
func (f *MemFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||||
infos := []os.FileInfo{}
|
infos := []os.FileInfo{}
|
||||||
|
|
||||||
return infos, nil
|
return infos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read bytes from the compressed file bytes.
|
||||||
func (f *MemFile) Read(p []byte) (n int, err error) {
|
func (f *MemFile) Read(p []byte) (n int, err error) {
|
||||||
if len(f.fi.content)-int(f.offset) >= len(p) {
|
if len(f.fi.content)-int(f.offset) >= len(p) {
|
||||||
n = len(p)
|
n = len(p)
|
||||||
@ -152,6 +168,7 @@ func (f *MemFile) Read(p []byte) (n int, err error) {
|
|||||||
var errWhence = errors.New("Seek: invalid whence")
|
var errWhence = errors.New("Seek: invalid whence")
|
||||||
var errOffset = errors.New("Seek: invalid offset")
|
var errOffset = errors.New("Seek: invalid offset")
|
||||||
|
|
||||||
|
// Read bytes from the compressed file bytes by seeker.
|
||||||
func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) {
|
func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) {
|
||||||
switch whence {
|
switch whence {
|
||||||
default:
|
default:
|
||||||
@ -169,8 +186,9 @@ func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) {
|
|||||||
return f.offset, nil
|
return f.offset, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//返回: gzip, deflate, 优先gzip
|
// GetAcceptEncodingZip returns accept encoding format in http header.
|
||||||
//返回空, 表示不zip
|
// zip is first, then deflate if both accepted.
|
||||||
|
// If no accepted, return empty string.
|
||||||
func GetAcceptEncodingZip(r *http.Request) string {
|
func GetAcceptEncodingZip(r *http.Request) string {
|
||||||
ss := r.Header.Get("Accept-Encoding")
|
ss := r.Header.Get("Accept-Encoding")
|
||||||
ss = strings.ToLower(ss)
|
ss = strings.ToLower(ss)
|
||||||
@ -181,8 +199,10 @@ func GetAcceptEncodingZip(r *http.Request) string {
|
|||||||
} else {
|
} else {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloseZWriter closes the io.Writer after compressing static file.
|
||||||
func CloseZWriter(zwriter io.Writer) {
|
func CloseZWriter(zwriter io.Writer) {
|
||||||
if zwriter == nil {
|
if zwriter == nil {
|
||||||
return
|
return
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// An environment variable when restarting application http listener.
|
||||||
FDKey = "BEEGO_HOT_FD"
|
FDKey = "BEEGO_HOT_FD"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ type conn struct {
|
|||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close current processing connection.
|
||||||
func (c conn) Close() error {
|
func (c conn) Close() error {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
@ -67,6 +69,8 @@ func newStoppable(l net.Listener) (sl *stoppableListener) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set stopped Listener to accept requests again.
|
||||||
|
// it returns the accepted and closable connection or error.
|
||||||
func (sl *stoppableListener) Accept() (c net.Conn, err error) {
|
func (sl *stoppableListener) Accept() (c net.Conn, err error) {
|
||||||
c, err = sl.Listener.Accept()
|
c, err = sl.Listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -80,6 +84,7 @@ func (sl *stoppableListener) Accept() (c net.Conn, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Listener waits signal to kill or interrupt then restart.
|
||||||
func WaitSignal(l net.Listener) error {
|
func WaitSignal(l net.Listener) error {
|
||||||
ch := make(chan os.Signal, 1)
|
ch := make(chan os.Signal, 1)
|
||||||
signal.Notify(ch, os.Interrupt, os.Kill)
|
signal.Notify(ch, os.Interrupt, os.Kill)
|
||||||
@ -101,6 +106,7 @@ func WaitSignal(l net.Listener) error {
|
|||||||
return nil // It'll never get here.
|
return nil // It'll never get here.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kill current running os process.
|
||||||
func CloseSelf() error {
|
func CloseSelf() error {
|
||||||
ppid := os.Getpid()
|
ppid := os.Getpid()
|
||||||
if ppid == 1 { // init provided sockets, for example systemd
|
if ppid == 1 { // init provided sockets, for example systemd
|
||||||
@ -140,7 +146,8 @@ func Restart(l net.Listener) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetInitListner(tcpaddr *net.TCPAddr) (l net.Listener, err error) {
|
// Get current net.Listen in running process.
|
||||||
|
func GetInitListener(tcpaddr *net.TCPAddr) (l net.Listener, err error) {
|
||||||
countStr := os.Getenv(FDKey)
|
countStr := os.Getenv(FDKey)
|
||||||
if countStr == "" {
|
if countStr == "" {
|
||||||
return net.ListenTCP("tcp", tcpaddr)
|
return net.ListenTCP("tcp", tcpaddr)
|
||||||
|
53
router.go
53
router.go
@ -19,6 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// default filter execution points
|
||||||
BeforeRouter = iota
|
BeforeRouter = iota
|
||||||
AfterStatic
|
AfterStatic
|
||||||
BeforeExec
|
BeforeExec
|
||||||
@ -27,6 +28,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// supported http methods.
|
||||||
HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head"}
|
HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head"}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,6 +41,7 @@ type controllerInfo struct {
|
|||||||
hasMethod bool
|
hasMethod bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ControllerRegistor containers registered router rules, controller handlers and filters.
|
||||||
type ControllerRegistor struct {
|
type ControllerRegistor struct {
|
||||||
routers []*controllerInfo // regexp router storage
|
routers []*controllerInfo // regexp router storage
|
||||||
fixrouters []*controllerInfo // fixed router storage
|
fixrouters []*controllerInfo // fixed router storage
|
||||||
@ -48,6 +51,7 @@ type ControllerRegistor struct {
|
|||||||
autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type
|
autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewControllerRegistor returns a new ControllerRegistor.
|
||||||
func NewControllerRegistor() *ControllerRegistor {
|
func NewControllerRegistor() *ControllerRegistor {
|
||||||
return &ControllerRegistor{
|
return &ControllerRegistor{
|
||||||
routers: make([]*controllerInfo, 0),
|
routers: make([]*controllerInfo, 0),
|
||||||
@ -56,15 +60,16 @@ func NewControllerRegistor() *ControllerRegistor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//methods support like this:
|
// Add controller handler and pattern rules to ControllerRegistor.
|
||||||
//default methods is the same name as method
|
// usage:
|
||||||
//Add("/user",&UserController{})
|
// default methods is the same name as method
|
||||||
//Add("/api/list",&RestController{},"*:ListFood")
|
// Add("/user",&UserController{})
|
||||||
//Add("/api/create",&RestController{},"post:CreateFood")
|
// Add("/api/list",&RestController{},"*:ListFood")
|
||||||
//Add("/api/update",&RestController{},"put:UpdateFood")
|
// Add("/api/create",&RestController{},"post:CreateFood")
|
||||||
//Add("/api/delete",&RestController{},"delete:DeleteFood")
|
// Add("/api/update",&RestController{},"put:UpdateFood")
|
||||||
//Add("/api",&RestController{},"get,post:ApiFunc")
|
// Add("/api/delete",&RestController{},"delete:DeleteFood")
|
||||||
//Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
|
// Add("/api",&RestController{},"get,post:ApiFunc")
|
||||||
|
// Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
|
||||||
func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingMethods ...string) {
|
func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingMethods ...string) {
|
||||||
parts := strings.Split(pattern, "/")
|
parts := strings.Split(pattern, "/")
|
||||||
|
|
||||||
@ -210,11 +215,11 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add auto router to controller
|
// Add auto router to ControllerRegistor.
|
||||||
// example beego.AddAuto(&MainContorlller{})
|
// example beego.AddAuto(&MainContorlller{}),
|
||||||
// MainController has method List and Page
|
// MainController has method List and Page.
|
||||||
// you can visit the url /main/list to exec List function
|
// visit the url /main/list to exec List function
|
||||||
// /main/page to exec Page function
|
// /main/page to exec Page function.
|
||||||
func (p *ControllerRegistor) AddAuto(c ControllerInterface) {
|
func (p *ControllerRegistor) AddAuto(c ControllerInterface) {
|
||||||
p.enableAuto = true
|
p.enableAuto = true
|
||||||
reflectVal := reflect.ValueOf(c)
|
reflectVal := reflect.ValueOf(c)
|
||||||
@ -231,6 +236,8 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [Deprecated] use InsertFilter.
|
||||||
|
// Add FilterFunc with pattern for action.
|
||||||
func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) {
|
func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) {
|
||||||
mr := buildFilter(pattern, filter)
|
mr := buildFilter(pattern, filter)
|
||||||
switch action {
|
switch action {
|
||||||
@ -248,12 +255,15 @@ func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc
|
|||||||
p.enableFilter = true
|
p.enableFilter = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a FilterFunc with pattern rule and action constant.
|
||||||
func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc) {
|
func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc) {
|
||||||
mr := buildFilter(pattern, filter)
|
mr := buildFilter(pattern, filter)
|
||||||
p.filters[pos] = append(p.filters[pos], mr)
|
p.filters[pos] = append(p.filters[pos], mr)
|
||||||
p.enableFilter = true
|
p.enableFilter = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UrlFor does another controller handler in this request function.
|
||||||
|
// it can access any controller method.
|
||||||
func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
|
func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
|
||||||
paths := strings.Split(endpoint, ".")
|
paths := strings.Split(endpoint, ".")
|
||||||
if len(paths) <= 1 {
|
if len(paths) <= 1 {
|
||||||
@ -369,7 +379,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// main function to serveHTTP
|
// Implement http.Handler interface.
|
||||||
func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
@ -753,8 +763,8 @@ Admin:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// there always should be error handler that sets error code accordingly for all unhandled errors
|
// there always should be error handler that sets error code accordingly for all unhandled errors.
|
||||||
// in order to have custom UI for error page it's necessary to override "500" error
|
// in order to have custom UI for error page it's necessary to override "500" error.
|
||||||
func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.ResponseWriter, r *http.Request) {
|
func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.ResponseWriter, r *http.Request) {
|
||||||
handler := middleware.SimpleServerError
|
handler := middleware.SimpleServerError
|
||||||
ok := true
|
ok := true
|
||||||
@ -771,6 +781,9 @@ func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.Resp
|
|||||||
return handler
|
return handler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns method name from request header or form field.
|
||||||
|
// sometimes browsers can't create PUT and DELETE request.
|
||||||
|
// set a form field "_method" instead.
|
||||||
func (p *ControllerRegistor) getRunMethod(method string, context *beecontext.Context, router *controllerInfo) string {
|
func (p *ControllerRegistor) getRunMethod(method string, context *beecontext.Context, router *controllerInfo) string {
|
||||||
method = strings.ToLower(method)
|
method = strings.ToLower(method)
|
||||||
if method == "post" && strings.ToLower(context.Input.Query("_method")) == "put" {
|
if method == "post" && strings.ToLower(context.Input.Query("_method")) == "put" {
|
||||||
@ -806,6 +819,7 @@ func (w *responseWriter) Header() http.Header {
|
|||||||
return w.writer.Header()
|
return w.writer.Header()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init content-length header.
|
||||||
func (w *responseWriter) InitHeadContent(contentlength int64) {
|
func (w *responseWriter) InitHeadContent(contentlength int64) {
|
||||||
if w.contentEncoding == "gzip" {
|
if w.contentEncoding == "gzip" {
|
||||||
w.Header().Set("Content-Encoding", "gzip")
|
w.Header().Set("Content-Encoding", "gzip")
|
||||||
@ -817,14 +831,15 @@ func (w *responseWriter) InitHeadContent(contentlength int64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write writes the data to the connection as part of an HTTP reply,
|
// Write writes the data to the connection as part of an HTTP reply,
|
||||||
// and sets `started` to true
|
// and sets `started` to true.
|
||||||
|
// started means the response has sent out.
|
||||||
func (w *responseWriter) Write(p []byte) (int, error) {
|
func (w *responseWriter) Write(p []byte) (int, error) {
|
||||||
w.started = true
|
w.started = true
|
||||||
return w.writer.Write(p)
|
return w.writer.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteHeader sends an HTTP response header with status code,
|
// WriteHeader sends an HTTP response header with status code,
|
||||||
// and sets `started` to true
|
// and sets `started` to true.
|
||||||
func (w *responseWriter) WriteHeader(code int) {
|
func (w *responseWriter) WriteHeader(code int) {
|
||||||
w.status = code
|
w.status = code
|
||||||
w.started = true
|
w.started = true
|
||||||
|
11
template.go
11
template.go
@ -17,8 +17,9 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
beegoTplFuncMap template.FuncMap
|
beegoTplFuncMap template.FuncMap
|
||||||
BeeTemplates map[string]*template.Template
|
// beego template caching map ans supported template file extensions.
|
||||||
BeeTemplateExt []string
|
BeeTemplates map[string]*template.Template
|
||||||
|
BeeTemplateExt []string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -50,7 +51,7 @@ func init() {
|
|||||||
beegoTplFuncMap["urlfor"] = UrlFor // !=
|
beegoTplFuncMap["urlfor"] = UrlFor // !=
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFuncMap let user to register a func in the template
|
// AddFuncMap let user to register a func in the template.
|
||||||
func AddFuncMap(key string, funname interface{}) error {
|
func AddFuncMap(key string, funname interface{}) error {
|
||||||
beegoTplFuncMap[key] = funname
|
beegoTplFuncMap[key] = funname
|
||||||
return nil
|
return nil
|
||||||
@ -88,6 +89,7 @@ func (self *templatefile) visit(paths string, f os.FileInfo, err error) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return this path has supported template extension of beego or not.
|
||||||
func HasTemplateExt(paths string) bool {
|
func HasTemplateExt(paths string) bool {
|
||||||
for _, v := range BeeTemplateExt {
|
for _, v := range BeeTemplateExt {
|
||||||
if strings.HasSuffix(paths, "."+v) {
|
if strings.HasSuffix(paths, "."+v) {
|
||||||
@ -97,6 +99,7 @@ func HasTemplateExt(paths string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add new extension for template.
|
||||||
func AddTemplateExt(ext string) {
|
func AddTemplateExt(ext string) {
|
||||||
for _, v := range BeeTemplateExt {
|
for _, v := range BeeTemplateExt {
|
||||||
if v == ext {
|
if v == ext {
|
||||||
@ -106,6 +109,8 @@ func AddTemplateExt(ext string) {
|
|||||||
BeeTemplateExt = append(BeeTemplateExt, ext)
|
BeeTemplateExt = append(BeeTemplateExt, ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build all template files in a directory.
|
||||||
|
// it makes beego can render any template file in view directory.
|
||||||
func BuildTemplate(dir string) error {
|
func BuildTemplate(dir string) error {
|
||||||
if _, err := os.Stat(dir); err != nil {
|
if _, err := os.Stat(dir); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Substr() return the substr from start to length
|
// Substr returns the substr from start to length.
|
||||||
func Substr(s string, start, length int) string {
|
func Substr(s string, start, length int) string {
|
||||||
bt := []rune(s)
|
bt := []rune(s)
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
@ -27,7 +27,7 @@ func Substr(s string, start, length int) string {
|
|||||||
return string(bt[start:end])
|
return string(bt[start:end])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Html2str() returns escaping text convert from html
|
// Html2str returns escaping text convert from html.
|
||||||
func Html2str(html string) string {
|
func Html2str(html string) string {
|
||||||
src := string(html)
|
src := string(html)
|
||||||
|
|
||||||
@ -60,6 +60,7 @@ func DateFormat(t time.Time, layout string) (datestring string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DateFormat pattern rules.
|
||||||
var DatePatterns = []string{
|
var DatePatterns = []string{
|
||||||
// year
|
// year
|
||||||
"Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
|
"Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
|
||||||
@ -100,14 +101,14 @@ var DatePatterns = []string{
|
|||||||
"r", time.RFC1123Z,
|
"r", time.RFC1123Z,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse Date use PHP time format
|
// Parse Date use PHP time format.
|
||||||
func DateParse(dateString, format string) (time.Time, error) {
|
func DateParse(dateString, format string) (time.Time, error) {
|
||||||
replacer := strings.NewReplacer(DatePatterns...)
|
replacer := strings.NewReplacer(DatePatterns...)
|
||||||
format = replacer.Replace(format)
|
format = replacer.Replace(format)
|
||||||
return time.ParseInLocation(format, dateString, time.Local)
|
return time.ParseInLocation(format, dateString, time.Local)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Date takes a PHP like date func to Go's time format
|
// Date takes a PHP like date func to Go's time format.
|
||||||
func Date(t time.Time, format string) string {
|
func Date(t time.Time, format string) string {
|
||||||
replacer := strings.NewReplacer(DatePatterns...)
|
replacer := strings.NewReplacer(DatePatterns...)
|
||||||
format = replacer.Replace(format)
|
format = replacer.Replace(format)
|
||||||
@ -115,7 +116,7 @@ func Date(t time.Time, format string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compare is a quick and dirty comparison function. It will convert whatever you give it to strings and see if the two values are equal.
|
// Compare is a quick and dirty comparison function. It will convert whatever you give it to strings and see if the two values are equal.
|
||||||
// Whitespace is trimmed. Used by the template parser as "eq"
|
// Whitespace is trimmed. Used by the template parser as "eq".
|
||||||
func Compare(a, b interface{}) (equal bool) {
|
func Compare(a, b interface{}) (equal bool) {
|
||||||
equal = false
|
equal = false
|
||||||
if strings.TrimSpace(fmt.Sprintf("%v", a)) == strings.TrimSpace(fmt.Sprintf("%v", b)) {
|
if strings.TrimSpace(fmt.Sprintf("%v", a)) == strings.TrimSpace(fmt.Sprintf("%v", b)) {
|
||||||
@ -124,10 +125,12 @@ func Compare(a, b interface{}) (equal bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert string to template.HTML type.
|
||||||
func Str2html(raw string) template.HTML {
|
func Str2html(raw string) template.HTML {
|
||||||
return template.HTML(raw)
|
return template.HTML(raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Htmlquote returns quoted html string.
|
||||||
func Htmlquote(src string) string {
|
func Htmlquote(src string) string {
|
||||||
//HTML编码为实体符号
|
//HTML编码为实体符号
|
||||||
/*
|
/*
|
||||||
@ -150,6 +153,7 @@ func Htmlquote(src string) string {
|
|||||||
return strings.TrimSpace(text)
|
return strings.TrimSpace(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Htmlunquote returns unquoted html string.
|
||||||
func Htmlunquote(src string) string {
|
func Htmlunquote(src string) string {
|
||||||
//实体符号解释为HTML
|
//实体符号解释为HTML
|
||||||
/*
|
/*
|
||||||
@ -174,13 +178,14 @@ func Htmlunquote(src string) string {
|
|||||||
return strings.TrimSpace(text)
|
return strings.TrimSpace(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will reference the index function local to the current blueprint:
|
// UrlFor returns url string with another registered controller handler with params.
|
||||||
|
// usage:
|
||||||
// UrlFor(".index")
|
// UrlFor(".index")
|
||||||
// ... print UrlFor("index")
|
// print UrlFor("index")
|
||||||
// ... print UrlFor("login")
|
// print UrlFor("login")
|
||||||
// ... print UrlFor("login", "next","/"")
|
// print UrlFor("login", "next","/"")
|
||||||
// ... print UrlFor("profile", "username","John Doe")
|
// print UrlFor("profile", "username","John Doe")
|
||||||
// ...
|
// result:
|
||||||
// /
|
// /
|
||||||
// /login
|
// /login
|
||||||
// /login?next=/
|
// /login?next=/
|
||||||
@ -189,7 +194,7 @@ func UrlFor(endpoint string, values ...string) string {
|
|||||||
return BeeApp.UrlFor(endpoint, values...)
|
return BeeApp.UrlFor(endpoint, values...)
|
||||||
}
|
}
|
||||||
|
|
||||||
//This can be changed to a better name
|
// returns script tag with src string.
|
||||||
func AssetsJs(src string) template.HTML {
|
func AssetsJs(src string) template.HTML {
|
||||||
text := string(src)
|
text := string(src)
|
||||||
|
|
||||||
@ -198,7 +203,7 @@ func AssetsJs(src string) template.HTML {
|
|||||||
return template.HTML(text)
|
return template.HTML(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
//This can be changed to a better name
|
// returns stylesheet link tag with str string.
|
||||||
func AssetsCss(src string) template.HTML {
|
func AssetsCss(src string) template.HTML {
|
||||||
text := string(src)
|
text := string(src)
|
||||||
|
|
||||||
@ -207,7 +212,7 @@ func AssetsCss(src string) template.HTML {
|
|||||||
return template.HTML(text)
|
return template.HTML(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse form values to struct via tag
|
// parse form values to struct via tag.
|
||||||
func ParseForm(form url.Values, obj interface{}) error {
|
func ParseForm(form url.Values, obj interface{}) error {
|
||||||
objT := reflect.TypeOf(obj)
|
objT := reflect.TypeOf(obj)
|
||||||
objV := reflect.ValueOf(obj)
|
objV := reflect.ValueOf(obj)
|
||||||
@ -295,7 +300,8 @@ var unKind = map[reflect.Kind]bool{
|
|||||||
reflect.UnsafePointer: true,
|
reflect.UnsafePointer: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// obj must be a struct pointer
|
// render object to form html.
|
||||||
|
// obj must be a struct pointer.
|
||||||
func RenderForm(obj interface{}) template.HTML {
|
func RenderForm(obj interface{}) template.HTML {
|
||||||
objT := reflect.TypeOf(obj)
|
objT := reflect.TypeOf(obj)
|
||||||
objV := reflect.ValueOf(obj)
|
objV := reflect.ValueOf(obj)
|
||||||
|
Loading…
Reference in New Issue
Block a user