Merge pull request #402 from fuxiaohei/master
add api comments in file memzipfile.go,reload.go,router.go,template.go and templatefunc.go
Showing
6 changed files
with
94 additions
and
41 deletions
| ... | @@ -61,7 +61,7 @@ func (app *App) Run() { | ... | @@ -61,7 +61,7 @@ func (app *App) Run() { |
| 61 | if nil != err { | 61 | if nil != err { |
| 62 | BeeLogger.Critical("ResolveTCPAddr:", err) | 62 | BeeLogger.Critical("ResolveTCPAddr:", err) |
| 63 | } | 63 | } |
| 64 | l, err = GetInitListner(laddr) | 64 | l, err = GetInitListener(laddr) |
| 65 | theStoppable = newStoppable(l) | 65 | theStoppable = newStoppable(l) |
| 66 | err = server.Serve(theStoppable) | 66 | err = server.Serve(theStoppable) |
| 67 | theStoppable.wg.Wait() | 67 | theStoppable.wg.Wait() |
| ... | @@ -118,7 +118,7 @@ func (app *App) AutoRouter(c ControllerInterface) *App { | ... | @@ -118,7 +118,7 @@ func (app *App) AutoRouter(c ControllerInterface) *App { |
| 118 | return app | 118 | return app |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | // UrlFor does another controller handler with params in current context. | 121 | // UrlFor creates a url with another registered controller handler with params. |
| 122 | // The endpoint is formed as path.controller.name to defined the controller method which will run. | 122 | // The endpoint is formed as path.controller.name to defined the controller method which will run. |
| 123 | // The values need key-pair data to assign into controller method. | 123 | // The values need key-pair data to assign into controller method. |
| 124 | func (app *App) UrlFor(endpoint string, values ...string) string { | 124 | func (app *App) UrlFor(endpoint string, values ...string) string { | ... | ... |
| ... | @@ -16,7 +16,8 @@ import ( | ... | @@ -16,7 +16,8 @@ import ( |
| 16 | 16 | ||
| 17 | var gmfim map[string]*MemFileInfo = make(map[string]*MemFileInfo) | 17 | var gmfim map[string]*MemFileInfo = make(map[string]*MemFileInfo) |
| 18 | 18 | ||
| 19 | //TODO: 加锁保证数据完整性 | 19 | // OpenMemZipFile returns MemFile object with a compressed static file. |
| 20 | // it's used for serve static file if gzip enable. | ||
| 20 | func OpenMemZipFile(path string, zip string) (*MemFile, error) { | 21 | func OpenMemZipFile(path string, zip string) (*MemFile, error) { |
| 21 | osfile, e := os.Open(path) | 22 | osfile, e := os.Open(path) |
| 22 | if e != nil { | 23 | if e != nil { |
| ... | @@ -86,6 +87,8 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) { | ... | @@ -86,6 +87,8 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) { |
| 86 | return &MemFile{fi: cfi, offset: 0}, nil | 87 | return &MemFile{fi: cfi, offset: 0}, nil |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 90 | // MemFileInfo contains a compressed file bytes and file information. | ||
| 91 | // it implements os.FileInfo interface. | ||
| 89 | type MemFileInfo struct { | 92 | type MemFileInfo struct { |
| 90 | os.FileInfo | 93 | os.FileInfo |
| 91 | modTime time.Time | 94 | modTime time.Time |
| ... | @@ -94,49 +97,62 @@ type MemFileInfo struct { | ... | @@ -94,49 +97,62 @@ type MemFileInfo struct { |
| 94 | fileSize int64 | 97 | fileSize int64 |
| 95 | } | 98 | } |
| 96 | 99 | ||
| 100 | // Name returns the compressed filename. | ||
| 97 | func (fi *MemFileInfo) Name() string { | 101 | func (fi *MemFileInfo) Name() string { |
| 98 | return fi.Name() | 102 | return fi.Name() |
| 99 | } | 103 | } |
| 100 | 104 | ||
| 105 | // Size returns the raw file content size, not compressed size. | ||
| 101 | func (fi *MemFileInfo) Size() int64 { | 106 | func (fi *MemFileInfo) Size() int64 { |
| 102 | return fi.contentSize | 107 | return fi.contentSize |
| 103 | } | 108 | } |
| 104 | 109 | ||
| 110 | // Mode returns file mode. | ||
| 105 | func (fi *MemFileInfo) Mode() os.FileMode { | 111 | func (fi *MemFileInfo) Mode() os.FileMode { |
| 106 | return fi.Mode() | 112 | return fi.Mode() |
| 107 | } | 113 | } |
| 108 | 114 | ||
| 115 | // ModTime returns the last modified time of raw file. | ||
| 109 | func (fi *MemFileInfo) ModTime() time.Time { | 116 | func (fi *MemFileInfo) ModTime() time.Time { |
| 110 | return fi.modTime | 117 | return fi.modTime |
| 111 | } | 118 | } |
| 112 | 119 | ||
| 120 | // IsDir returns the compressing file is a directory or not. | ||
| 113 | func (fi *MemFileInfo) IsDir() bool { | 121 | func (fi *MemFileInfo) IsDir() bool { |
| 114 | return fi.IsDir() | 122 | return fi.IsDir() |
| 115 | } | 123 | } |
| 116 | 124 | ||
| 125 | // return nil. implement the os.FileInfo interface method. | ||
| 117 | func (fi *MemFileInfo) Sys() interface{} { | 126 | func (fi *MemFileInfo) Sys() interface{} { |
| 118 | return nil | 127 | return nil |
| 119 | } | 128 | } |
| 120 | 129 | ||
| 130 | // MemFile contains MemFileInfo and bytes offset when reading. | ||
| 131 | // it implements io.Reader,io.ReadCloser and io.Seeker. | ||
| 121 | type MemFile struct { | 132 | type MemFile struct { |
| 122 | fi *MemFileInfo | 133 | fi *MemFileInfo |
| 123 | offset int64 | 134 | offset int64 |
| 124 | } | 135 | } |
| 125 | 136 | ||
| 137 | // Close memfile. | ||
| 126 | func (f *MemFile) Close() error { | 138 | func (f *MemFile) Close() error { |
| 127 | return nil | 139 | return nil |
| 128 | } | 140 | } |
| 129 | 141 | ||
| 142 | // Get os.FileInfo of memfile. | ||
| 130 | func (f *MemFile) Stat() (os.FileInfo, error) { | 143 | func (f *MemFile) Stat() (os.FileInfo, error) { |
| 131 | return f.fi, nil | 144 | return f.fi, nil |
| 132 | } | 145 | } |
| 133 | 146 | ||
| 147 | // read os.FileInfo of files in directory of memfile. | ||
| 148 | // it returns empty slice. | ||
| 134 | func (f *MemFile) Readdir(count int) ([]os.FileInfo, error) { | 149 | func (f *MemFile) Readdir(count int) ([]os.FileInfo, error) { |
| 135 | infos := []os.FileInfo{} | 150 | infos := []os.FileInfo{} |
| 136 | 151 | ||
| 137 | return infos, nil | 152 | return infos, nil |
| 138 | } | 153 | } |
| 139 | 154 | ||
| 155 | // Read bytes from the compressed file bytes. | ||
| 140 | func (f *MemFile) Read(p []byte) (n int, err error) { | 156 | func (f *MemFile) Read(p []byte) (n int, err error) { |
| 141 | if len(f.fi.content)-int(f.offset) >= len(p) { | 157 | if len(f.fi.content)-int(f.offset) >= len(p) { |
| 142 | n = len(p) | 158 | n = len(p) |
| ... | @@ -152,6 +168,7 @@ func (f *MemFile) Read(p []byte) (n int, err error) { | ... | @@ -152,6 +168,7 @@ func (f *MemFile) Read(p []byte) (n int, err error) { |
| 152 | var errWhence = errors.New("Seek: invalid whence") | 168 | var errWhence = errors.New("Seek: invalid whence") |
| 153 | var errOffset = errors.New("Seek: invalid offset") | 169 | var errOffset = errors.New("Seek: invalid offset") |
| 154 | 170 | ||
| 171 | // Read bytes from the compressed file bytes by seeker. | ||
| 155 | func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) { | 172 | func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) { |
| 156 | switch whence { | 173 | switch whence { |
| 157 | default: | 174 | default: |
| ... | @@ -169,8 +186,9 @@ func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) { | ... | @@ -169,8 +186,9 @@ func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) { |
| 169 | return f.offset, nil | 186 | return f.offset, nil |
| 170 | } | 187 | } |
| 171 | 188 | ||
| 172 | //返回: gzip, deflate, 优先gzip | 189 | // GetAcceptEncodingZip returns accept encoding format in http header. |
| 173 | //返回空, 表示不zip | 190 | // zip is first, then deflate if both accepted. |
| 191 | // If no accepted, return empty string. | ||
| 174 | func GetAcceptEncodingZip(r *http.Request) string { | 192 | func GetAcceptEncodingZip(r *http.Request) string { |
| 175 | ss := r.Header.Get("Accept-Encoding") | 193 | ss := r.Header.Get("Accept-Encoding") |
| 176 | ss = strings.ToLower(ss) | 194 | ss = strings.ToLower(ss) |
| ... | @@ -181,8 +199,10 @@ func GetAcceptEncodingZip(r *http.Request) string { | ... | @@ -181,8 +199,10 @@ func GetAcceptEncodingZip(r *http.Request) string { |
| 181 | } else { | 199 | } else { |
| 182 | return "" | 200 | return "" |
| 183 | } | 201 | } |
| 202 | return "" | ||
| 184 | } | 203 | } |
| 185 | 204 | ||
| 205 | // CloseZWriter closes the io.Writer after compressing static file. | ||
| 186 | func CloseZWriter(zwriter io.Writer) { | 206 | func CloseZWriter(zwriter io.Writer) { |
| 187 | if zwriter == nil { | 207 | if zwriter == nil { |
| 188 | return | 208 | return | ... | ... |
| ... | @@ -16,6 +16,7 @@ import ( | ... | @@ -16,6 +16,7 @@ import ( |
| 16 | ) | 16 | ) |
| 17 | 17 | ||
| 18 | const ( | 18 | const ( |
| 19 | // An environment variable when restarting application http listener. | ||
| 19 | FDKey = "BEEGO_HOT_FD" | 20 | FDKey = "BEEGO_HOT_FD" |
| 20 | ) | 21 | ) |
| 21 | 22 | ||
| ... | @@ -32,6 +33,7 @@ type conn struct { | ... | @@ -32,6 +33,7 @@ type conn struct { |
| 32 | lock sync.Mutex | 33 | lock sync.Mutex |
| 33 | } | 34 | } |
| 34 | 35 | ||
| 36 | // Close current processing connection. | ||
| 35 | func (c conn) Close() error { | 37 | func (c conn) Close() error { |
| 36 | c.lock.Lock() | 38 | c.lock.Lock() |
| 37 | defer c.lock.Unlock() | 39 | defer c.lock.Unlock() |
| ... | @@ -67,6 +69,8 @@ func newStoppable(l net.Listener) (sl *stoppableListener) { | ... | @@ -67,6 +69,8 @@ func newStoppable(l net.Listener) (sl *stoppableListener) { |
| 67 | return | 69 | return |
| 68 | } | 70 | } |
| 69 | 71 | ||
| 72 | // Set stopped Listener to accept requests again. | ||
| 73 | // it returns the accepted and closable connection or error. | ||
| 70 | func (sl *stoppableListener) Accept() (c net.Conn, err error) { | 74 | func (sl *stoppableListener) Accept() (c net.Conn, err error) { |
| 71 | c, err = sl.Listener.Accept() | 75 | c, err = sl.Listener.Accept() |
| 72 | if err != nil { | 76 | if err != nil { |
| ... | @@ -80,6 +84,7 @@ func (sl *stoppableListener) Accept() (c net.Conn, err error) { | ... | @@ -80,6 +84,7 @@ func (sl *stoppableListener) Accept() (c net.Conn, err error) { |
| 80 | return | 84 | return |
| 81 | } | 85 | } |
| 82 | 86 | ||
| 87 | // Listener waits signal to kill or interrupt then restart. | ||
| 83 | func WaitSignal(l net.Listener) error { | 88 | func WaitSignal(l net.Listener) error { |
| 84 | ch := make(chan os.Signal, 1) | 89 | ch := make(chan os.Signal, 1) |
| 85 | signal.Notify(ch, os.Interrupt, os.Kill) | 90 | signal.Notify(ch, os.Interrupt, os.Kill) |
| ... | @@ -101,6 +106,7 @@ func WaitSignal(l net.Listener) error { | ... | @@ -101,6 +106,7 @@ func WaitSignal(l net.Listener) error { |
| 101 | return nil // It'll never get here. | 106 | return nil // It'll never get here. |
| 102 | } | 107 | } |
| 103 | 108 | ||
| 109 | // Kill current running os process. | ||
| 104 | func CloseSelf() error { | 110 | func CloseSelf() error { |
| 105 | ppid := os.Getpid() | 111 | ppid := os.Getpid() |
| 106 | if ppid == 1 { // init provided sockets, for example systemd | 112 | if ppid == 1 { // init provided sockets, for example systemd |
| ... | @@ -140,7 +146,8 @@ func Restart(l net.Listener) error { | ... | @@ -140,7 +146,8 @@ func Restart(l net.Listener) error { |
| 140 | return nil | 146 | return nil |
| 141 | } | 147 | } |
| 142 | 148 | ||
| 143 | func GetInitListner(tcpaddr *net.TCPAddr) (l net.Listener, err error) { | 149 | // Get current net.Listen in running process. |
| 150 | func GetInitListener(tcpaddr *net.TCPAddr) (l net.Listener, err error) { | ||
| 144 | countStr := os.Getenv(FDKey) | 151 | countStr := os.Getenv(FDKey) |
| 145 | if countStr == "" { | 152 | if countStr == "" { |
| 146 | return net.ListenTCP("tcp", tcpaddr) | 153 | return net.ListenTCP("tcp", tcpaddr) | ... | ... |
| ... | @@ -19,6 +19,7 @@ import ( | ... | @@ -19,6 +19,7 @@ import ( |
| 19 | ) | 19 | ) |
| 20 | 20 | ||
| 21 | const ( | 21 | const ( |
| 22 | // default filter execution points | ||
| 22 | BeforeRouter = iota | 23 | BeforeRouter = iota |
| 23 | AfterStatic | 24 | AfterStatic |
| 24 | BeforeExec | 25 | BeforeExec |
| ... | @@ -27,6 +28,7 @@ const ( | ... | @@ -27,6 +28,7 @@ const ( |
| 27 | ) | 28 | ) |
| 28 | 29 | ||
| 29 | var ( | 30 | var ( |
| 31 | // supported http methods. | ||
| 30 | HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head"} | 32 | HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head"} |
| 31 | ) | 33 | ) |
| 32 | 34 | ||
| ... | @@ -39,6 +41,7 @@ type controllerInfo struct { | ... | @@ -39,6 +41,7 @@ type controllerInfo struct { |
| 39 | hasMethod bool | 41 | hasMethod bool |
| 40 | } | 42 | } |
| 41 | 43 | ||
| 44 | // ControllerRegistor containers registered router rules, controller handlers and filters. | ||
| 42 | type ControllerRegistor struct { | 45 | type ControllerRegistor struct { |
| 43 | routers []*controllerInfo // regexp router storage | 46 | routers []*controllerInfo // regexp router storage |
| 44 | fixrouters []*controllerInfo // fixed router storage | 47 | fixrouters []*controllerInfo // fixed router storage |
| ... | @@ -48,6 +51,7 @@ type ControllerRegistor struct { | ... | @@ -48,6 +51,7 @@ type ControllerRegistor struct { |
| 48 | autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type | 51 | autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type |
| 49 | } | 52 | } |
| 50 | 53 | ||
| 54 | // NewControllerRegistor returns a new ControllerRegistor. | ||
| 51 | func NewControllerRegistor() *ControllerRegistor { | 55 | func NewControllerRegistor() *ControllerRegistor { |
| 52 | return &ControllerRegistor{ | 56 | return &ControllerRegistor{ |
| 53 | routers: make([]*controllerInfo, 0), | 57 | routers: make([]*controllerInfo, 0), |
| ... | @@ -56,15 +60,16 @@ func NewControllerRegistor() *ControllerRegistor { | ... | @@ -56,15 +60,16 @@ func NewControllerRegistor() *ControllerRegistor { |
| 56 | } | 60 | } |
| 57 | } | 61 | } |
| 58 | 62 | ||
| 59 | //methods support like this: | 63 | // Add controller handler and pattern rules to ControllerRegistor. |
| 60 | //default methods is the same name as method | 64 | // usage: |
| 61 | //Add("/user",&UserController{}) | 65 | // default methods is the same name as method |
| 62 | //Add("/api/list",&RestController{},"*:ListFood") | 66 | // Add("/user",&UserController{}) |
| 63 | //Add("/api/create",&RestController{},"post:CreateFood") | 67 | // Add("/api/list",&RestController{},"*:ListFood") |
| 64 | //Add("/api/update",&RestController{},"put:UpdateFood") | 68 | // Add("/api/create",&RestController{},"post:CreateFood") |
| 65 | //Add("/api/delete",&RestController{},"delete:DeleteFood") | 69 | // Add("/api/update",&RestController{},"put:UpdateFood") |
| 66 | //Add("/api",&RestController{},"get,post:ApiFunc") | 70 | // Add("/api/delete",&RestController{},"delete:DeleteFood") |
| 67 | //Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc") | 71 | // Add("/api",&RestController{},"get,post:ApiFunc") |
| 72 | // Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc") | ||
| 68 | func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingMethods ...string) { | 73 | func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingMethods ...string) { |
| 69 | parts := strings.Split(pattern, "/") | 74 | parts := strings.Split(pattern, "/") |
| 70 | 75 | ||
| ... | @@ -210,11 +215,11 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM | ... | @@ -210,11 +215,11 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM |
| 210 | } | 215 | } |
| 211 | } | 216 | } |
| 212 | 217 | ||
| 213 | // add auto router to controller | 218 | // Add auto router to ControllerRegistor. |
| 214 | // example beego.AddAuto(&MainContorlller{}) | 219 | // example beego.AddAuto(&MainContorlller{}), |
| 215 | // MainController has method List and Page | 220 | // MainController has method List and Page. |
| 216 | // you can visit the url /main/list to exec List function | 221 | // visit the url /main/list to exec List function |
| 217 | // /main/page to exec Page function | 222 | // /main/page to exec Page function. |
| 218 | func (p *ControllerRegistor) AddAuto(c ControllerInterface) { | 223 | func (p *ControllerRegistor) AddAuto(c ControllerInterface) { |
| 219 | p.enableAuto = true | 224 | p.enableAuto = true |
| 220 | reflectVal := reflect.ValueOf(c) | 225 | reflectVal := reflect.ValueOf(c) |
| ... | @@ -231,6 +236,8 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) { | ... | @@ -231,6 +236,8 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) { |
| 231 | } | 236 | } |
| 232 | } | 237 | } |
| 233 | 238 | ||
| 239 | // [Deprecated] use InsertFilter. | ||
| 240 | // Add FilterFunc with pattern for action. | ||
| 234 | func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) { | 241 | func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) { |
| 235 | mr := buildFilter(pattern, filter) | 242 | mr := buildFilter(pattern, filter) |
| 236 | switch action { | 243 | switch action { |
| ... | @@ -248,12 +255,15 @@ func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc | ... | @@ -248,12 +255,15 @@ func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc |
| 248 | p.enableFilter = true | 255 | p.enableFilter = true |
| 249 | } | 256 | } |
| 250 | 257 | ||
| 258 | // Add a FilterFunc with pattern rule and action constant. | ||
| 251 | func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc) { | 259 | func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc) { |
| 252 | mr := buildFilter(pattern, filter) | 260 | mr := buildFilter(pattern, filter) |
| 253 | p.filters[pos] = append(p.filters[pos], mr) | 261 | p.filters[pos] = append(p.filters[pos], mr) |
| 254 | p.enableFilter = true | 262 | p.enableFilter = true |
| 255 | } | 263 | } |
| 256 | 264 | ||
| 265 | // UrlFor does another controller handler in this request function. | ||
| 266 | // it can access any controller method. | ||
| 257 | func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string { | 267 | func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string { |
| 258 | paths := strings.Split(endpoint, ".") | 268 | paths := strings.Split(endpoint, ".") |
| 259 | if len(paths) <= 1 { | 269 | if len(paths) <= 1 { |
| ... | @@ -369,7 +379,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string { | ... | @@ -369,7 +379,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string { |
| 369 | return "" | 379 | return "" |
| 370 | } | 380 | } |
| 371 | 381 | ||
| 372 | // main function to serveHTTP | 382 | // Implement http.Handler interface. |
| 373 | func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) { | 383 | func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) { |
| 374 | defer func() { | 384 | defer func() { |
| 375 | if err := recover(); err != nil { | 385 | if err := recover(); err != nil { |
| ... | @@ -753,8 +763,8 @@ Admin: | ... | @@ -753,8 +763,8 @@ Admin: |
| 753 | } | 763 | } |
| 754 | } | 764 | } |
| 755 | 765 | ||
| 756 | // there always should be error handler that sets error code accordingly for all unhandled errors | 766 | // there always should be error handler that sets error code accordingly for all unhandled errors. |
| 757 | // in order to have custom UI for error page it's necessary to override "500" error | 767 | // in order to have custom UI for error page it's necessary to override "500" error. |
| 758 | func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.ResponseWriter, r *http.Request) { | 768 | func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.ResponseWriter, r *http.Request) { |
| 759 | handler := middleware.SimpleServerError | 769 | handler := middleware.SimpleServerError |
| 760 | ok := true | 770 | ok := true |
| ... | @@ -771,6 +781,9 @@ func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.Resp | ... | @@ -771,6 +781,9 @@ func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.Resp |
| 771 | return handler | 781 | return handler |
| 772 | } | 782 | } |
| 773 | 783 | ||
| 784 | // returns method name from request header or form field. | ||
| 785 | // sometimes browsers can't create PUT and DELETE request. | ||
| 786 | // set a form field "_method" instead. | ||
| 774 | func (p *ControllerRegistor) getRunMethod(method string, context *beecontext.Context, router *controllerInfo) string { | 787 | func (p *ControllerRegistor) getRunMethod(method string, context *beecontext.Context, router *controllerInfo) string { |
| 775 | method = strings.ToLower(method) | 788 | method = strings.ToLower(method) |
| 776 | if method == "post" && strings.ToLower(context.Input.Query("_method")) == "put" { | 789 | if method == "post" && strings.ToLower(context.Input.Query("_method")) == "put" { |
| ... | @@ -806,6 +819,7 @@ func (w *responseWriter) Header() http.Header { | ... | @@ -806,6 +819,7 @@ func (w *responseWriter) Header() http.Header { |
| 806 | return w.writer.Header() | 819 | return w.writer.Header() |
| 807 | } | 820 | } |
| 808 | 821 | ||
| 822 | // Init content-length header. | ||
| 809 | func (w *responseWriter) InitHeadContent(contentlength int64) { | 823 | func (w *responseWriter) InitHeadContent(contentlength int64) { |
| 810 | if w.contentEncoding == "gzip" { | 824 | if w.contentEncoding == "gzip" { |
| 811 | w.Header().Set("Content-Encoding", "gzip") | 825 | w.Header().Set("Content-Encoding", "gzip") |
| ... | @@ -817,14 +831,15 @@ func (w *responseWriter) InitHeadContent(contentlength int64) { | ... | @@ -817,14 +831,15 @@ func (w *responseWriter) InitHeadContent(contentlength int64) { |
| 817 | } | 831 | } |
| 818 | 832 | ||
| 819 | // Write writes the data to the connection as part of an HTTP reply, | 833 | // Write writes the data to the connection as part of an HTTP reply, |
| 820 | // and sets `started` to true | 834 | // and sets `started` to true. |
| 835 | // started means the response has sent out. | ||
| 821 | func (w *responseWriter) Write(p []byte) (int, error) { | 836 | func (w *responseWriter) Write(p []byte) (int, error) { |
| 822 | w.started = true | 837 | w.started = true |
| 823 | return w.writer.Write(p) | 838 | return w.writer.Write(p) |
| 824 | } | 839 | } |
| 825 | 840 | ||
| 826 | // WriteHeader sends an HTTP response header with status code, | 841 | // WriteHeader sends an HTTP response header with status code, |
| 827 | // and sets `started` to true | 842 | // and sets `started` to true. |
| 828 | func (w *responseWriter) WriteHeader(code int) { | 843 | func (w *responseWriter) WriteHeader(code int) { |
| 829 | w.status = code | 844 | w.status = code |
| 830 | w.started = true | 845 | w.started = true | ... | ... |
| ... | @@ -17,6 +17,7 @@ import ( | ... | @@ -17,6 +17,7 @@ import ( |
| 17 | 17 | ||
| 18 | var ( | 18 | var ( |
| 19 | beegoTplFuncMap template.FuncMap | 19 | beegoTplFuncMap template.FuncMap |
| 20 | // beego template caching map ans supported template file extensions. | ||
| 20 | BeeTemplates map[string]*template.Template | 21 | BeeTemplates map[string]*template.Template |
| 21 | BeeTemplateExt []string | 22 | BeeTemplateExt []string |
| 22 | ) | 23 | ) |
| ... | @@ -50,7 +51,7 @@ func init() { | ... | @@ -50,7 +51,7 @@ func init() { |
| 50 | beegoTplFuncMap["urlfor"] = UrlFor // != | 51 | beegoTplFuncMap["urlfor"] = UrlFor // != |
| 51 | } | 52 | } |
| 52 | 53 | ||
| 53 | // AddFuncMap let user to register a func in the template | 54 | // AddFuncMap let user to register a func in the template. |
| 54 | func AddFuncMap(key string, funname interface{}) error { | 55 | func AddFuncMap(key string, funname interface{}) error { |
| 55 | beegoTplFuncMap[key] = funname | 56 | beegoTplFuncMap[key] = funname |
| 56 | return nil | 57 | return nil |
| ... | @@ -88,6 +89,7 @@ func (self *templatefile) visit(paths string, f os.FileInfo, err error) error { | ... | @@ -88,6 +89,7 @@ func (self *templatefile) visit(paths string, f os.FileInfo, err error) error { |
| 88 | return nil | 89 | return nil |
| 89 | } | 90 | } |
| 90 | 91 | ||
| 92 | // return this path has supported template extension of beego or not. | ||
| 91 | func HasTemplateExt(paths string) bool { | 93 | func HasTemplateExt(paths string) bool { |
| 92 | for _, v := range BeeTemplateExt { | 94 | for _, v := range BeeTemplateExt { |
| 93 | if strings.HasSuffix(paths, "."+v) { | 95 | if strings.HasSuffix(paths, "."+v) { |
| ... | @@ -97,6 +99,7 @@ func HasTemplateExt(paths string) bool { | ... | @@ -97,6 +99,7 @@ func HasTemplateExt(paths string) bool { |
| 97 | return false | 99 | return false |
| 98 | } | 100 | } |
| 99 | 101 | ||
| 102 | // add new extension for template. | ||
| 100 | func AddTemplateExt(ext string) { | 103 | func AddTemplateExt(ext string) { |
| 101 | for _, v := range BeeTemplateExt { | 104 | for _, v := range BeeTemplateExt { |
| 102 | if v == ext { | 105 | if v == ext { |
| ... | @@ -106,6 +109,8 @@ func AddTemplateExt(ext string) { | ... | @@ -106,6 +109,8 @@ func AddTemplateExt(ext string) { |
| 106 | BeeTemplateExt = append(BeeTemplateExt, ext) | 109 | BeeTemplateExt = append(BeeTemplateExt, ext) |
| 107 | } | 110 | } |
| 108 | 111 | ||
| 112 | // build all template files in a directory. | ||
| 113 | // it makes beego can render any template file in view directory. | ||
| 109 | func BuildTemplate(dir string) error { | 114 | func BuildTemplate(dir string) error { |
| 110 | if _, err := os.Stat(dir); err != nil { | 115 | if _, err := os.Stat(dir); err != nil { |
| 111 | if os.IsNotExist(err) { | 116 | if os.IsNotExist(err) { | ... | ... |
| ... | @@ -12,7 +12,7 @@ import ( | ... | @@ -12,7 +12,7 @@ import ( |
| 12 | "time" | 12 | "time" |
| 13 | ) | 13 | ) |
| 14 | 14 | ||
| 15 | // Substr() return the substr from start to length | 15 | // Substr returns the substr from start to length. |
| 16 | func Substr(s string, start, length int) string { | 16 | func Substr(s string, start, length int) string { |
| 17 | bt := []rune(s) | 17 | bt := []rune(s) |
| 18 | if start < 0 { | 18 | if start < 0 { |
| ... | @@ -27,7 +27,7 @@ func Substr(s string, start, length int) string { | ... | @@ -27,7 +27,7 @@ func Substr(s string, start, length int) string { |
| 27 | return string(bt[start:end]) | 27 | return string(bt[start:end]) |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | // Html2str() returns escaping text convert from html | 30 | // Html2str returns escaping text convert from html. |
| 31 | func Html2str(html string) string { | 31 | func Html2str(html string) string { |
| 32 | src := string(html) | 32 | src := string(html) |
| 33 | 33 | ||
| ... | @@ -60,6 +60,7 @@ func DateFormat(t time.Time, layout string) (datestring string) { | ... | @@ -60,6 +60,7 @@ func DateFormat(t time.Time, layout string) (datestring string) { |
| 60 | return | 60 | return |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | // DateFormat pattern rules. | ||
| 63 | var DatePatterns = []string{ | 64 | var DatePatterns = []string{ |
| 64 | // year | 65 | // year |
| 65 | "Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003 | 66 | "Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003 |
| ... | @@ -100,14 +101,14 @@ var DatePatterns = []string{ | ... | @@ -100,14 +101,14 @@ var DatePatterns = []string{ |
| 100 | "r", time.RFC1123Z, | 101 | "r", time.RFC1123Z, |
| 101 | } | 102 | } |
| 102 | 103 | ||
| 103 | // Parse Date use PHP time format | 104 | // Parse Date use PHP time format. |
| 104 | func DateParse(dateString, format string) (time.Time, error) { | 105 | func DateParse(dateString, format string) (time.Time, error) { |
| 105 | replacer := strings.NewReplacer(DatePatterns...) | 106 | replacer := strings.NewReplacer(DatePatterns...) |
| 106 | format = replacer.Replace(format) | 107 | format = replacer.Replace(format) |
| 107 | return time.ParseInLocation(format, dateString, time.Local) | 108 | return time.ParseInLocation(format, dateString, time.Local) |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | // Date takes a PHP like date func to Go's time format | 111 | // Date takes a PHP like date func to Go's time format. |
| 111 | func Date(t time.Time, format string) string { | 112 | func Date(t time.Time, format string) string { |
| 112 | replacer := strings.NewReplacer(DatePatterns...) | 113 | replacer := strings.NewReplacer(DatePatterns...) |
| 113 | format = replacer.Replace(format) | 114 | format = replacer.Replace(format) |
| ... | @@ -115,7 +116,7 @@ func Date(t time.Time, format string) string { | ... | @@ -115,7 +116,7 @@ func Date(t time.Time, format string) string { |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | // 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. | 118 | // 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. |
| 118 | // Whitespace is trimmed. Used by the template parser as "eq" | 119 | // Whitespace is trimmed. Used by the template parser as "eq". |
| 119 | func Compare(a, b interface{}) (equal bool) { | 120 | func Compare(a, b interface{}) (equal bool) { |
| 120 | equal = false | 121 | equal = false |
| 121 | if strings.TrimSpace(fmt.Sprintf("%v", a)) == strings.TrimSpace(fmt.Sprintf("%v", b)) { | 122 | if strings.TrimSpace(fmt.Sprintf("%v", a)) == strings.TrimSpace(fmt.Sprintf("%v", b)) { |
| ... | @@ -124,10 +125,12 @@ func Compare(a, b interface{}) (equal bool) { | ... | @@ -124,10 +125,12 @@ func Compare(a, b interface{}) (equal bool) { |
| 124 | return | 125 | return |
| 125 | } | 126 | } |
| 126 | 127 | ||
| 128 | // Convert string to template.HTML type. | ||
| 127 | func Str2html(raw string) template.HTML { | 129 | func Str2html(raw string) template.HTML { |
| 128 | return template.HTML(raw) | 130 | return template.HTML(raw) |
| 129 | } | 131 | } |
| 130 | 132 | ||
| 133 | // Htmlquote returns quoted html string. | ||
| 131 | func Htmlquote(src string) string { | 134 | func Htmlquote(src string) string { |
| 132 | //HTML编码为实体符号 | 135 | //HTML编码为实体符号 |
| 133 | /* | 136 | /* |
| ... | @@ -150,6 +153,7 @@ func Htmlquote(src string) string { | ... | @@ -150,6 +153,7 @@ func Htmlquote(src string) string { |
| 150 | return strings.TrimSpace(text) | 153 | return strings.TrimSpace(text) |
| 151 | } | 154 | } |
| 152 | 155 | ||
| 156 | // Htmlunquote returns unquoted html string. | ||
| 153 | func Htmlunquote(src string) string { | 157 | func Htmlunquote(src string) string { |
| 154 | //实体符号解释为HTML | 158 | //实体符号解释为HTML |
| 155 | /* | 159 | /* |
| ... | @@ -174,13 +178,14 @@ func Htmlunquote(src string) string { | ... | @@ -174,13 +178,14 @@ func Htmlunquote(src string) string { |
| 174 | return strings.TrimSpace(text) | 178 | return strings.TrimSpace(text) |
| 175 | } | 179 | } |
| 176 | 180 | ||
| 177 | // This will reference the index function local to the current blueprint: | 181 | // UrlFor returns url string with another registered controller handler with params. |
| 182 | // usage: | ||
| 178 | // UrlFor(".index") | 183 | // UrlFor(".index") |
| 179 | // ... print UrlFor("index") | 184 | // print UrlFor("index") |
| 180 | // ... print UrlFor("login") | 185 | // print UrlFor("login") |
| 181 | // ... print UrlFor("login", "next","/"") | 186 | // print UrlFor("login", "next","/"") |
| 182 | // ... print UrlFor("profile", "username","John Doe") | 187 | // print UrlFor("profile", "username","John Doe") |
| 183 | // ... | 188 | // result: |
| 184 | // / | 189 | // / |
| 185 | // /login | 190 | // /login |
| 186 | // /login?next=/ | 191 | // /login?next=/ |
| ... | @@ -189,7 +194,7 @@ func UrlFor(endpoint string, values ...string) string { | ... | @@ -189,7 +194,7 @@ func UrlFor(endpoint string, values ...string) string { |
| 189 | return BeeApp.UrlFor(endpoint, values...) | 194 | return BeeApp.UrlFor(endpoint, values...) |
| 190 | } | 195 | } |
| 191 | 196 | ||
| 192 | //This can be changed to a better name | 197 | // returns script tag with src string. |
| 193 | func AssetsJs(src string) template.HTML { | 198 | func AssetsJs(src string) template.HTML { |
| 194 | text := string(src) | 199 | text := string(src) |
| 195 | 200 | ||
| ... | @@ -198,7 +203,7 @@ func AssetsJs(src string) template.HTML { | ... | @@ -198,7 +203,7 @@ func AssetsJs(src string) template.HTML { |
| 198 | return template.HTML(text) | 203 | return template.HTML(text) |
| 199 | } | 204 | } |
| 200 | 205 | ||
| 201 | //This can be changed to a better name | 206 | // returns stylesheet link tag with str string. |
| 202 | func AssetsCss(src string) template.HTML { | 207 | func AssetsCss(src string) template.HTML { |
| 203 | text := string(src) | 208 | text := string(src) |
| 204 | 209 | ||
| ... | @@ -207,7 +212,7 @@ func AssetsCss(src string) template.HTML { | ... | @@ -207,7 +212,7 @@ func AssetsCss(src string) template.HTML { |
| 207 | return template.HTML(text) | 212 | return template.HTML(text) |
| 208 | } | 213 | } |
| 209 | 214 | ||
| 210 | // parse form values to struct via tag | 215 | // parse form values to struct via tag. |
| 211 | func ParseForm(form url.Values, obj interface{}) error { | 216 | func ParseForm(form url.Values, obj interface{}) error { |
| 212 | objT := reflect.TypeOf(obj) | 217 | objT := reflect.TypeOf(obj) |
| 213 | objV := reflect.ValueOf(obj) | 218 | objV := reflect.ValueOf(obj) |
| ... | @@ -295,7 +300,8 @@ var unKind = map[reflect.Kind]bool{ | ... | @@ -295,7 +300,8 @@ var unKind = map[reflect.Kind]bool{ |
| 295 | reflect.UnsafePointer: true, | 300 | reflect.UnsafePointer: true, |
| 296 | } | 301 | } |
| 297 | 302 | ||
| 298 | // obj must be a struct pointer | 303 | // render object to form html. |
| 304 | // obj must be a struct pointer. | ||
| 299 | func RenderForm(obj interface{}) template.HTML { | 305 | func RenderForm(obj interface{}) template.HTML { |
| 300 | objT := reflect.TypeOf(obj) | 306 | objT := reflect.TypeOf(obj) |
| 301 | objV := reflect.ValueOf(obj) | 307 | objV := reflect.ValueOf(obj) | ... | ... |
-
Please register or sign in to post a comment