mirror of
https://github.com/astaxie/beego.git
synced 2024-11-26 07:01:28 +00:00
Merge branch 'astaxie/develop' into develop
This commit is contained in:
commit
2ebf3cd450
@ -69,10 +69,8 @@ func (ctx *Context) Reset(rw http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Redirect does redirection to localurl with http header status code.
|
// Redirect does redirection to localurl with http header status code.
|
||||||
// It sends http response header directly.
|
|
||||||
func (ctx *Context) Redirect(status int, localurl string) {
|
func (ctx *Context) Redirect(status int, localurl string) {
|
||||||
ctx.Output.Header("Location", localurl)
|
http.Redirect(ctx.ResponseWriter, ctx.Request, localurl, status)
|
||||||
ctx.ResponseWriter.WriteHeader(status)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Abort stops this request.
|
// Abort stops this request.
|
||||||
|
32
logs/file.go
32
logs/file.go
@ -22,6 +22,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -53,7 +54,7 @@ type fileLogWriter struct {
|
|||||||
|
|
||||||
Level int `json:"level"`
|
Level int `json:"level"`
|
||||||
|
|
||||||
Perm os.FileMode `json:"perm"`
|
Perm string `json:"perm"`
|
||||||
|
|
||||||
fileNameOnly, suffix string // like "project.log", project is fileNameOnly and .log is suffix
|
fileNameOnly, suffix string // like "project.log", project is fileNameOnly and .log is suffix
|
||||||
}
|
}
|
||||||
@ -65,7 +66,7 @@ func newFileWriter() Logger {
|
|||||||
MaxDays: 7,
|
MaxDays: 7,
|
||||||
Rotate: true,
|
Rotate: true,
|
||||||
Level: LevelTrace,
|
Level: LevelTrace,
|
||||||
Perm: 0660,
|
Perm: "0660",
|
||||||
}
|
}
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
@ -79,7 +80,7 @@ func newFileWriter() Logger {
|
|||||||
// "daily":true,
|
// "daily":true,
|
||||||
// "maxDays":15,
|
// "maxDays":15,
|
||||||
// "rotate":true,
|
// "rotate":true,
|
||||||
// "perm":0600
|
// "perm":"0600"
|
||||||
// }
|
// }
|
||||||
func (w *fileLogWriter) Init(jsonConfig string) error {
|
func (w *fileLogWriter) Init(jsonConfig string) error {
|
||||||
err := json.Unmarshal([]byte(jsonConfig), w)
|
err := json.Unmarshal([]byte(jsonConfig), w)
|
||||||
@ -153,7 +154,11 @@ func (w *fileLogWriter) WriteMsg(when time.Time, msg string, level int) error {
|
|||||||
|
|
||||||
func (w *fileLogWriter) createLogFile() (*os.File, error) {
|
func (w *fileLogWriter) createLogFile() (*os.File, error) {
|
||||||
// Open the log file
|
// Open the log file
|
||||||
fd, err := os.OpenFile(w.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, w.Perm)
|
perm, err := strconv.ParseInt(w.Perm, 8, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fd, err := os.OpenFile(w.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(perm))
|
||||||
return fd, err
|
return fd, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +172,9 @@ func (w *fileLogWriter) initFd() error {
|
|||||||
w.dailyOpenTime = time.Now()
|
w.dailyOpenTime = time.Now()
|
||||||
w.dailyOpenDate = w.dailyOpenTime.Day()
|
w.dailyOpenDate = w.dailyOpenTime.Day()
|
||||||
w.maxLinesCurLines = 0
|
w.maxLinesCurLines = 0
|
||||||
|
if w.Daily {
|
||||||
|
go w.dailyRotate(w.dailyOpenTime)
|
||||||
|
}
|
||||||
if fInfo.Size() > 0 {
|
if fInfo.Size() > 0 {
|
||||||
count, err := w.lines()
|
count, err := w.lines()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -177,6 +185,22 @@ func (w *fileLogWriter) initFd() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *fileLogWriter) dailyRotate(openTime time.Time) {
|
||||||
|
y, m, d := openTime.Add(24 * time.Hour).Date()
|
||||||
|
nextDay := time.Date(y, m, d, 0, 0, 0, 0, openTime.Location())
|
||||||
|
tm := time.NewTimer(time.Duration(nextDay.UnixNano() - openTime.UnixNano() + 100))
|
||||||
|
select {
|
||||||
|
case <-tm.C:
|
||||||
|
w.Lock()
|
||||||
|
if w.needRotate(0, time.Now().Day()) {
|
||||||
|
if err := w.doRotate(time.Now()); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w *fileLogWriter) lines() (int, error) {
|
func (w *fileLogWriter) lines() (int, error) {
|
||||||
fd, err := os.Open(w.Filename)
|
fd, err := os.Open(w.Filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -17,12 +17,34 @@ package logs
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestFilePerm(t *testing.T) {
|
||||||
|
log := NewLogger(10000)
|
||||||
|
log.SetLogger("file", `{"filename":"test.log", "perm": "0600"}`)
|
||||||
|
log.Debug("debug")
|
||||||
|
log.Informational("info")
|
||||||
|
log.Notice("notice")
|
||||||
|
log.Warning("warning")
|
||||||
|
log.Error("error")
|
||||||
|
log.Alert("alert")
|
||||||
|
log.Critical("critical")
|
||||||
|
log.Emergency("emergency")
|
||||||
|
file, err := os.Stat("test.log")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if file.Mode() != 0600 {
|
||||||
|
t.Fatal("unexpected log file permission")
|
||||||
|
}
|
||||||
|
os.Remove("test.log")
|
||||||
|
}
|
||||||
|
|
||||||
func TestFile1(t *testing.T) {
|
func TestFile1(t *testing.T) {
|
||||||
log := NewLogger(10000)
|
log := NewLogger(10000)
|
||||||
log.SetLogger("file", `{"filename":"test.log"}`)
|
log.SetLogger("file", `{"filename":"test.log"}`)
|
||||||
@ -125,13 +147,28 @@ func TestFileRotate_03(t *testing.T) {
|
|||||||
os.Remove(fn)
|
os.Remove(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFileRotate_04(t *testing.T) {
|
||||||
|
fn1 := "rotate_day.log"
|
||||||
|
fn2 := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".log"
|
||||||
|
testFileDailyRotate(t, fn1, fn2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFileRotate_05(t *testing.T) {
|
||||||
|
fn1 := "rotate_day.log"
|
||||||
|
fn := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".log"
|
||||||
|
os.Create(fn)
|
||||||
|
fn2 := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".001.log"
|
||||||
|
testFileDailyRotate(t, fn1, fn2)
|
||||||
|
os.Remove(fn)
|
||||||
|
}
|
||||||
|
|
||||||
func testFileRotate(t *testing.T, fn1, fn2 string) {
|
func testFileRotate(t *testing.T, fn1, fn2 string) {
|
||||||
fw := &fileLogWriter{
|
fw := &fileLogWriter{
|
||||||
Daily: true,
|
Daily: true,
|
||||||
MaxDays: 7,
|
MaxDays: 7,
|
||||||
Rotate: true,
|
Rotate: true,
|
||||||
Level: LevelTrace,
|
Level: LevelTrace,
|
||||||
Perm: 0660,
|
Perm: "0660",
|
||||||
}
|
}
|
||||||
fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
|
fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
|
||||||
fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
|
fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
|
||||||
@ -145,6 +182,38 @@ func testFileRotate(t *testing.T, fn1, fn2 string) {
|
|||||||
}
|
}
|
||||||
os.Remove(file)
|
os.Remove(file)
|
||||||
}
|
}
|
||||||
|
fw.Destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFileDailyRotate(t *testing.T, fn1, fn2 string) {
|
||||||
|
fw := &fileLogWriter{
|
||||||
|
Daily: true,
|
||||||
|
MaxDays: 7,
|
||||||
|
Rotate: true,
|
||||||
|
Level: LevelTrace,
|
||||||
|
Perm: "0660",
|
||||||
|
}
|
||||||
|
fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
|
||||||
|
fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
|
||||||
|
fw.dailyOpenDate = fw.dailyOpenTime.Day()
|
||||||
|
today, _ := time.ParseInLocation("2006-01-02", time.Now().Format("2006-01-02"), fw.dailyOpenTime.Location())
|
||||||
|
today = today.Add(-1 * time.Second)
|
||||||
|
fw.dailyRotate(today)
|
||||||
|
for _, file := range []string{fn1, fn2} {
|
||||||
|
_, err := os.Stat(file)
|
||||||
|
if err != nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
content, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if len(content) > 0 {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
os.Remove(file)
|
||||||
|
}
|
||||||
|
fw.Destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func exists(path string) (bool, error) {
|
func exists(path string) (bool, error) {
|
||||||
|
@ -1475,7 +1475,11 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
|
|||||||
|
|
||||||
sels := strings.Join(cols, ", ")
|
sels := strings.Join(cols, ", ")
|
||||||
|
|
||||||
query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s%s%s%s", sels, Q, mi.table, Q, join, where, groupBy, orderBy, limit)
|
sqlSelect := "SELECT"
|
||||||
|
if qs.distinct {
|
||||||
|
sqlSelect += " DISTINCT"
|
||||||
|
}
|
||||||
|
query := fmt.Sprintf("%s %s FROM %s%s%s T0 %s%s%s%s%s", sqlSelect, sels, Q, mi.table, Q, join, where, groupBy, orderBy, limit)
|
||||||
|
|
||||||
d.ins.ReplaceMarks(&query)
|
d.ins.ReplaceMarks(&query)
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ func registerModel(prefix string, model interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if info.fields.pk == nil {
|
if info.fields.pk == nil {
|
||||||
fmt.Printf("<orm.RegisterModel> `%s` need a primary key field\n", name)
|
fmt.Printf("<orm.RegisterModel> `%s` need a primary key field, default use 'id' if not set\n", name)
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
192
session/ssdb/sess_ssdb.go
Normal file
192
session/ssdb/sess_ssdb.go
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
package ssdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/session"
|
||||||
|
"github.com/ssdb/gossdb/ssdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ssdbProvider = &SsdbProvider{}
|
||||||
|
|
||||||
|
type SsdbProvider struct {
|
||||||
|
client *ssdb.Client
|
||||||
|
host string
|
||||||
|
port int
|
||||||
|
maxLifetime int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SsdbProvider) connectInit() error {
|
||||||
|
var err error
|
||||||
|
if p.host == "" || p.port == 0 {
|
||||||
|
return errors.New("SessionInit First")
|
||||||
|
}
|
||||||
|
p.client, err = ssdb.Connect(p.host, p.port)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SsdbProvider) SessionInit(maxLifetime int64, savePath string) error {
|
||||||
|
var e error = nil
|
||||||
|
p.maxLifetime = maxLifetime
|
||||||
|
address := strings.Split(savePath, ":")
|
||||||
|
p.host = address[0]
|
||||||
|
p.port, e = strconv.Atoi(address[1])
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
err := p.connectInit()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SsdbProvider) SessionRead(sid string) (session.Store, error) {
|
||||||
|
if p.client == nil {
|
||||||
|
if err := p.connectInit(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var kv map[interface{}]interface{}
|
||||||
|
value, err := p.client.Get(sid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if value == nil || len(value.(string)) == 0 {
|
||||||
|
kv = make(map[interface{}]interface{})
|
||||||
|
} else {
|
||||||
|
kv, err = session.DecodeGob([]byte(value.(string)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rs := &SessionStore{sid: sid, values: kv, maxLifetime: p.maxLifetime, client: p.client}
|
||||||
|
return rs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SsdbProvider) SessionExist(sid string) bool {
|
||||||
|
if p.client == nil {
|
||||||
|
if err := p.connectInit(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value, err := p.client.Get(sid)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if value == nil || len(value.(string)) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
func (p *SsdbProvider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
|
||||||
|
//conn.Do("setx", key, v, ttl)
|
||||||
|
if p.client == nil {
|
||||||
|
if err := p.connectInit(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value, err := p.client.Get(oldsid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var kv map[interface{}]interface{}
|
||||||
|
if value == nil || len(value.(string)) == 0 {
|
||||||
|
kv = make(map[interface{}]interface{})
|
||||||
|
} else {
|
||||||
|
kv, err = session.DecodeGob([]byte(value.(string)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = p.client.Del(oldsid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, e := p.client.Do("setx", sid, value, p.maxLifetime)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
rs := &SessionStore{sid: sid, values: kv, maxLifetime: p.maxLifetime, client: p.client}
|
||||||
|
return rs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SsdbProvider) SessionDestroy(sid string) error {
|
||||||
|
if p.client == nil {
|
||||||
|
if err := p.connectInit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := p.client.Del(sid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SsdbProvider) SessionGC() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SsdbProvider) SessionAll() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type SessionStore struct {
|
||||||
|
sid string
|
||||||
|
lock sync.RWMutex
|
||||||
|
values map[interface{}]interface{}
|
||||||
|
maxLifetime int64
|
||||||
|
client *ssdb.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SessionStore) Set(key, value interface{}) error {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
s.values[key] = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *SessionStore) Get(key interface{}) interface{} {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
if value, ok := s.values[key]; ok {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SessionStore) Delete(key interface{}) error {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
delete(s.values, key)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *SessionStore) Flush() error {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
s.values = make(map[interface{}]interface{})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *SessionStore) SessionID() string {
|
||||||
|
return s.sid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SessionStore) SessionRelease(w http.ResponseWriter) {
|
||||||
|
b, err := session.EncodeGob(s.values)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.client.Do("setx", s.sid, string(b), s.maxLifetime)
|
||||||
|
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
session.Register("ssdb", ssdbProvider)
|
||||||
|
}
|
25
template.go
25
template.go
@ -33,12 +33,12 @@ import (
|
|||||||
var (
|
var (
|
||||||
beegoTplFuncMap = make(template.FuncMap)
|
beegoTplFuncMap = make(template.FuncMap)
|
||||||
// beeTemplates caching map and supported template file extensions.
|
// beeTemplates caching map and supported template file extensions.
|
||||||
beeTemplates = make(map[string]TemplateRenderer)
|
beeTemplates = make(map[string]*template.Template)
|
||||||
templatesLock sync.RWMutex
|
templatesLock sync.RWMutex
|
||||||
// beeTemplateExt stores the template extension which will build
|
// beeTemplateExt stores the template extension which will build
|
||||||
beeTemplateExt = []string{"tpl", "html"}
|
beeTemplateExt = []string{"tpl", "html"}
|
||||||
// beeTemplatePreprocessors stores associations of extension -> preprocessor handler
|
// beeTemplatePreprocessors stores associations of extension -> preprocessor handler
|
||||||
beeTemplateEngines = map[string]templateHandler{}
|
beeTemplateEngines = map[string]templatePreProcessor{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExecuteTemplate applies the template with name to the specified data object,
|
// ExecuteTemplate applies the template with name to the specified data object,
|
||||||
@ -50,11 +50,22 @@ func ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
|
|||||||
defer templatesLock.RUnlock()
|
defer templatesLock.RUnlock()
|
||||||
}
|
}
|
||||||
if t, ok := beeTemplates[name]; ok {
|
if t, ok := beeTemplates[name]; ok {
|
||||||
|
if t.Lookup(name) != nil {
|
||||||
err := t.ExecuteTemplate(wr, name, data)
|
err := t.ExecuteTemplate(wr, name, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Trace("template Execute err:", err)
|
logs.Trace("template Execute err:", err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
} else {
|
||||||
|
err := t.Execute(wr, data)
|
||||||
|
if err != nil {
|
||||||
|
if err != nil {
|
||||||
|
logs.Trace("template Execute err:", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
panic("can't find templatefile in the path:" + name)
|
panic("can't find templatefile in the path:" + name)
|
||||||
}
|
}
|
||||||
@ -94,10 +105,8 @@ func AddFuncMap(key string, fn interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type templateHandler func(root, path string, funcs template.FuncMap) (TemplateRenderer, error)
|
type templatePreProcessor func(root, path string, funcs template.FuncMap) (*template.Template, error)
|
||||||
type TemplateRenderer interface {
|
|
||||||
ExecuteTemplate(wr io.Writer, name string, data interface{}) error
|
|
||||||
}
|
|
||||||
type templateFile struct {
|
type templateFile struct {
|
||||||
root string
|
root string
|
||||||
files map[string][]string
|
files map[string][]string
|
||||||
@ -172,7 +181,7 @@ func BuildTemplate(dir string, files ...string) error {
|
|||||||
if buildAllFiles || utils.InSlice(file, files) {
|
if buildAllFiles || utils.InSlice(file, files) {
|
||||||
templatesLock.Lock()
|
templatesLock.Lock()
|
||||||
ext := filepath.Ext(file)
|
ext := filepath.Ext(file)
|
||||||
var t TemplateRenderer
|
var t *template.Template
|
||||||
if len(ext) == 0 {
|
if len(ext) == 0 {
|
||||||
t, err = getTemplate(self.root, file, v...)
|
t, err = getTemplate(self.root, file, v...)
|
||||||
} else if fn, ok := beeTemplateEngines[ext[1:]]; ok {
|
} else if fn, ok := beeTemplateEngines[ext[1:]]; ok {
|
||||||
@ -325,7 +334,7 @@ func DelStaticPath(url string) *App {
|
|||||||
return BeeApp
|
return BeeApp
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddTemplateEngine(extension string, fn templateHandler) *App {
|
func AddTemplateEngine(extension string, fn templatePreProcessor) *App {
|
||||||
AddTemplateExt(extension)
|
AddTemplateExt(extension)
|
||||||
beeTemplateEngines[extension] = fn
|
beeTemplateEngines[extension] = fn
|
||||||
return BeeApp
|
return BeeApp
|
||||||
|
Loading…
Reference in New Issue
Block a user