1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-25 18:00:54 +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:
astaxie 2013-12-21 03:55:10 -08:00
commit 8ba6dbb9a0
6 changed files with 105 additions and 52 deletions

22
app.go
View File

@ -61,7 +61,7 @@ func (app *App) Run() {
if nil != err {
BeeLogger.Critical("ResolveTCPAddr:", err)
}
l, err = GetInitListner(laddr)
l, err = GetInitListener(laddr)
theStoppable = newStoppable(l)
err = server.Serve(theStoppable)
theStoppable.wg.Wait()
@ -92,19 +92,19 @@ func (app *App) Run() {
// The c argument needs a controller handler implemented beego.ControllerInterface.
// The mapping methods argument only need one string to define custom router rules.
// usage:
// simple router
// beego.Router("/admin", &admin.UserController{})
// beego.Router("/admin/index", &admin.ArticleController{})
// simple router
// beego.Router("/admin", &admin.UserController{})
// 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
// beego.Router("/api/list",&RestController{},"*:ListFood")
// beego.Router("/api/create",&RestController{},"post:CreateFood")
// beego.Router("/api/update",&RestController{},"put:UpdateFood")
// beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
// beego.Router("/api/list",&RestController{},"*:ListFood")
// beego.Router("/api/create",&RestController{},"post:CreateFood")
// beego.Router("/api/update",&RestController{},"put:UpdateFood")
// beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
func (app *App) Router(path string, c ControllerInterface, mappingMethods ...string) *App {
app.Handlers.Add(path, c, mappingMethods...)
return app
@ -118,7 +118,7 @@ func (app *App) AutoRouter(c ControllerInterface) *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 values need key-pair data to assign into controller method.
func (app *App) UrlFor(endpoint string, values ...string) string {

View File

@ -16,7 +16,8 @@ import (
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) {
osfile, e := os.Open(path)
if e != nil {
@ -86,6 +87,8 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
return &MemFile{fi: cfi, offset: 0}, nil
}
// MemFileInfo contains a compressed file bytes and file information.
// it implements os.FileInfo interface.
type MemFileInfo struct {
os.FileInfo
modTime time.Time
@ -94,49 +97,62 @@ type MemFileInfo struct {
fileSize int64
}
// Name returns the compressed filename.
func (fi *MemFileInfo) Name() string {
return fi.Name()
}
// Size returns the raw file content size, not compressed size.
func (fi *MemFileInfo) Size() int64 {
return fi.contentSize
}
// Mode returns file mode.
func (fi *MemFileInfo) Mode() os.FileMode {
return fi.Mode()
}
// ModTime returns the last modified time of raw file.
func (fi *MemFileInfo) ModTime() time.Time {
return fi.modTime
}
// IsDir returns the compressing file is a directory or not.
func (fi *MemFileInfo) IsDir() bool {
return fi.IsDir()
}
// return nil. implement the os.FileInfo interface method.
func (fi *MemFileInfo) Sys() interface{} {
return nil
}
// MemFile contains MemFileInfo and bytes offset when reading.
// it implements io.Reader,io.ReadCloser and io.Seeker.
type MemFile struct {
fi *MemFileInfo
offset int64
}
// Close memfile.
func (f *MemFile) Close() error {
return nil
}
// Get os.FileInfo of memfile.
func (f *MemFile) Stat() (os.FileInfo, error) {
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) {
infos := []os.FileInfo{}
return infos, nil
}
// Read bytes from the compressed file bytes.
func (f *MemFile) Read(p []byte) (n int, err error) {
if len(f.fi.content)-int(f.offset) >= 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 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) {
switch whence {
default:
@ -169,8 +186,9 @@ func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) {
return f.offset, nil
}
//返回: gzip, deflate, 优先gzip
//返回空, 表示不zip
// GetAcceptEncodingZip returns accept encoding format in http header.
// zip is first, then deflate if both accepted.
// If no accepted, return empty string.
func GetAcceptEncodingZip(r *http.Request) string {
ss := r.Header.Get("Accept-Encoding")
ss = strings.ToLower(ss)
@ -181,8 +199,10 @@ func GetAcceptEncodingZip(r *http.Request) string {
} else {
return ""
}
return ""
}
// CloseZWriter closes the io.Writer after compressing static file.
func CloseZWriter(zwriter io.Writer) {
if zwriter == nil {
return

View File

@ -16,6 +16,7 @@ import (
)
const (
// An environment variable when restarting application http listener.
FDKey = "BEEGO_HOT_FD"
)
@ -32,6 +33,7 @@ type conn struct {
lock sync.Mutex
}
// Close current processing connection.
func (c conn) Close() error {
c.lock.Lock()
defer c.lock.Unlock()
@ -67,6 +69,8 @@ func newStoppable(l net.Listener) (sl *stoppableListener) {
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) {
c, err = sl.Listener.Accept()
if err != nil {
@ -80,6 +84,7 @@ func (sl *stoppableListener) Accept() (c net.Conn, err error) {
return
}
// Listener waits signal to kill or interrupt then restart.
func WaitSignal(l net.Listener) error {
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, os.Kill)
@ -101,6 +106,7 @@ func WaitSignal(l net.Listener) error {
return nil // It'll never get here.
}
// Kill current running os process.
func CloseSelf() error {
ppid := os.Getpid()
if ppid == 1 { // init provided sockets, for example systemd
@ -140,7 +146,8 @@ func Restart(l net.Listener) error {
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)
if countStr == "" {
return net.ListenTCP("tcp", tcpaddr)

View File

@ -19,6 +19,7 @@ import (
)
const (
// default filter execution points
BeforeRouter = iota
AfterStatic
BeforeExec
@ -27,6 +28,7 @@ const (
)
var (
// supported http methods.
HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head"}
)
@ -39,6 +41,7 @@ type controllerInfo struct {
hasMethod bool
}
// ControllerRegistor containers registered router rules, controller handlers and filters.
type ControllerRegistor struct {
routers []*controllerInfo // regexp 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
}
// NewControllerRegistor returns a new ControllerRegistor.
func NewControllerRegistor() *ControllerRegistor {
return &ControllerRegistor{
routers: make([]*controllerInfo, 0),
@ -56,15 +60,16 @@ func NewControllerRegistor() *ControllerRegistor {
}
}
//methods support like this:
//default methods is the same name as method
//Add("/user",&UserController{})
//Add("/api/list",&RestController{},"*:ListFood")
//Add("/api/create",&RestController{},"post:CreateFood")
//Add("/api/update",&RestController{},"put:UpdateFood")
//Add("/api/delete",&RestController{},"delete:DeleteFood")
//Add("/api",&RestController{},"get,post:ApiFunc")
//Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
// Add controller handler and pattern rules to ControllerRegistor.
// usage:
// default methods is the same name as method
// Add("/user",&UserController{})
// Add("/api/list",&RestController{},"*:ListFood")
// Add("/api/create",&RestController{},"post:CreateFood")
// Add("/api/update",&RestController{},"put:UpdateFood")
// Add("/api/delete",&RestController{},"delete:DeleteFood")
// Add("/api",&RestController{},"get,post:ApiFunc")
// Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingMethods ...string) {
parts := strings.Split(pattern, "/")
@ -210,11 +215,11 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM
}
}
// add auto router to controller
// example beego.AddAuto(&MainContorlller{})
// MainController has method List and Page
// you can visit the url /main/list to exec List function
// /main/page to exec Page function
// Add auto router to ControllerRegistor.
// example beego.AddAuto(&MainContorlller{}),
// MainController has method List and Page.
// visit the url /main/list to exec List function
// /main/page to exec Page function.
func (p *ControllerRegistor) AddAuto(c ControllerInterface) {
p.enableAuto = true
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) {
mr := buildFilter(pattern, filter)
switch action {
@ -248,12 +255,15 @@ func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc
p.enableFilter = true
}
// Add a FilterFunc with pattern rule and action constant.
func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc) {
mr := buildFilter(pattern, filter)
p.filters[pos] = append(p.filters[pos], mr)
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 {
paths := strings.Split(endpoint, ".")
if len(paths) <= 1 {
@ -369,7 +379,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
return ""
}
// main function to serveHTTP
// Implement http.Handler interface.
func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
defer func() {
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
// in order to have custom UI for error page it's necessary to override "500" error
// 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.
func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.ResponseWriter, r *http.Request) {
handler := middleware.SimpleServerError
ok := true
@ -771,6 +781,9 @@ func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.Resp
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 {
method = strings.ToLower(method)
if method == "post" && strings.ToLower(context.Input.Query("_method")) == "put" {
@ -806,6 +819,7 @@ func (w *responseWriter) Header() http.Header {
return w.writer.Header()
}
// Init content-length header.
func (w *responseWriter) InitHeadContent(contentlength int64) {
if w.contentEncoding == "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,
// 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) {
w.started = true
return w.writer.Write(p)
}
// 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) {
w.status = code
w.started = true

View File

@ -17,8 +17,9 @@ import (
var (
beegoTplFuncMap template.FuncMap
BeeTemplates map[string]*template.Template
BeeTemplateExt []string
// beego template caching map ans supported template file extensions.
BeeTemplates map[string]*template.Template
BeeTemplateExt []string
)
func init() {
@ -50,7 +51,7 @@ func init() {
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 {
beegoTplFuncMap[key] = funname
return nil
@ -88,6 +89,7 @@ func (self *templatefile) visit(paths string, f os.FileInfo, err error) error {
return nil
}
// return this path has supported template extension of beego or not.
func HasTemplateExt(paths string) bool {
for _, v := range BeeTemplateExt {
if strings.HasSuffix(paths, "."+v) {
@ -97,6 +99,7 @@ func HasTemplateExt(paths string) bool {
return false
}
// add new extension for template.
func AddTemplateExt(ext string) {
for _, v := range BeeTemplateExt {
if v == ext {
@ -106,6 +109,8 @@ func AddTemplateExt(ext string) {
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 {
if _, err := os.Stat(dir); err != nil {
if os.IsNotExist(err) {

View File

@ -12,7 +12,7 @@ import (
"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 {
bt := []rune(s)
if start < 0 {
@ -27,7 +27,7 @@ func Substr(s string, start, length int) string {
return string(bt[start:end])
}
// Html2str() returns escaping text convert from html
// Html2str returns escaping text convert from html.
func Html2str(html string) string {
src := string(html)
@ -60,6 +60,7 @@ func DateFormat(t time.Time, layout string) (datestring string) {
return
}
// DateFormat pattern rules.
var DatePatterns = []string{
// year
"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,
}
// Parse Date use PHP time format
// Parse Date use PHP time format.
func DateParse(dateString, format string) (time.Time, error) {
replacer := strings.NewReplacer(DatePatterns...)
format = replacer.Replace(format)
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 {
replacer := strings.NewReplacer(DatePatterns...)
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.
// 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) {
equal = false
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
}
// Convert string to template.HTML type.
func Str2html(raw string) template.HTML {
return template.HTML(raw)
}
// Htmlquote returns quoted html string.
func Htmlquote(src string) string {
//HTML编码为实体符号
/*
@ -150,6 +153,7 @@ func Htmlquote(src string) string {
return strings.TrimSpace(text)
}
// Htmlunquote returns unquoted html string.
func Htmlunquote(src string) string {
//实体符号解释为HTML
/*
@ -174,13 +178,14 @@ func Htmlunquote(src string) string {
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")
// ... print UrlFor("index")
// ... print UrlFor("login")
// ... print UrlFor("login", "next","/"")
// ... print UrlFor("profile", "username","John Doe")
// ...
// print UrlFor("index")
// print UrlFor("login")
// print UrlFor("login", "next","/"")
// print UrlFor("profile", "username","John Doe")
// result:
// /
// /login
// /login?next=/
@ -189,7 +194,7 @@ func UrlFor(endpoint string, values ...string) string {
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 {
text := string(src)
@ -198,7 +203,7 @@ func AssetsJs(src string) template.HTML {
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 {
text := string(src)
@ -207,7 +212,7 @@ func AssetsCss(src string) template.HTML {
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 {
objT := reflect.TypeOf(obj)
objV := reflect.ValueOf(obj)
@ -295,7 +300,8 @@ var unKind = map[reflect.Kind]bool{
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 {
objT := reflect.TypeOf(obj)
objV := reflect.ValueOf(obj)