Commit d1bba029 authored by astaxie's avatar astaxie

refact beego config

parent 3d4ad560
......@@ -85,50 +85,11 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
data := make(map[interface{}]interface{})
switch command {
case "conf":
m := make(map[string]interface{})
m["AppName"] = AppName
m["AppPath"] = AppPath
m["AppConfigPath"] = AppConfigPath
m["StaticDir"] = StaticDir
m["StaticExtensionsToGzip"] = StaticExtensionsToGzip
m["HTTPAddr"] = HTTPAddr
m["HTTPPort"] = HTTPPort
m["HTTPTLS"] = EnableHTTPTLS
m["HTTPCertFile"] = HTTPCertFile
m["HTTPKeyFile"] = HTTPKeyFile
m["RecoverPanic"] = RecoverPanic
m["AutoRender"] = AutoRender
m["ViewsPath"] = ViewsPath
m["RunMode"] = RunMode
m["SessionOn"] = SessionOn
m["SessionProvider"] = SessionProvider
m["SessionName"] = SessionName
m["SessionGCMaxLifetime"] = SessionGCMaxLifetime
m["SessionProviderConfig"] = SessionProviderConfig
m["SessionCookieLifeTime"] = SessionCookieLifeTime
m["EnableFcgi"] = EnableFcgi
m["MaxMemory"] = MaxMemory
m["EnableGzip"] = EnableGzip
m["DirectoryIndex"] = DirectoryIndex
m["HTTPServerTimeOut"] = HTTPServerTimeOut
m["EnableErrorsShow"] = EnableErrorsShow
m["XSRFKEY"] = XSRFKEY
m["EnableXSRF"] = EnableXSRF
m["XSRFExpire"] = XSRFExpire
m["CopyRequestBody"] = CopyRequestBody
m["TemplateLeft"] = TemplateLeft
m["TemplateRight"] = TemplateRight
m["BeegoServerName"] = BeegoServerName
m["EnableAdmin"] = EnableAdmin
m["AdminHTTPAddr"] = AdminHTTPAddr
m["AdminHTTPPort"] = AdminHTTPPort
tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
tmpl = template.Must(tmpl.Parse(configTpl))
tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
data["Content"] = m
data["Content"] = BConfig
tmpl.Execute(rw, data)
......@@ -391,10 +352,10 @@ func (admin *adminApp) Run() {
if len(toolbox.AdminTaskList) > 0 {
toolbox.StartTask()
}
addr := AdminHTTPAddr
addr := BConfig.Listen.AdminAddr
if AdminHTTPPort != 0 {
addr = fmt.Sprintf("%s:%d", AdminHTTPAddr, AdminHTTPPort)
if BConfig.Listen.AdminPort != 0 {
addr = fmt.Sprintf("%s:%d", BConfig.Listen.AdminAddr, BConfig.Listen.AdminPort)
}
for p, f := range admin.routers {
http.Handle(p, f)
......@@ -402,7 +363,7 @@ func (admin *adminApp) Run() {
BeeLogger.Info("Admin server Running on %s", addr)
var err error
if Graceful {
if BConfig.Listen.Graceful {
err = grace.ListenAndServe(addr, nil)
} else {
err = http.ListenAndServe(addr, nil)
......
......@@ -52,10 +52,10 @@ func NewApp() *App {
// Run beego application.
func (app *App) Run() {
addr := HTTPAddr
addr := BConfig.Listen.HTTPAddr
if HTTPPort != 0 {
addr = fmt.Sprintf("%s:%d", HTTPAddr, HTTPPort)
if BConfig.Listen.HTTPPort != 0 {
addr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPAddr, BConfig.Listen.HTTPPort)
}
var (
......@@ -64,8 +64,8 @@ func (app *App) Run() {
)
endRunning := make(chan bool, 1)
if EnableFcgi {
if EnableStdIo {
if BConfig.Listen.EnableFcgi {
if BConfig.Listen.EnableStdIo {
err = fcgi.Serve(nil, app.Handlers) // standard I/O
if err == nil {
BeeLogger.Info("Use FCGI via standard I/O")
......@@ -73,7 +73,7 @@ func (app *App) Run() {
BeeLogger.Info("Cannot use FCGI via standard I/O", err)
}
} else {
if HTTPPort == 0 {
if BConfig.Listen.HTTPPort == 0 {
// remove the Socket file before start
if utils.FileExists(addr) {
os.Remove(addr)
......@@ -88,23 +88,23 @@ func (app *App) Run() {
err = fcgi.Serve(l, app.Handlers)
}
} else {
if Graceful {
httpsAddr := addr
app.Server.Addr = addr
if BConfig.Listen.Graceful {
httpsAddr := BConfig.Listen.HTTPSAddr
app.Server.Addr = httpsAddr
app.Server.Handler = app.Handlers
app.Server.ReadTimeout = time.Duration(HTTPServerTimeOut) * time.Second
app.Server.WriteTimeout = time.Duration(HTTPServerTimeOut) * time.Second
if EnableHTTPTLS {
app.Server.ReadTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second
app.Server.WriteTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second
if BConfig.Listen.HTTPSEnable {
go func() {
time.Sleep(20 * time.Microsecond)
if HTTPSPort != 0 {
httpsAddr = fmt.Sprintf("%s:%d", HTTPAddr, HTTPSPort)
if BConfig.Listen.HTTPSPort != 0 {
httpsAddr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPSAddr, BConfig.Listen.HTTPSPort)
app.Server.Addr = httpsAddr
}
server := grace.NewServer(httpsAddr, app.Handlers)
server.Server.ReadTimeout = app.Server.ReadTimeout
server.Server.WriteTimeout = app.Server.WriteTimeout
err := server.ListenAndServeTLS(HTTPCertFile, HTTPKeyFile)
err := server.ListenAndServeTLS(BConfig.Listen.HTTPSCertFile, BConfig.Listen.HTTPSKeyFile)
if err != nil {
BeeLogger.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
time.Sleep(100 * time.Microsecond)
......@@ -112,12 +112,12 @@ func (app *App) Run() {
}
}()
}
if EnableHTTPListen {
if BConfig.Listen.HTTPEnable {
go func() {
server := grace.NewServer(addr, app.Handlers)
server.Server.ReadTimeout = app.Server.ReadTimeout
server.Server.WriteTimeout = app.Server.WriteTimeout
if ListenTCP4 {
if BConfig.Listen.ListenTCP4 {
server.Network = "tcp4"
}
err := server.ListenAndServe()
......@@ -131,17 +131,17 @@ func (app *App) Run() {
} else {
app.Server.Addr = addr
app.Server.Handler = app.Handlers
app.Server.ReadTimeout = time.Duration(HTTPServerTimeOut) * time.Second
app.Server.WriteTimeout = time.Duration(HTTPServerTimeOut) * time.Second
app.Server.ReadTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second
app.Server.WriteTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second
if EnableHTTPTLS {
if BConfig.Listen.HTTPSEnable {
go func() {
time.Sleep(20 * time.Microsecond)
if HTTPSPort != 0 {
app.Server.Addr = fmt.Sprintf("%s:%d", HTTPAddr, HTTPSPort)
if BConfig.Listen.HTTPSPort != 0 {
app.Server.Addr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPSAddr, BConfig.Listen.HTTPSPort)
}
BeeLogger.Info("https server Running on %s", app.Server.Addr)
err := app.Server.ListenAndServeTLS(HTTPCertFile, HTTPKeyFile)
err := app.Server.ListenAndServeTLS(BConfig.Listen.HTTPSCertFile, BConfig.Listen.HTTPSKeyFile)
if err != nil {
BeeLogger.Critical("ListenAndServeTLS: ", err)
time.Sleep(100 * time.Microsecond)
......@@ -150,11 +150,11 @@ func (app *App) Run() {
}()
}
if EnableHTTPListen {
if BConfig.Listen.HTTPEnable {
go func() {
app.Server.Addr = addr
BeeLogger.Info("http server Running on %s", app.Server.Addr)
if ListenTCP4 {
if BConfig.Listen.ListenTCP4 {
ln, err := net.Listen("tcp4", app.Server.Addr)
if err != nil {
BeeLogger.Critical("ListenAndServe: ", err)
......
......@@ -15,10 +15,13 @@
package beego
import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/astaxie/beego/logs"
)
// beego web framework version.
......@@ -49,10 +52,10 @@ func Run(params ...string) {
if len(params) > 0 && params[0] != "" {
strs := strings.Split(params[0], ":")
if len(strs) > 0 && strs[0] != "" {
HTTPAddr = strs[0]
BConfig.Listen.HTTPAddr = strs[0]
}
if len(strs) > 1 && strs[1] != "" {
HTTPPort, _ = strconv.Atoi(strs[1])
BConfig.Listen.HTTPPort, _ = strconv.Atoi(strs[1])
}
}
......@@ -60,15 +63,22 @@ func Run(params ...string) {
}
func initBeforeHTTPRun() {
// if AppConfigPath not In the conf/app.conf reParse config
if AppConfigPath != filepath.Join(AppPath, "conf", "app.conf") {
err := ParseConfig()
if err != nil && AppConfigPath != filepath.Join(workPath, "conf", "app.conf") {
// configuration is critical to app, panic here if parse failed
panic(err)
// if AppConfigPath is setted or conf/app.conf exist
err := ParseConfig()
if err != nil {
panic(err)
}
//init log
BeeLogger = logs.NewLogger(10000)
for adaptor, config := range BConfig.Log.Output {
err = BeeLogger.SetLogger(adaptor, config)
if err != nil {
fmt.Printf("%s with the config `%s` got err:%s\n", adaptor, config, err)
}
}
SetLogFuncCall(BConfig.Log.FileLineNum)
//init hooks
AddAPPStartHook(registerMime)
AddAPPStartHook(registerDefaultErrorHandler)
......@@ -85,15 +95,9 @@ func initBeforeHTTPRun() {
}
// TestBeegoInit is for test package init
func TestBeegoInit(apppath string) {
AppPath = apppath
func TestBeegoInit(ap string) {
os.Setenv("BEEGO_RUNMODE", "test")
AppConfigPath = filepath.Join(AppPath, "conf", "app.conf")
err := ParseConfig()
if err != nil && !os.IsNotExist(err) {
// for init if doesn't have app.conf will not panic
Info(err)
}
os.Chdir(AppPath)
AppConfigPath = filepath.Join(ap, "conf", "app.conf")
os.Chdir(ap)
initBeforeHTTPRun()
}
This diff is collapsed.
......@@ -19,11 +19,11 @@ import (
)
func TestDefaults(t *testing.T) {
if FlashName != "BEEGO_FLASH" {
if BConfig.WebConfig.FlashName != "BEEGO_FLASH" {
t.Errorf("FlashName was not set to default.")
}
if FlashSeperator != "BEEGOFLASH" {
if BConfig.WebConfig.FlashSeperator != "BEEGOFLASH" {
t.Errorf("FlashName was not set to default.")
}
}
......@@ -200,7 +200,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
c.TplNames = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
}
if RunMode == "dev" {
if BConfig.RunMode == "dev" {
buildFiles := make([]string, 1)
buildFiles = append(buildFiles, c.TplNames)
if c.LayoutSections != nil {
......@@ -211,7 +211,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
buildFiles = append(buildFiles, sectionTpl)
}
}
BuildTemplate(ViewsPath, buildFiles...)
BuildTemplate(BConfig.WebConfig.ViewsPath, buildFiles...)
}
newbytes := bytes.NewBufferString("")
if _, ok := BeeTemplates[c.TplNames]; !ok {
......@@ -256,8 +256,8 @@ func (c *Controller) RenderBytes() ([]byte, error) {
if c.TplNames == "" {
c.TplNames = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
}
if RunMode == "dev" {
BuildTemplate(ViewsPath, c.TplNames)
if BConfig.RunMode == "dev" {
BuildTemplate(BConfig.WebConfig.ViewsPath, c.TplNames)
}
ibytes := bytes.NewBufferString("")
if _, ok := BeeTemplates[c.TplNames]; !ok {
......@@ -319,7 +319,7 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string {
func (c *Controller) ServeJSON(encoding ...bool) {
var hasIndent bool
var hasencoding bool
if RunMode == "prod" {
if BConfig.RunMode == "prod" {
hasIndent = false
} else {
hasIndent = true
......@@ -333,7 +333,7 @@ func (c *Controller) ServeJSON(encoding ...bool) {
// ServeJSONP sends a jsonp response.
func (c *Controller) ServeJSONP() {
var hasIndent bool
if RunMode == "prod" {
if BConfig.RunMode == "prod" {
hasIndent = false
} else {
hasIndent = true
......@@ -344,7 +344,7 @@ func (c *Controller) ServeJSONP() {
// ServeXML sends xml response.
func (c *Controller) ServeXML() {
var hasIndent bool
if RunMode == "prod" {
if BConfig.RunMode == "prod" {
hasIndent = false
} else {
hasIndent = true
......@@ -628,9 +628,9 @@ func (c *Controller) XSRFToken() string {
if c.XSRFExpire > 0 {
expire = int64(c.XSRFExpire)
} else {
expire = int64(XSRFExpire)
expire = int64(BConfig.WebConfig.XSRFExpire)
}
c._xsrfToken = c.Ctx.XSRFToken(XSRFKEY, expire)
c._xsrfToken = c.Ctx.XSRFToken(BConfig.WebConfig.XSRFKEY, expire)
}
return c._xsrfToken
}
......
......@@ -15,30 +15,25 @@
package beego
import (
"fmt"
"github.com/astaxie/beego/context"
"testing"
"github.com/astaxie/beego/context"
)
func TestGetInt(t *testing.T) {
i := &context.BeegoInput{Params: map[string]string{"age": "40"}}
ctx := &context.Context{Input: i}
ctrlr := Controller{Ctx: ctx}
val, _ := ctrlr.GetInt("age")
if (val != 40) {
if val != 40 {
t.Errorf("TestGetInt expect 40,get %T,%v", val, val)
}
}
func TestGetInt8(t *testing.T) {
i := &context.BeegoInput{Params: map[string]string{"age": "40"}}
ctx := &context.Context{Input: i}
ctrlr := Controller{Ctx: ctx}
val, _ := ctrlr.GetInt8("age")
if val != 40 {
t.Errorf("TestGetInt8 expect 40,get %T,%v", val, val)
......@@ -47,11 +42,9 @@ func TestGetInt8(t *testing.T) {
}
func TestGetInt16(t *testing.T) {
i := &context.BeegoInput{Params: map[string]string{"age": "40"}}
ctx := &context.Context{Input: i}
ctrlr := Controller{Ctx: ctx}
val, _ := ctrlr.GetInt16("age")
if val != 40 {
t.Errorf("TestGetInt16 expect 40,get %T,%v", val, val)
......@@ -59,24 +52,19 @@ func TestGetInt16(t *testing.T) {
}
func TestGetInt32(t *testing.T) {
i := &context.BeegoInput{Params: map[string]string{"age": "40"}}
ctx := &context.Context{Input: i}
ctrlr := Controller{Ctx: ctx}
val, _ := ctrlr.GetInt32("age")
fmt.Printf("%T", val)
if val != 40 {
t.Errorf("TestGetInt32 expect 40,get %T,%v", val, val)
}
}
func TestGetInt64(t *testing.T) {
i := &context.BeegoInput{Params: map[string]string{"age": "40"}}
ctx := &context.Context{Input: i}
ctrlr := Controller{Ctx: ctx}
val, _ := ctrlr.GetInt64("age")
if val != 40 {
t.Errorf("TestGeetInt64 expect 40,get %T,%v", val, val)
......
......@@ -24,7 +24,7 @@ import (
var GlobalDocAPI map[string]interface{}
func init() {
if EnableDocs {
if BConfig.WebConfig.EnableDocs {
GlobalDocAPI = make(map[string]interface{})
}
}
......
......@@ -85,7 +85,7 @@ var tpl = `
func showErr(err interface{}, ctx *context.Context, Stack string) {
t, _ := template.New("beegoerrortemp").Parse(tpl)
data := make(map[string]string)
data["AppError"] = AppName + ":" + fmt.Sprint(err)
data["AppError"] = BConfig.AppName + ":" + fmt.Sprint(err)
data["RequestMethod"] = ctx.Input.Method()
data["RequestURL"] = ctx.Input.URI()
data["RemoteAddr"] = ctx.Input.IP()
......@@ -437,7 +437,7 @@ func executeError(err *errorInfo, ctx *context.Context, code int) {
method.Call(in)
//render template
if AutoRender {
if BConfig.WebConfig.AutoRender {
if err := execController.Render(); err != nil {
panic(err)
}
......
......@@ -20,8 +20,14 @@ import (
"testing"
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/logs"
)
func init() {
BeeLogger = logs.NewLogger(10000)
BeeLogger.SetLogger("console", "")
}
var FilterUser = func(ctx *context.Context) {
ctx.Output.Body([]byte("i am " + ctx.Input.Params[":last"] + ctx.Input.Params[":first"]))
}
......
......@@ -83,27 +83,27 @@ func (fd *FlashData) Store(c *Controller) {
c.Data["flash"] = fd.Data
var flashValue string
for key, value := range fd.Data {
flashValue += "\x00" + key + "\x23" + FlashSeperator + "\x23" + value + "\x00"
flashValue += "\x00" + key + "\x23" + BConfig.WebConfig.FlashSeperator + "\x23" + value + "\x00"
}
c.Ctx.SetCookie(FlashName, url.QueryEscape(flashValue), 0, "/")
c.Ctx.SetCookie(BConfig.WebConfig.FlashName, url.QueryEscape(flashValue), 0, "/")
}
// ReadFromRequest parsed flash data from encoded values in cookie.
func ReadFromRequest(c *Controller) *FlashData {
flash := NewFlash()
if cookie, err := c.Ctx.Request.Cookie(FlashName); err == nil {
if cookie, err := c.Ctx.Request.Cookie(BConfig.WebConfig.FlashName); err == nil {
v, _ := url.QueryUnescape(cookie.Value)
vals := strings.Split(v, "\x00")
for _, v := range vals {
if len(v) > 0 {
kv := strings.Split(v, "\x23"+FlashSeperator+"\x23")
kv := strings.Split(v, "\x23"+BConfig.WebConfig.FlashSeperator+"\x23")
if len(kv) == 2 {
flash.Data[kv[0]] = kv[1]
}
}
}
//read one time then delete it
c.Ctx.SetCookie(FlashName, "", -1, "/")
c.Ctx.SetCookie(BConfig.WebConfig.FlashName, "", -1, "/")
}
c.Data["flash"] = flash.Data
return flash
......
......@@ -41,19 +41,19 @@ func registerDefaultErrorHandler() error {
}
func registerSession() error {
if SessionOn {
if BConfig.WebConfig.Session.SessionOn {
var err error
sessionConfig := AppConfig.String("sessionConfig")
if sessionConfig == "" {
sessionConfig = `{"cookieName":"` + SessionName + `",` +
`"gclifetime":` + strconv.FormatInt(SessionGCMaxLifetime, 10) + `,` +
`"providerConfig":"` + filepath.ToSlash(SessionProviderConfig) + `",` +
`"secure":` + strconv.FormatBool(EnableHTTPTLS) + `,` +
`"enableSetCookie":` + strconv.FormatBool(SessionAutoSetCookie) + `,` +
`"domain":"` + SessionDomain + `",` +
`"cookieLifeTime":` + strconv.Itoa(SessionCookieLifeTime) + `}`
sessionConfig = `{"cookieName":"` + BConfig.WebConfig.Session.SessionName + `",` +
`"gclifetime":` + strconv.FormatInt(BConfig.WebConfig.Session.SessionGCMaxLifetime, 10) + `,` +
`"providerConfig":"` + filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig) + `",` +
`"secure":` + strconv.FormatBool(BConfig.Listen.HTTPSEnable) + `,` +
`"enableSetCookie":` + strconv.FormatBool(BConfig.WebConfig.Session.SessionAutoSetCookie) + `,` +
`"domain":"` + BConfig.WebConfig.Session.SessionDomain + `",` +
`"cookieLifeTime":` + strconv.Itoa(BConfig.WebConfig.Session.SessionCookieLifeTime) + `}`
}
GlobalSessions, err = session.NewManager(SessionProvider, sessionConfig)
GlobalSessions, err = session.NewManager(BConfig.WebConfig.Session.SessionProvider, sessionConfig)
if err != nil {
return err
}
......@@ -63,9 +63,9 @@ func registerSession() error {
}
func registerTemplate() error {
if AutoRender {
err := BuildTemplate(ViewsPath)
if err != nil && RunMode == "dev" {
if BConfig.WebConfig.AutoRender {
err := BuildTemplate(BConfig.WebConfig.ViewsPath)
if err != nil && BConfig.RunMode == "dev" {
Warn(err)
}
}
......@@ -73,7 +73,7 @@ func registerTemplate() error {
}
func registerDocs() error {
if EnableDocs {
if BConfig.WebConfig.EnableDocs {
Get("/docs", serverDocs)
Get("/docs/*", serverDocs)
}
......@@ -81,7 +81,7 @@ func registerDocs() error {
}
func registerAdmin() error {
if EnableAdmin {
if BConfig.Listen.AdminEnable {
go beeAdminApp.Run()
}
return nil
......
......@@ -130,7 +130,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
}
func genRouterCode() {
os.Mkdir(path.Join(workPath, "routers"), 0755)
os.Mkdir("routers", 0755)
Info("generate router from comments")
var (
globalinfo string
......@@ -172,7 +172,7 @@ func genRouterCode() {
}
}
if globalinfo != "" {
f, err := os.Create(path.Join(workPath, "routers", commentFilename))
f, err := os.Create(path.Join("routers", commentFilename))
if err != nil {
panic(err)
}
......@@ -182,11 +182,11 @@ func genRouterCode() {
}
func compareFile(pkgRealpath string) bool {
if !utils.FileExists(path.Join(workPath, "routers", commentFilename)) {
if !utils.FileExists(path.Join("routers", commentFilename)) {
return true
}
if utils.FileExists(path.Join(workPath, lastupdateFilename)) {
content, err := ioutil.ReadFile(path.Join(workPath, lastupdateFilename))
if utils.FileExists(lastupdateFilename) {
content, err := ioutil.ReadFile(lastupdateFilename)
if err != nil {
return true
}
......@@ -214,7 +214,7 @@ func savetoFile(pkgRealpath string) {
if err != nil {
return
}
ioutil.WriteFile(path.Join(workPath, lastupdateFilename), d, os.ModePerm)
ioutil.WriteFile(lastupdateFilename, d, os.ModePerm)
}
func getpathTime(pkgRealpath string) (lastupdate int64, err error) {
......
......@@ -220,7 +220,7 @@ func Test_Preflight(t *testing.T) {
func Benchmark_WithoutCORS(b *testing.B) {
recorder := httptest.NewRecorder()
handler := beego.NewControllerRegister()
beego.RunMode = "prod"
beego.BConfig.RunMode = "prod"
handler.Any("/foo", func(ctx *context.Context) {
ctx.Output.SetStatus(500)
})
......@@ -234,7 +234,7 @@ func Benchmark_WithoutCORS(b *testing.B) {
func Benchmark_WithCORS(b *testing.B) {
recorder := httptest.NewRecorder()
handler := beego.NewControllerRegister()
beego.RunMode = "prod"
beego.BConfig.RunMode = "prod"
handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
AllowAllOrigins: true,
AllowCredentials: true,
......
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package jwt provides JWT (Json Web Token) authentication
//
// Usage
// In file main.go
//
// import (
// "github.com/astaxie/beego"
// "github.com/astaxie/beego/plugins/jwt"
// )
//
// func main() {
// // JWT for Url matching /v1/*
// // PrivateKeyPath: The path for the private RSA key used by JWT
// // PublicKeyPath: The path for the public RSA key used by JWT
// // The list of Urls should be excluded from the JWT Auth
// beego.InsertFilter("/v1/*", beego.BeforeRouter, jwt.AuthRequest(&jwt.Options{
// PrivateKeyPath: "conf/beeblog.rsa",
// PublicKeyPath: "conf/beeblog.rsa.pub",
// WhiteList: []string{"/v1/jwt/issue-token", "/docs"},
// }))
// beego.Run()
// }
//
// In file routers/router.go
//
// import (
// "github.com/astaxie/beego"
// "github.com/astaxie/beego/plugins/jwt"
// )
// func init() {
// ns := beego.NSNamespace("/jwt",
// beego.NSInclude(
// &jwt.JwtController{},
// ),
// )
// beego.AddNamespace(ns)
// }
//
package jwt
import (
"io/ioutil"
"net/http"
"time"
"github.com/astaxie/beego"
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/logs"
goJwt "github.com/dgrijalva/jwt-go"
)
// Options for the JWT Auth
type Options struct {
PrivateKeyPath string
PublicKeyPath string
WhiteList []string
}
// RSAKeys store PrivateKey and PublicKey
var RSAKeys struct {
PrivateKey []byte
PublicKey []byte
}
// AuthRequest retunn FilterFunc
func AuthRequest(o *Options) beego.FilterFunc {
RSAKeys.PrivateKey, _ = ioutil.ReadFile(o.PrivateKeyPath)
RSAKeys.PublicKey, _ = ioutil.ReadFile(o.PublicKeyPath)
return func(ctx *context.Context) {
// :TODO the url patterns should be considered here.
// Shouldn't only use the string equal
for _, method := range o.WhiteList {
if method == ctx.Request.URL.Path {
return
}
}
parsedToken, err := goJwt.ParseFromRequest(ctx.Request, func(t *goJwt.Token) (interface{}, error) {
return RSAKeys.PublicKey, nil
})
if err == nil && parsedToken.Valid {
ctx.Output.SetStatus(http.StatusOK)
} else {
ctx.Output.SetStatus(http.StatusUnauthorized)
}
}
}
// Controller oprations for Jwt
type Controller struct {
beego.Controller
}
// URLMapping is used to mapping the string to method
func (c *Controller) URLMapping() {
c.Mapping("IssueToken", c.IssueToken)
}
// IssueToken function
// @Title IssueToken
// @Description Issue a Json Web Token
// @Success 200 string
// @Failure 403 no privilege to access
// @Failure 500 server inner error
// @router /issue-token [get]
func (c *Controller) IssueToken() {
c.Data["json"] = CreateToken()
c.ServeJSON()
}
// CreateToken return the token
func CreateToken() map[string]string {
log := logs.NewLogger(10000)
log.SetLogger("console", "")
token := goJwt.New(goJwt.GetSigningMethod("RS256")) // Create a Token that will be signed with RSA 256.
token.Claims["ID"] = "This is my super fake ID"
token.Claims["exp"] = time.Now().Unix() + 36000
// The claims object allows you to store information in the actual token.
tokenString, _ := token.SignedString(RSAKeys.PrivateKey)
// tokenString Contains the actual token you should share with your client.
return map[string]string{"token": tokenString}
}
package jwt
import (
"github.com/astaxie/beego"
"net/http"
"net/http/httptest"
"testing"
)
func testRequest(method, path string) (*httptest.ResponseRecorder, *http.Request) {
request, _ := http.NewRequest(method, path, nil)
recorder := httptest.NewRecorder()
return recorder, request
}
func Test_IssueTokenAction(t *testing.T) {
url := "/v1/jwt/issue-token"
mux := beego.NewControllerRegister()
mux.InsertFilter("*", beego.BeforeRouter, AuthRequest(&Options{
PrivateKeyPath: "test/jwt.rsa",
PublicKeyPath: "test/jwt.rsa.pub",
WhiteList: []string{"/v1/jwt/issue-token", "/docs"},
}))
mux.Add("/v1/jwt/issue-token", &JwtController{}, "get:IssueToken")
rw, r := testRequest("GET", url)
mux.ServeHTTP(rw, r)
if rw.Code != http.StatusOK {
t.Errorf("Shoud return 200")
}
}
func (tc *JwtController) Foo() {
tc.Ctx.Output.Body([]byte("ok"))
}
func Test_AuthRequestWithAuthorizationHeader(t *testing.T) {
url := "/foo"
mux := beego.NewControllerRegister()
mux.InsertFilter("*", beego.BeforeRouter, AuthRequest(&Options{
PrivateKeyPath: "test/jwt.rsa",
PublicKeyPath: "test/jwt.rsa.pub",
WhiteList: []string{"/v1/jwt/issue-token", "/docs"},
}))
mux.Add("/foo", &JwtController{}, "get:Foo")
newToken := CreateToken()
rw, r := testRequest("GET", url)
r.Header.Add("Authorization", "Bearer "+newToken["token"])
mux.ServeHTTP(rw, r)
if rw.Code != http.StatusOK {
t.Errorf("Shoud return 200")
}
if rw.Body.String() != "ok" {
t.Errorf("Should output ok")
}
}
func Test_AuthRequestWithoutAuthorizationHeader(t *testing.T) {
url := "/foo"
mux := beego.NewControllerRegister()
mux.InsertFilter("*", beego.BeforeRouter, AuthRequest(&Options{
PrivateKeyPath: "test/jwt.rsa",
PublicKeyPath: "test/jwt.rsa.pub",
WhiteList: []string{"/v1/jwt/issue-token", "/docs"},
}))
mux.Add("/foo", &JwtController{}, "get:Foo")
rw, r := testRequest("GET", url)
mux.ServeHTTP(rw, r)
if rw.Code != http.StatusUnauthorized {
t.Errorf("Shoud return 401")
}
}
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCdu+23Y/0J/FTQKnIPnxupoOo9/OYCv90DPXN/KLLRAMjYzgcC
DsBST2xVR5jlimI/gyfCpVB62dwpSzzr0cA3MoDhbaGWuTdQUX9zmiLoQ4I7X6h0
dwyiihOz+CzOMlAg5+qBhiTGcKvIFlfEc1FUcn/tB3PVRG9j6B1Ibz5CnQIDAQAB
AoGAFGg+/i4ai9MwqeoD7c95Bb5C8BgrLgnir0uhCL+cOvwuABbPw01jRoLuEi58
Mp5vzaXLXByFSA+ts03/qMbvZkDGac5g5kLli5TjHIONMxVBrdfGQ1+OApnaPayN
N+HYjZKs6xao6J5iFqfA0FqzDR9kQhUoeosdQoo1GlxDckECQQDO/0LJrFiLzYWe
qS/DxfAnFu2BlClKZjxRJ3vIkRRaON6HPl8BeJW901bFKG5+WSfO+OwQ9egWaf3X
fFm/oEHRAkEAwxMor4fOkBZbL4KPW7sen169vwnXuYusqj0t3dIeiIVrCigkOMT4
OvX/63u4CTdXh1D5u/4Z/1HTYH92VCP7DQJAJPxbNKnE0IYSf/z++d4eQP3JxkNw
9Ug7Msz5QycZGd3bdRLh6uNe7iIa+PN2esD3afX0SDuIEqkxoBUp/CFoYQJAUmi3
mV+/7bLkFrALK+9iwmTdt+TKk4HkEY8C32CysW3biFDo7GqZix79XFfJqWsNuQaG
WdrA1NGWgH+YV3dTyQJAIWEZGAuUXRkQB20LfjGzpsKgQFbqjTisMS0qe3JjnDwu
0JR8sYXapgeEEEisH+OtkZKIfyeFOwoUyNC83bcvgw==
-----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdu+23Y/0J/FTQKnIPnxupoOo9
/OYCv90DPXN/KLLRAMjYzgcCDsBST2xVR5jlimI/gyfCpVB62dwpSzzr0cA3MoDh
baGWuTdQUX9zmiLoQ4I7X6h0dwyiihOz+CzOMlAg5+qBhiTGcKvIFlfEc1FUcn/t
B3PVRG9j6B1Ibz5CnQIDAQAB
-----END PUBLIC KEY-----
......@@ -87,7 +87,7 @@ func (l *logFilter) Filter(ctx *beecontext.Context) bool {
if requestPath == "/favicon.ico" || requestPath == "/robots.txt" {
return true
}
for prefix := range StaticDir {
for prefix := range BConfig.WebConfig.StaticDir {
if strings.HasPrefix(requestPath, prefix) {
return true
}
......@@ -183,7 +183,7 @@ func (p *ControllerRegister) Add(pattern string, c ControllerInterface, mappingM
}
func (p *ControllerRegister) addToRouter(method, pattern string, r *controllerInfo) {
if !RouterCaseSensitive {
if !BConfig.RouterCaseSensitive {
pattern = strings.ToLower(pattern)
}
if t, ok := p.routers[method]; ok {
......@@ -198,7 +198,7 @@ func (p *ControllerRegister) addToRouter(method, pattern string, r *controllerIn
// Include only when the Runmode is dev will generate router file in the router/auto.go from the controller
// Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{})
func (p *ControllerRegister) Include(cList ...ControllerInterface) {
if RunMode == "dev" {
if BConfig.RunMode == "dev" {
skip := make(map[string]bool, 10)
for _, c := range cList {
reflectVal := reflect.ValueOf(c)
......@@ -406,7 +406,7 @@ func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter Filter
mr.tree = NewTree()
mr.pattern = pattern
mr.filterFunc = filter
if !RouterCaseSensitive {
if !BConfig.RouterCaseSensitive {
pattern = strings.ToLower(pattern)
}
if len(params) == 0 {
......@@ -580,8 +580,8 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
w := &responseWriter{rw, false, 0}
if RunMode == "dev" {
w.Header().Set("Server", BeegoServerName)
if BConfig.RunMode == "dev" {
w.Header().Set("Server", BConfig.ServerName)
}
// init context
......@@ -592,12 +592,12 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
Output: beecontext.NewOutput(),
}
context.Output.Context = context
context.Output.EnableGzip = EnableGzip
context.Output.EnableGzip = BConfig.EnableGzip
defer p.recoverPanic(context)
var urlPath string
if !RouterCaseSensitive {
if !BConfig.RouterCaseSensitive {
urlPath = strings.ToLower(r.URL.Path)
} else {
urlPath = r.URL.Path
......@@ -646,7 +646,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
}
// session init
if SessionOn {
if BConfig.WebConfig.Session.SessionOn {
var err error
context.Input.CruSession, err = GlobalSessions.SessionStart(w, r)
if err != nil {
......@@ -660,10 +660,10 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
}
if r.Method != "GET" && r.Method != "HEAD" {
if CopyRequestBody && !context.Input.IsUpload() {
if BConfig.CopyRequestBody && !context.Input.IsUpload() {
context.Input.CopyBody()
}
context.Input.ParseFormOrMulitForm(MaxMemory)
context.Input.ParseFormOrMulitForm(BConfig.MaxMemory)
}
if doFilter(BeforeRouter) {
......@@ -765,7 +765,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
execController.Prepare()
//if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf
if EnableXSRF {
if BConfig.WebConfig.EnableXSRF {
execController.XSRFToken()
if r.Method == "POST" || r.Method == "DELETE" || r.Method == "PUT" ||
(r.Method == "POST" && (context.Input.Query("_method") == "DELETE" || context.Input.Query("_method") == "PUT")) {
......@@ -802,7 +802,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
//render template
if !w.started && context.Output.Status == 0 {
if AutoRender {
if BConfig.WebConfig.AutoRender {
if err := execController.Render(); err != nil {
panic(err)
}
......@@ -825,7 +825,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
Admin:
timeend := time.Since(starttime)
//admin module record QPS
if EnableAdmin {
if BConfig.Listen.AdminEnable {
if FilterMonitorFunc(r.Method, r.URL.Path, timeend) {
if runrouter != nil {
go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runrouter.Name(), timeend)
......@@ -835,7 +835,7 @@ Admin:
}
}
if RunMode == "dev" || AccessLogs {
if BConfig.RunMode == "dev" || BConfig.Log.AccessLogs {
var devinfo string
if findrouter {
if routerInfo != nil {
......@@ -862,10 +862,10 @@ func (p *ControllerRegister) recoverPanic(context *beecontext.Context) {
if err == ErrAbort {
return
}
if !RecoverPanic {
if !BConfig.RecoverPanic {
panic(err)
} else {
if EnableErrorsShow {
if BConfig.EnableErrorsShow {
if _, ok := ErrorMaps[fmt.Sprint(err)]; ok {
exception(fmt.Sprint(err), context)
return
......@@ -882,7 +882,7 @@ func (p *ControllerRegister) recoverPanic(context *beecontext.Context) {
Critical(fmt.Sprintf("%s:%d", file, line))
stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d", file, line))
}
if RunMode == "dev" {
if BConfig.RunMode == "dev" {
showErr(err, context, stack)
}
}
......
......@@ -49,7 +49,7 @@ func serverStaticRouter(ctx *context.Context) {
}
if filePath == "" || fileInfo == nil {
if RunMode == "dev" {
if BConfig.RunMode == "dev" {
Warn("Can't find/open the file:", filePath, err)
}
http.NotFound(ctx.ResponseWriter, ctx.Request)
......@@ -61,14 +61,14 @@ func serverStaticRouter(ctx *context.Context) {
return
}
var enableCompress = EnableGzip && isStaticCompress(filePath)
var enableCompress = BConfig.EnableGzip && isStaticCompress(filePath)
var acceptEncoding string
if enableCompress {
acceptEncoding = context.ParseEncoding(ctx.Request)
}
b, n, sch, err := openFile(filePath, fileInfo, acceptEncoding)
if err != nil {
if RunMode == "dev" {
if BConfig.RunMode == "dev" {
Warn("Can't compress the file:", filePath, err)
}
http.NotFound(ctx.ResponseWriter, ctx.Request)
......@@ -133,7 +133,7 @@ func isOk(s *serveContentHolder, fi os.FileInfo) bool {
// isStaticCompress detect static files
func isStaticCompress(filePath string) bool {
for _, statExtension := range StaticExtensionsToGzip {
for _, statExtension := range BConfig.WebConfig.StaticExtensionsToGzip {
if strings.HasSuffix(strings.ToLower(filePath), strings.ToLower(statExtension)) {
return true
}
......@@ -151,7 +151,7 @@ func searchFile(ctx *context.Context) (string, os.FileInfo, error) {
if fi, _ := os.Stat(file); fi != nil {
return file, fi, nil
}
for _, staticDir := range StaticDir {
for _, staticDir := range BConfig.WebConfig.StaticDir {
filePath := path.Join(staticDir, requestPath)
if fi, _ := os.Stat(filePath); fi != nil {
return filePath, fi, nil
......@@ -160,7 +160,7 @@ func searchFile(ctx *context.Context) (string, os.FileInfo, error) {
return "", nil, errors.New(requestPath + " file not find")
}
for prefix, staticDir := range StaticDir {
for prefix, staticDir := range BConfig.WebConfig.StaticDir {
if len(prefix) == 0 {
continue
}
......@@ -193,5 +193,5 @@ func lookupFile(ctx *context.Context) (bool, string, os.FileInfo, error) {
if ifi, _ := os.Stat(ifp); ifi != nil && ifi.Mode().IsRegular() {
return false, ifp, ifi, err
}
return !DirectoryIndex, fp, fi, err
return !BConfig.WebConfig.DirectoryIndex, fp, fi, err
}
......@@ -176,7 +176,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
if err != nil {
return nil, [][]string{}, err
}
reg := regexp.MustCompile(TemplateLeft + "[ ]*template[ ]+\"([^\"]+)\"")
reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*template[ ]+\"([^\"]+)\"")
allsub := reg.FindAllStringSubmatch(string(data), -1)
for _, m := range allsub {
if len(m) == 2 {
......@@ -197,7 +197,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
}
func getTemplate(root, file string, others ...string) (t *template.Template, err error) {
t = template.New(file).Delims(TemplateLeft, TemplateRight).Funcs(beegoTplFuncMap)
t = template.New(file).Delims(BConfig.WebConfig.TemplateLeft, BConfig.WebConfig.TemplateRight).Funcs(beegoTplFuncMap)
var submods [][]string
t, submods, err = getTplDeep(root, file, "", t)
if err != nil {
......@@ -239,7 +239,7 @@ func _getTemplate(t0 *template.Template, root string, submods [][]string, others
if err != nil {
continue
}
reg := regexp.MustCompile(TemplateLeft + "[ ]*define[ ]+\"([^\"]+)\"")
reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*define[ ]+\"([^\"]+)\"")
allsub := reg.FindAllStringSubmatch(string(data), -1)
for _, sub := range allsub {
if len(sub) == 2 && sub[1] == m[1] {
......@@ -262,7 +262,7 @@ func _getTemplate(t0 *template.Template, root string, submods [][]string, others
// SetViewsPath sets view directory path in beego application.
func SetViewsPath(path string) *App {
ViewsPath = path
BConfig.WebConfig.ViewsPath = path
return BeeApp
}
......@@ -273,7 +273,7 @@ func SetStaticPath(url string, path string) *App {
url = "/" + url
}
url = strings.TrimRight(url, "/")
StaticDir[url] = path
BConfig.WebConfig.StaticDir[url] = path
return BeeApp
}
......@@ -283,6 +283,6 @@ func DelStaticPath(url string) *App {
url = "/" + url
}
url = strings.TrimRight(url, "/")
delete(StaticDir, url)
delete(BConfig.WebConfig.StaticDir, url)
return BeeApp
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment