mirror of
https://github.com/astaxie/beego.git
synced 2024-11-24 15:50:54 +00:00
release new version 1.1.4
This commit is contained in:
commit
82ca85dc65
46
admin.go
46
admin.go
@ -9,8 +9,8 @@ import (
|
|||||||
"github.com/astaxie/beego/utils"
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BeeAdminApp is the default AdminApp used by admin module.
|
// BeeAdminApp is the default adminApp used by admin module.
|
||||||
var BeeAdminApp *AdminApp
|
var beeAdminApp *adminApp
|
||||||
|
|
||||||
// FilterMonitorFunc is default monitor filter when admin module is enable.
|
// FilterMonitorFunc is default monitor filter when admin module is enable.
|
||||||
// if this func returns, admin module records qbs for this request by condition of this function logic.
|
// if this func returns, admin module records qbs for this request by condition of this function logic.
|
||||||
@ -31,22 +31,22 @@ var BeeAdminApp *AdminApp
|
|||||||
var FilterMonitorFunc func(string, string, time.Duration) bool
|
var FilterMonitorFunc func(string, string, time.Duration) bool
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
BeeAdminApp = &AdminApp{
|
beeAdminApp = &adminApp{
|
||||||
routers: make(map[string]http.HandlerFunc),
|
routers: make(map[string]http.HandlerFunc),
|
||||||
}
|
}
|
||||||
BeeAdminApp.Route("/", AdminIndex)
|
beeAdminApp.Route("/", adminIndex)
|
||||||
BeeAdminApp.Route("/qps", QpsIndex)
|
beeAdminApp.Route("/qps", qpsIndex)
|
||||||
BeeAdminApp.Route("/prof", ProfIndex)
|
beeAdminApp.Route("/prof", profIndex)
|
||||||
BeeAdminApp.Route("/healthcheck", Healthcheck)
|
beeAdminApp.Route("/healthcheck", healthcheck)
|
||||||
BeeAdminApp.Route("/task", TaskStatus)
|
beeAdminApp.Route("/task", taskStatus)
|
||||||
BeeAdminApp.Route("/runtask", RunTask)
|
beeAdminApp.Route("/runtask", runTask)
|
||||||
BeeAdminApp.Route("/listconf", ListConf)
|
beeAdminApp.Route("/listconf", listConf)
|
||||||
FilterMonitorFunc = func(string, string, time.Duration) bool { return true }
|
FilterMonitorFunc = func(string, string, time.Duration) bool { return true }
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdminIndex is the default http.Handler for admin module.
|
// AdminIndex is the default http.Handler for admin module.
|
||||||
// it matches url pattern "/".
|
// it matches url pattern "/".
|
||||||
func AdminIndex(rw http.ResponseWriter, r *http.Request) {
|
func adminIndex(rw http.ResponseWriter, r *http.Request) {
|
||||||
rw.Write([]byte("Welcome to Admin Dashboard\n"))
|
rw.Write([]byte("Welcome to Admin Dashboard\n"))
|
||||||
rw.Write([]byte("There are servral functions:\n"))
|
rw.Write([]byte("There are servral functions:\n"))
|
||||||
rw.Write([]byte("1. Record all request and request time, http://localhost:8088/qps\n"))
|
rw.Write([]byte("1. Record all request and request time, http://localhost:8088/qps\n"))
|
||||||
@ -60,13 +60,13 @@ func AdminIndex(rw http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// QpsIndex is the http.Handler for writing qbs statistics map result info in http.ResponseWriter.
|
// QpsIndex is the http.Handler for writing qbs statistics map result info in http.ResponseWriter.
|
||||||
// it's registered with url pattern "/qbs" in admin module.
|
// it's registered with url pattern "/qbs" in admin module.
|
||||||
func QpsIndex(rw http.ResponseWriter, r *http.Request) {
|
func qpsIndex(rw http.ResponseWriter, r *http.Request) {
|
||||||
toolbox.StatisticsMap.GetMap(rw)
|
toolbox.StatisticsMap.GetMap(rw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListConf is the http.Handler of displaying all beego configuration values as key/value pair.
|
// ListConf is the http.Handler of displaying all beego configuration values as key/value pair.
|
||||||
// it's registered with url pattern "/listconf" in admin module.
|
// it's registered with url pattern "/listconf" in admin module.
|
||||||
func ListConf(rw http.ResponseWriter, r *http.Request) {
|
func listConf(rw http.ResponseWriter, r *http.Request) {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
command := r.Form.Get("command")
|
command := r.Form.Get("command")
|
||||||
if command != "" {
|
if command != "" {
|
||||||
@ -183,7 +183,7 @@ func ListConf(rw http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// ProfIndex is a http.Handler for showing profile command.
|
// ProfIndex is a http.Handler for showing profile command.
|
||||||
// it's in url pattern "/prof" in admin module.
|
// it's in url pattern "/prof" in admin module.
|
||||||
func ProfIndex(rw http.ResponseWriter, r *http.Request) {
|
func profIndex(rw http.ResponseWriter, r *http.Request) {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
command := r.Form.Get("command")
|
command := r.Form.Get("command")
|
||||||
if command != "" {
|
if command != "" {
|
||||||
@ -204,7 +204,7 @@ func ProfIndex(rw http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Healthcheck is a http.Handler calling health checking and showing the result.
|
// Healthcheck is a http.Handler calling health checking and showing the result.
|
||||||
// it's in "/healthcheck" pattern in admin module.
|
// it's in "/healthcheck" pattern in admin module.
|
||||||
func Healthcheck(rw http.ResponseWriter, req *http.Request) {
|
func healthcheck(rw http.ResponseWriter, req *http.Request) {
|
||||||
for name, h := range toolbox.AdminCheckList {
|
for name, h := range toolbox.AdminCheckList {
|
||||||
if err := h.Check(); err != nil {
|
if err := h.Check(); err != nil {
|
||||||
fmt.Fprintf(rw, "%s : ok\n", name)
|
fmt.Fprintf(rw, "%s : ok\n", name)
|
||||||
@ -216,7 +216,7 @@ func Healthcheck(rw http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
// TaskStatus is a http.Handler with running task status (task name, status and the last execution).
|
// TaskStatus is a http.Handler with running task status (task name, status and the last execution).
|
||||||
// it's in "/task" pattern in admin module.
|
// it's in "/task" pattern in admin module.
|
||||||
func TaskStatus(rw http.ResponseWriter, req *http.Request) {
|
func taskStatus(rw http.ResponseWriter, req *http.Request) {
|
||||||
for tname, tk := range toolbox.AdminTaskList {
|
for tname, tk := range toolbox.AdminTaskList {
|
||||||
fmt.Fprintf(rw, "%s:%s:%s", tname, tk.GetStatus(), tk.GetPrev().String())
|
fmt.Fprintf(rw, "%s:%s:%s", tname, tk.GetStatus(), tk.GetPrev().String())
|
||||||
}
|
}
|
||||||
@ -224,7 +224,7 @@ func TaskStatus(rw http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
// RunTask is a http.Handler to run a Task from the "query string.
|
// RunTask is a http.Handler to run a Task from the "query string.
|
||||||
// the request url likes /runtask?taskname=sendmail.
|
// the request url likes /runtask?taskname=sendmail.
|
||||||
func RunTask(rw http.ResponseWriter, req *http.Request) {
|
func runTask(rw http.ResponseWriter, req *http.Request) {
|
||||||
req.ParseForm()
|
req.ParseForm()
|
||||||
taskname := req.Form.Get("taskname")
|
taskname := req.Form.Get("taskname")
|
||||||
if t, ok := toolbox.AdminTaskList[taskname]; ok {
|
if t, ok := toolbox.AdminTaskList[taskname]; ok {
|
||||||
@ -238,19 +238,19 @@ func RunTask(rw http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdminApp is an http.HandlerFunc map used as BeeAdminApp.
|
// adminApp is an http.HandlerFunc map used as beeAdminApp.
|
||||||
type AdminApp struct {
|
type adminApp struct {
|
||||||
routers map[string]http.HandlerFunc
|
routers map[string]http.HandlerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Route adds http.HandlerFunc to AdminApp with url pattern.
|
// Route adds http.HandlerFunc to adminApp with url pattern.
|
||||||
func (admin *AdminApp) Route(pattern string, f http.HandlerFunc) {
|
func (admin *adminApp) Route(pattern string, f http.HandlerFunc) {
|
||||||
admin.routers[pattern] = f
|
admin.routers[pattern] = f
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run AdminApp http server.
|
// Run adminApp http server.
|
||||||
// Its addr is defined in configuration file as adminhttpaddr and adminhttpport.
|
// Its addr is defined in configuration file as adminhttpaddr and adminhttpport.
|
||||||
func (admin *AdminApp) Run() {
|
func (admin *adminApp) Run() {
|
||||||
if len(toolbox.AdminTaskList) > 0 {
|
if len(toolbox.AdminTaskList) > 0 {
|
||||||
toolbox.StartTask()
|
toolbox.StartTask()
|
||||||
}
|
}
|
||||||
|
6
beego.go
6
beego.go
@ -1,3 +1,4 @@
|
|||||||
|
// beego is an open-source, high-performance web framework for the Go programming language
|
||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -13,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// beego web framework version.
|
// beego web framework version.
|
||||||
const VERSION = "1.1.3"
|
const VERSION = "1.1.4"
|
||||||
|
|
||||||
type hookfunc func() error //hook function to run
|
type hookfunc func() error //hook function to run
|
||||||
var hooks []hookfunc //hook function slice to store the hookfunc
|
var hooks []hookfunc //hook function slice to store the hookfunc
|
||||||
@ -137,6 +138,7 @@ func SetStaticPath(url string, path string) *App {
|
|||||||
if !strings.HasPrefix(url, "/") {
|
if !strings.HasPrefix(url, "/") {
|
||||||
url = "/" + url
|
url = "/" + url
|
||||||
}
|
}
|
||||||
|
url = strings.TrimRight(url, "/")
|
||||||
StaticDir[url] = path
|
StaticDir[url] = path
|
||||||
return BeeApp
|
return BeeApp
|
||||||
}
|
}
|
||||||
@ -178,7 +180,7 @@ func Run() {
|
|||||||
initBeforeHttpRun()
|
initBeforeHttpRun()
|
||||||
|
|
||||||
if EnableAdmin {
|
if EnableAdmin {
|
||||||
go BeeAdminApp.Run()
|
go beeAdminApp.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
BeeApp.Run()
|
BeeApp.Run()
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/beego/memcache"
|
"github.com/beego/memcache"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Memcache adapter.
|
// Memcache adapter.
|
||||||
@ -147,5 +149,5 @@ func (rc *MemcacheCache) connectInit() (*memcache.Connection, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Register("memcache", NewMemCache())
|
cache.Register("memcache", NewMemCache())
|
||||||
}
|
}
|
4
cache/redis.go → cache/redis/redis.go
vendored
4
cache/redis.go → cache/redis/redis.go
vendored
@ -6,6 +6,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/beego/redigo/redis"
|
"github.com/beego/redigo/redis"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -130,5 +132,5 @@ func (rc *RedisCache) connectInit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Register("redis", NewRedisCache())
|
cache.Register("redis", NewRedisCache())
|
||||||
}
|
}
|
@ -306,9 +306,9 @@ func ParseConfig() (err error) {
|
|||||||
sds := strings.Fields(sd)
|
sds := strings.Fields(sd)
|
||||||
for _, v := range sds {
|
for _, v := range sds {
|
||||||
if url2fsmap := strings.SplitN(v, ":", 2); len(url2fsmap) == 2 {
|
if url2fsmap := strings.SplitN(v, ":", 2); len(url2fsmap) == 2 {
|
||||||
StaticDir["/"+url2fsmap[0]] = url2fsmap[1]
|
StaticDir["/"+strings.TrimRight(url2fsmap[0], "/")] = url2fsmap[1]
|
||||||
} else {
|
} else {
|
||||||
StaticDir["/"+url2fsmap[0]] = url2fsmap[0]
|
StaticDir["/"+strings.TrimRight(url2fsmap[0], "/")] = url2fsmap[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package context
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -92,6 +93,41 @@ func (input *BeegoInput) Is(method string) bool {
|
|||||||
return input.Method() == method
|
return input.Method() == method
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is this a GET method request?
|
||||||
|
func (input *BeegoInput) IsGet() bool {
|
||||||
|
return input.Is("GET")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this a POST method request?
|
||||||
|
func (input *BeegoInput) IsPost() bool {
|
||||||
|
return input.Is("POST")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this a Head method request?
|
||||||
|
func (input *BeegoInput) IsHead() bool {
|
||||||
|
return input.Is("HEAD")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this a OPTIONS method request?
|
||||||
|
func (input *BeegoInput) IsOptions() bool {
|
||||||
|
return input.Is("OPTIONS")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this a PUT method request?
|
||||||
|
func (input *BeegoInput) IsPut() bool {
|
||||||
|
return input.Is("PUT")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this a DELETE method request?
|
||||||
|
func (input *BeegoInput) IsDelete() bool {
|
||||||
|
return input.Is("DELETE")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this a PATCH method request?
|
||||||
|
func (input *BeegoInput) IsPatch() bool {
|
||||||
|
return input.Is("PATCH")
|
||||||
|
}
|
||||||
|
|
||||||
// IsAjax returns boolean of this request is generated by ajax.
|
// IsAjax returns boolean of this request is generated by ajax.
|
||||||
func (input *BeegoInput) IsAjax() bool {
|
func (input *BeegoInput) IsAjax() bool {
|
||||||
return input.Header("X-Requested-With") == "XMLHttpRequest"
|
return input.Header("X-Requested-With") == "XMLHttpRequest"
|
||||||
@ -109,7 +145,7 @@ func (input *BeegoInput) IsWebsocket() bool {
|
|||||||
|
|
||||||
// IsSecure returns boolean of whether file uploads in this request or not..
|
// IsSecure returns boolean of whether file uploads in this request or not..
|
||||||
func (input *BeegoInput) IsUpload() bool {
|
func (input *BeegoInput) IsUpload() bool {
|
||||||
return input.Request.MultipartForm != nil
|
return input.Header("Content-Type") == "multipart/form-data"
|
||||||
}
|
}
|
||||||
|
|
||||||
// IP returns request client ip.
|
// IP returns request client ip.
|
||||||
@ -175,7 +211,9 @@ func (input *BeegoInput) Param(key string) string {
|
|||||||
|
|
||||||
// Query returns input data item string by a given string.
|
// Query returns input data item string by a given string.
|
||||||
func (input *BeegoInput) Query(key string) string {
|
func (input *BeegoInput) Query(key string) string {
|
||||||
input.Request.ParseForm()
|
if input.Request.Form == nil {
|
||||||
|
input.Request.ParseForm()
|
||||||
|
}
|
||||||
return input.Request.Form.Get(key)
|
return input.Request.Form.Get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +238,7 @@ func (input *BeegoInput) Session(key interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Body returns the raw request body data as bytes.
|
// Body returns the raw request body data as bytes.
|
||||||
func (input *BeegoInput) Body() []byte {
|
func (input *BeegoInput) CopyBody() []byte {
|
||||||
requestbody, _ := ioutil.ReadAll(input.Request.Body)
|
requestbody, _ := ioutil.ReadAll(input.Request.Body)
|
||||||
input.Request.Body.Close()
|
input.Request.Body.Close()
|
||||||
bf := bytes.NewBuffer(requestbody)
|
bf := bytes.NewBuffer(requestbody)
|
||||||
@ -222,3 +260,21 @@ func (input *BeegoInput) GetData(key interface{}) interface{} {
|
|||||||
func (input *BeegoInput) SetData(key, val interface{}) {
|
func (input *BeegoInput) SetData(key, val interface{}) {
|
||||||
input.Data[key] = val
|
input.Data[key] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (input *BeegoInput) ParseFormOrMulitForm(maxMemory int64) error {
|
||||||
|
// Parse the body depending on the content type.
|
||||||
|
switch input.Header("Content-Type") {
|
||||||
|
case "application/x-www-form-urlencoded":
|
||||||
|
// Typical form.
|
||||||
|
if err := input.Request.ParseForm(); err != nil {
|
||||||
|
return errors.New("Error parsing request body:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
case "multipart/form-data":
|
||||||
|
if err := input.Request.ParseMultipartForm(maxMemory); err != nil {
|
||||||
|
return errors.New("Error parsing request body:" + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -14,12 +14,12 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var gmfim map[string]*MemFileInfo = make(map[string]*MemFileInfo)
|
var gmfim map[string]*memFileInfo = make(map[string]*memFileInfo)
|
||||||
var lock sync.RWMutex
|
var lock sync.RWMutex
|
||||||
|
|
||||||
// OpenMemZipFile returns MemFile object with a compressed static file.
|
// OpenMemZipFile returns MemFile object with a compressed static file.
|
||||||
// it's used for serve static file if gzip enable.
|
// it's used for serve static file if gzip enable.
|
||||||
func OpenMemZipFile(path string, zip string) (*MemFile, error) {
|
func openMemZipFile(path string, zip string) (*memFile, error) {
|
||||||
osfile, e := os.Open(path)
|
osfile, e := os.Open(path)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
@ -36,12 +36,9 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
|
|||||||
lock.RLock()
|
lock.RLock()
|
||||||
cfi, ok := gmfim[zip+":"+path]
|
cfi, ok := gmfim[zip+":"+path]
|
||||||
lock.RUnlock()
|
lock.RUnlock()
|
||||||
if ok && cfi.ModTime() == modtime && cfi.fileSize == fileSize {
|
if !(ok && cfi.ModTime() == modtime && cfi.fileSize == fileSize) {
|
||||||
|
|
||||||
} else {
|
|
||||||
var content []byte
|
var content []byte
|
||||||
if zip == "gzip" {
|
if zip == "gzip" {
|
||||||
//将文件内容压缩到zipbuf中
|
|
||||||
var zipbuf bytes.Buffer
|
var zipbuf bytes.Buffer
|
||||||
gzipwriter, e := gzip.NewWriterLevel(&zipbuf, gzip.BestCompression)
|
gzipwriter, e := gzip.NewWriterLevel(&zipbuf, gzip.BestCompression)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
@ -52,13 +49,11 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
|
|||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
//读zipbuf到content
|
|
||||||
content, e = ioutil.ReadAll(&zipbuf)
|
content, e = ioutil.ReadAll(&zipbuf)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
} else if zip == "deflate" {
|
} else if zip == "deflate" {
|
||||||
//将文件内容压缩到zipbuf中
|
|
||||||
var zipbuf bytes.Buffer
|
var zipbuf bytes.Buffer
|
||||||
deflatewriter, e := flate.NewWriter(&zipbuf, flate.BestCompression)
|
deflatewriter, e := flate.NewWriter(&zipbuf, flate.BestCompression)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
@ -69,7 +64,6 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
|
|||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
//将zipbuf读入到content
|
|
||||||
content, e = ioutil.ReadAll(&zipbuf)
|
content, e = ioutil.ReadAll(&zipbuf)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
@ -81,17 +75,17 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfi = &MemFileInfo{osfileinfo, modtime, content, int64(len(content)), fileSize}
|
cfi = &memFileInfo{osfileinfo, modtime, content, int64(len(content)), fileSize}
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
defer lock.Unlock()
|
defer lock.Unlock()
|
||||||
gmfim[zip+":"+path] = cfi
|
gmfim[zip+":"+path] = cfi
|
||||||
}
|
}
|
||||||
return &MemFile{fi: cfi, offset: 0}, nil
|
return &memFile{fi: cfi, offset: 0}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MemFileInfo contains a compressed file bytes and file information.
|
// MemFileInfo contains a compressed file bytes and file information.
|
||||||
// it implements os.FileInfo interface.
|
// it implements os.FileInfo interface.
|
||||||
type MemFileInfo struct {
|
type memFileInfo struct {
|
||||||
os.FileInfo
|
os.FileInfo
|
||||||
modTime time.Time
|
modTime time.Time
|
||||||
content []byte
|
content []byte
|
||||||
@ -100,62 +94,62 @@ type MemFileInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the compressed filename.
|
// Name returns the compressed filename.
|
||||||
func (fi *MemFileInfo) Name() string {
|
func (fi *memFileInfo) Name() string {
|
||||||
return fi.Name()
|
return fi.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the raw file content size, not compressed size.
|
// Size returns the raw file content size, not compressed size.
|
||||||
func (fi *MemFileInfo) Size() int64 {
|
func (fi *memFileInfo) Size() int64 {
|
||||||
return fi.contentSize
|
return fi.contentSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mode returns file mode.
|
// Mode returns file mode.
|
||||||
func (fi *MemFileInfo) Mode() os.FileMode {
|
func (fi *memFileInfo) Mode() os.FileMode {
|
||||||
return fi.Mode()
|
return fi.Mode()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModTime returns the last modified time of raw file.
|
// ModTime returns the last modified time of raw file.
|
||||||
func (fi *MemFileInfo) ModTime() time.Time {
|
func (fi *memFileInfo) ModTime() time.Time {
|
||||||
return fi.modTime
|
return fi.modTime
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDir returns the compressing file is a directory or not.
|
// IsDir returns the compressing file is a directory or not.
|
||||||
func (fi *MemFileInfo) IsDir() bool {
|
func (fi *memFileInfo) IsDir() bool {
|
||||||
return fi.IsDir()
|
return fi.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
// return nil. implement the os.FileInfo interface method.
|
// return nil. implement the os.FileInfo interface method.
|
||||||
func (fi *MemFileInfo) Sys() interface{} {
|
func (fi *memFileInfo) Sys() interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MemFile contains MemFileInfo and bytes offset when reading.
|
// MemFile contains MemFileInfo and bytes offset when reading.
|
||||||
// it implements io.Reader,io.ReadCloser and io.Seeker.
|
// it implements io.Reader,io.ReadCloser and io.Seeker.
|
||||||
type MemFile struct {
|
type memFile struct {
|
||||||
fi *MemFileInfo
|
fi *memFileInfo
|
||||||
offset int64
|
offset int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close memfile.
|
// Close memfile.
|
||||||
func (f *MemFile) Close() error {
|
func (f *memFile) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get os.FileInfo of memfile.
|
// Get os.FileInfo of memfile.
|
||||||
func (f *MemFile) Stat() (os.FileInfo, error) {
|
func (f *memFile) Stat() (os.FileInfo, error) {
|
||||||
return f.fi, nil
|
return f.fi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// read os.FileInfo of files in directory of memfile.
|
// read os.FileInfo of files in directory of memfile.
|
||||||
// it returns empty slice.
|
// it returns empty slice.
|
||||||
func (f *MemFile) Readdir(count int) ([]os.FileInfo, error) {
|
func (f *memFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||||
infos := []os.FileInfo{}
|
infos := []os.FileInfo{}
|
||||||
|
|
||||||
return infos, nil
|
return infos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read bytes from the compressed file bytes.
|
// Read bytes from the compressed file bytes.
|
||||||
func (f *MemFile) Read(p []byte) (n int, err error) {
|
func (f *memFile) Read(p []byte) (n int, err error) {
|
||||||
if len(f.fi.content)-int(f.offset) >= len(p) {
|
if len(f.fi.content)-int(f.offset) >= len(p) {
|
||||||
n = len(p)
|
n = len(p)
|
||||||
} else {
|
} else {
|
||||||
@ -171,7 +165,7 @@ var errWhence = errors.New("Seek: invalid whence")
|
|||||||
var errOffset = errors.New("Seek: invalid offset")
|
var errOffset = errors.New("Seek: invalid offset")
|
||||||
|
|
||||||
// Read bytes from the compressed file bytes by seeker.
|
// Read bytes from the compressed file bytes by seeker.
|
||||||
func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) {
|
func (f *memFile) Seek(offset int64, whence int) (ret int64, err error) {
|
||||||
switch whence {
|
switch whence {
|
||||||
default:
|
default:
|
||||||
return 0, errWhence
|
return 0, errWhence
|
||||||
@ -191,7 +185,7 @@ func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) {
|
|||||||
// GetAcceptEncodingZip returns accept encoding format in http header.
|
// GetAcceptEncodingZip returns accept encoding format in http header.
|
||||||
// zip is first, then deflate if both accepted.
|
// zip is first, then deflate if both accepted.
|
||||||
// If no accepted, return empty string.
|
// If no accepted, return empty string.
|
||||||
func GetAcceptEncodingZip(r *http.Request) string {
|
func getAcceptEncodingZip(r *http.Request) string {
|
||||||
ss := r.Header.Get("Accept-Encoding")
|
ss := r.Header.Get("Accept-Encoding")
|
||||||
ss = strings.ToLower(ss)
|
ss = strings.ToLower(ss)
|
||||||
if strings.Contains(ss, "gzip") {
|
if strings.Contains(ss, "gzip") {
|
||||||
@ -203,22 +197,3 @@ func GetAcceptEncodingZip(r *http.Request) string {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloseZWriter closes the io.Writer after compressing static file.
|
|
||||||
func CloseZWriter(zwriter io.Writer) {
|
|
||||||
if zwriter == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch zwriter.(type) {
|
|
||||||
case *gzip.Writer:
|
|
||||||
zwriter.(*gzip.Writer).Close()
|
|
||||||
case *flate.Writer:
|
|
||||||
zwriter.(*flate.Writer).Close()
|
|
||||||
//其他情况不close, 保持和默认(非压缩)行为一致
|
|
||||||
/*
|
|
||||||
case io.WriteCloser:
|
|
||||||
zwriter.(io.WriteCloser).Close()
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// Zero-downtime restarts in Go.
|
|
||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
112
router.go
112
router.go
@ -7,8 +7,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -33,7 +31,7 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// supported http methods.
|
// supported http methods.
|
||||||
HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head"}
|
HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head", "trace", "connect"}
|
||||||
// these beego.Controller's methods shouldn't reflect to AutoRouter
|
// these beego.Controller's methods shouldn't reflect to AutoRouter
|
||||||
exceptMethod = []string{"Init", "Prepare", "Finish", "Render", "RenderString",
|
exceptMethod = []string{"Init", "Prepare", "Finish", "Render", "RenderString",
|
||||||
"RenderBytes", "Redirect", "Abort", "StopRun", "UrlFor", "ServeJson", "ServeJsonp",
|
"RenderBytes", "Redirect", "Abort", "StopRun", "UrlFor", "ServeJson", "ServeJsonp",
|
||||||
@ -544,88 +542,26 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
http.Error(w, "Method Not Allowed", 405)
|
http.Error(w, "Method Not Allowed", 405)
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
//static file server
|
||||||
|
if serverStaticRouter(context) {
|
||||||
|
goto Admin
|
||||||
|
}
|
||||||
|
|
||||||
|
if context.Input.IsPost() {
|
||||||
|
if CopyRequestBody && !context.Input.IsUpload() {
|
||||||
|
context.Input.CopyBody()
|
||||||
|
}
|
||||||
|
context.Input.ParseFormOrMulitForm(MaxMemory)
|
||||||
|
}
|
||||||
|
|
||||||
if do_filter(BeforeRouter) {
|
if do_filter(BeforeRouter) {
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
//static file server
|
|
||||||
for prefix, staticDir := range StaticDir {
|
|
||||||
if len(prefix) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if r.URL.Path == "/favicon.ico" {
|
|
||||||
file := path.Join(staticDir, r.URL.Path)
|
|
||||||
if utils.FileExists(file) {
|
|
||||||
http.ServeFile(w, r, file)
|
|
||||||
w.started = true
|
|
||||||
goto Admin
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(r.URL.Path, prefix) {
|
|
||||||
if len(r.URL.Path) > len(prefix) && r.URL.Path[len(prefix)] != '/' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if r.URL.Path == prefix && prefix[len(prefix)-1] != '/' {
|
|
||||||
http.Redirect(rw, r, r.URL.Path+"/", 302)
|
|
||||||
goto Admin
|
|
||||||
}
|
|
||||||
file := path.Join(staticDir, r.URL.Path[len(prefix):])
|
|
||||||
finfo, err := os.Stat(file)
|
|
||||||
if err != nil {
|
|
||||||
if RunMode == "dev" {
|
|
||||||
Warn(err)
|
|
||||||
}
|
|
||||||
http.NotFound(w, r)
|
|
||||||
goto Admin
|
|
||||||
}
|
|
||||||
//if the request is dir and DirectoryIndex is false then
|
|
||||||
if finfo.IsDir() && !DirectoryIndex {
|
|
||||||
middleware.Exception("403", rw, r, "403 Forbidden")
|
|
||||||
goto Admin
|
|
||||||
}
|
|
||||||
|
|
||||||
//This block obtained from (https://github.com/smithfox/beego) - it should probably get merged into astaxie/beego after a pull request
|
|
||||||
isStaticFileToCompress := false
|
|
||||||
if StaticExtensionsToGzip != nil && len(StaticExtensionsToGzip) > 0 {
|
|
||||||
for _, statExtension := range StaticExtensionsToGzip {
|
|
||||||
if strings.HasSuffix(strings.ToLower(file), strings.ToLower(statExtension)) {
|
|
||||||
isStaticFileToCompress = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isStaticFileToCompress {
|
|
||||||
if EnableGzip {
|
|
||||||
w.contentEncoding = GetAcceptEncodingZip(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
memzipfile, err := OpenMemZipFile(file, w.contentEncoding)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.InitHeadContent(finfo.Size())
|
|
||||||
|
|
||||||
http.ServeContent(w, r, file, finfo.ModTime(), memzipfile)
|
|
||||||
} else {
|
|
||||||
http.ServeFile(w, r, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.started = true
|
|
||||||
goto Admin
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if do_filter(AfterStatic) {
|
if do_filter(AfterStatic) {
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
if CopyRequestBody {
|
|
||||||
context.Input.Body()
|
|
||||||
}
|
|
||||||
|
|
||||||
if context.Input.RunController != nil && context.Input.RunMethod != "" {
|
if context.Input.RunController != nil && context.Input.RunMethod != "" {
|
||||||
findrouter = true
|
findrouter = true
|
||||||
runMethod = context.Input.RunMethod
|
runMethod = context.Input.RunMethod
|
||||||
@ -757,9 +693,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if findrouter {
|
if findrouter {
|
||||||
if r.Method == "POST" {
|
|
||||||
r.ParseMultipartForm(MaxMemory)
|
|
||||||
}
|
|
||||||
//execute middleware filters
|
//execute middleware filters
|
||||||
if do_filter(BeforeExec) {
|
if do_filter(BeforeExec) {
|
||||||
goto Admin
|
goto Admin
|
||||||
@ -830,9 +763,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Admin:
|
|
||||||
do_filter(FinishRouter)
|
do_filter(FinishRouter)
|
||||||
|
Admin:
|
||||||
//admin module record QPS
|
//admin module record QPS
|
||||||
if EnableAdmin {
|
if EnableAdmin {
|
||||||
timeend := time.Since(starttime)
|
timeend := time.Since(starttime)
|
||||||
@ -891,10 +823,9 @@ func (p *ControllerRegistor) getRunMethod(method string, context *beecontext.Con
|
|||||||
//responseWriter is a wrapper for the http.ResponseWriter
|
//responseWriter is a wrapper for the http.ResponseWriter
|
||||||
//started set to true if response was written to then don't execute other handler
|
//started set to true if response was written to then don't execute other handler
|
||||||
type responseWriter struct {
|
type responseWriter struct {
|
||||||
writer http.ResponseWriter
|
writer http.ResponseWriter
|
||||||
started bool
|
started bool
|
||||||
status int
|
status int
|
||||||
contentEncoding string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header returns the header map that will be sent by WriteHeader.
|
// Header returns the header map that will be sent by WriteHeader.
|
||||||
@ -902,17 +833,6 @@ func (w *responseWriter) Header() http.Header {
|
|||||||
return w.writer.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")
|
|
||||||
} else if w.contentEncoding == "deflate" {
|
|
||||||
w.Header().Set("Content-Encoding", "deflate")
|
|
||||||
} else {
|
|
||||||
w.Header().Set("Content-Length", strconv.FormatInt(contentlength, 10))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write writes the data to the connection as part of an HTTP reply,
|
// Write writes the data to the connection as part of an HTTP reply,
|
||||||
// and sets `started` to true.
|
// and sets `started` to true.
|
||||||
// started means the response has sent out.
|
// started means the response has sent out.
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package session
|
package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/couchbaselabs/go-couchbase"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/couchbaselabs/go-couchbase"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
var couchbpder = &CouchbaseProvider{}
|
var couchbpder = &CouchbaseProvider{}
|
||||||
@ -70,7 +73,7 @@ func (cs *CouchbaseSessionStore) SessionRelease(w http.ResponseWriter) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bo, err := encodeGob(cs.values)
|
bo, err := session.EncodeGob(cs.values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -117,7 +120,7 @@ func (cp *CouchbaseProvider) SessionInit(maxlifetime int64, savePath string) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read couchbase session by sid
|
// read couchbase session by sid
|
||||||
func (cp *CouchbaseProvider) SessionRead(sid string) (SessionStore, error) {
|
func (cp *CouchbaseProvider) SessionRead(sid string) (session.SessionStore, error) {
|
||||||
cp.b = cp.getBucket()
|
cp.b = cp.getBucket()
|
||||||
|
|
||||||
var doc []byte
|
var doc []byte
|
||||||
@ -127,7 +130,7 @@ func (cp *CouchbaseProvider) SessionRead(sid string) (SessionStore, error) {
|
|||||||
if doc == nil {
|
if doc == nil {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = decodeGob(doc)
|
kv, err = session.DecodeGob(doc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -150,7 +153,7 @@ func (cp *CouchbaseProvider) SessionExist(sid string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *CouchbaseProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
|
func (cp *CouchbaseProvider) SessionRegenerate(oldsid, sid string) (session.SessionStore, error) {
|
||||||
cp.b = cp.getBucket()
|
cp.b = cp.getBucket()
|
||||||
|
|
||||||
var doc []byte
|
var doc []byte
|
||||||
@ -172,7 +175,7 @@ func (cp *CouchbaseProvider) SessionRegenerate(oldsid, sid string) (SessionStore
|
|||||||
if doc == nil {
|
if doc == nil {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = decodeGob(doc)
|
kv, err = session.DecodeGob(doc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -199,5 +202,5 @@ func (cp *CouchbaseProvider) SessionAll() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Register("couchbase", couchbpder)
|
session.Register("couchbase", couchbpder)
|
||||||
}
|
}
|
@ -14,6 +14,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/session"
|
||||||
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,7 +75,7 @@ func (st *MysqlSessionStore) SessionID() string {
|
|||||||
// must call this method to save values to database.
|
// must call this method to save values to database.
|
||||||
func (st *MysqlSessionStore) SessionRelease(w http.ResponseWriter) {
|
func (st *MysqlSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||||
defer st.c.Close()
|
defer st.c.Close()
|
||||||
b, err := encodeGob(st.values)
|
b, err := session.EncodeGob(st.values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -106,7 +108,7 @@ func (mp *MysqlProvider) SessionInit(maxlifetime int64, savePath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get mysql session by sid
|
// get mysql session by sid
|
||||||
func (mp *MysqlProvider) SessionRead(sid string) (SessionStore, error) {
|
func (mp *MysqlProvider) SessionRead(sid string) (session.SessionStore, error) {
|
||||||
c := mp.connectInit()
|
c := mp.connectInit()
|
||||||
row := c.QueryRow("select session_data from session where session_key=?", sid)
|
row := c.QueryRow("select session_data from session where session_key=?", sid)
|
||||||
var sessiondata []byte
|
var sessiondata []byte
|
||||||
@ -119,7 +121,7 @@ func (mp *MysqlProvider) SessionRead(sid string) (SessionStore, error) {
|
|||||||
if len(sessiondata) == 0 {
|
if len(sessiondata) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = decodeGob(sessiondata)
|
kv, err = session.DecodeGob(sessiondata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -143,7 +145,7 @@ func (mp *MysqlProvider) SessionExist(sid string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate new sid for mysql session
|
// generate new sid for mysql session
|
||||||
func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
|
func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (session.SessionStore, error) {
|
||||||
c := mp.connectInit()
|
c := mp.connectInit()
|
||||||
row := c.QueryRow("select session_data from session where session_key=?", oldsid)
|
row := c.QueryRow("select session_data from session where session_key=?", oldsid)
|
||||||
var sessiondata []byte
|
var sessiondata []byte
|
||||||
@ -156,7 +158,7 @@ func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er
|
|||||||
if len(sessiondata) == 0 {
|
if len(sessiondata) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = decodeGob(sessiondata)
|
kv, err = session.DecodeGob(sessiondata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -194,5 +196,5 @@ func (mp *MysqlProvider) SessionAll() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Register("mysql", mysqlpder)
|
session.Register("mysql", mysqlpder)
|
||||||
}
|
}
|
@ -34,6 +34,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/session"
|
||||||
|
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -93,7 +96,7 @@ func (st *PostgresqlSessionStore) SessionID() string {
|
|||||||
// must call this method to save values to database.
|
// must call this method to save values to database.
|
||||||
func (st *PostgresqlSessionStore) SessionRelease(w http.ResponseWriter) {
|
func (st *PostgresqlSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||||
defer st.c.Close()
|
defer st.c.Close()
|
||||||
b, err := encodeGob(st.values)
|
b, err := session.EncodeGob(st.values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -126,7 +129,7 @@ func (mp *PostgresqlProvider) SessionInit(maxlifetime int64, savePath string) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get postgresql session by sid
|
// get postgresql session by sid
|
||||||
func (mp *PostgresqlProvider) SessionRead(sid string) (SessionStore, error) {
|
func (mp *PostgresqlProvider) SessionRead(sid string) (session.SessionStore, error) {
|
||||||
c := mp.connectInit()
|
c := mp.connectInit()
|
||||||
row := c.QueryRow("select session_data from session where session_key=$1", sid)
|
row := c.QueryRow("select session_data from session where session_key=$1", sid)
|
||||||
var sessiondata []byte
|
var sessiondata []byte
|
||||||
@ -138,7 +141,7 @@ func (mp *PostgresqlProvider) SessionRead(sid string) (SessionStore, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +149,7 @@ func (mp *PostgresqlProvider) SessionRead(sid string) (SessionStore, error) {
|
|||||||
if len(sessiondata) == 0 {
|
if len(sessiondata) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = decodeGob(sessiondata)
|
kv, err = session.DecodeGob(sessiondata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -162,7 +165,7 @@ func (mp *PostgresqlProvider) SessionExist(sid string) bool {
|
|||||||
row := c.QueryRow("select session_data from session where session_key=$1", sid)
|
row := c.QueryRow("select session_data from session where session_key=$1", sid)
|
||||||
var sessiondata []byte
|
var sessiondata []byte
|
||||||
err := row.Scan(&sessiondata)
|
err := row.Scan(&sessiondata)
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
@ -171,21 +174,21 @@ func (mp *PostgresqlProvider) SessionExist(sid string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate new sid for postgresql session
|
// generate new sid for postgresql session
|
||||||
func (mp *PostgresqlProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
|
func (mp *PostgresqlProvider) SessionRegenerate(oldsid, sid string) (session.SessionStore, error) {
|
||||||
c := mp.connectInit()
|
c := mp.connectInit()
|
||||||
row := c.QueryRow("select session_data from session where session_key=$1", oldsid)
|
row := c.QueryRow("select session_data from session where session_key=$1", oldsid)
|
||||||
var sessiondata []byte
|
var sessiondata []byte
|
||||||
err := row.Scan(&sessiondata)
|
err := row.Scan(&sessiondata)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
c.Exec("insert into session(session_key,session_data,session_expiry) values($1,$2,$3)",
|
c.Exec("insert into session(session_key,session_data,session_expiry) values($1,$2,$3)",
|
||||||
oldsid, "", time.Now().Format(time.RFC3339))
|
oldsid, "", time.Now().Format(time.RFC3339))
|
||||||
}
|
}
|
||||||
c.Exec("update session set session_key=$1 where session_key=$2", sid, oldsid)
|
c.Exec("update session set session_key=$1 where session_key=$2", sid, oldsid)
|
||||||
var kv map[interface{}]interface{}
|
var kv map[interface{}]interface{}
|
||||||
if len(sessiondata) == 0 {
|
if len(sessiondata) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = decodeGob(sessiondata)
|
kv, err = session.DecodeGob(sessiondata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -223,5 +226,5 @@ func (mp *PostgresqlProvider) SessionAll() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Register("postgresql", postgresqlpder)
|
session.Register("postgresql", postgresqlpder)
|
||||||
}
|
}
|
@ -6,6 +6,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/session"
|
||||||
|
|
||||||
"github.com/beego/redigo/redis"
|
"github.com/beego/redigo/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -77,7 +79,7 @@ func (rs *RedisSessionStore) SessionRelease(w http.ResponseWriter) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := encodeGob(rs.values)
|
b, err := session.EncodeGob(rs.values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -134,7 +136,7 @@ func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read redis session by sid
|
// read redis session by sid
|
||||||
func (rp *RedisProvider) SessionRead(sid string) (SessionStore, error) {
|
func (rp *RedisProvider) SessionRead(sid string) (session.SessionStore, error) {
|
||||||
c := rp.poollist.Get()
|
c := rp.poollist.Get()
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
@ -143,7 +145,7 @@ func (rp *RedisProvider) SessionRead(sid string) (SessionStore, error) {
|
|||||||
if len(kvs) == 0 {
|
if len(kvs) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = decodeGob([]byte(kvs))
|
kv, err = session.DecodeGob([]byte(kvs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -166,7 +168,7 @@ func (rp *RedisProvider) SessionExist(sid string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate new sid for redis session
|
// generate new sid for redis session
|
||||||
func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
|
func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (session.SessionStore, error) {
|
||||||
c := rp.poollist.Get()
|
c := rp.poollist.Get()
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
@ -185,7 +187,7 @@ func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er
|
|||||||
if len(kvs) == 0 {
|
if len(kvs) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = decodeGob([]byte(kvs))
|
kv, err = session.DecodeGob([]byte(kvs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -215,5 +217,5 @@ func (rp *RedisProvider) SessionAll() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Register("redis", redispder)
|
session.Register("redis", redispder)
|
||||||
}
|
}
|
@ -70,7 +70,7 @@ func (fs *FileSessionStore) SessionID() string {
|
|||||||
// Write file session to local file with Gob string
|
// Write file session to local file with Gob string
|
||||||
func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) {
|
func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) {
|
||||||
defer fs.f.Close()
|
defer fs.f.Close()
|
||||||
b, err := encodeGob(fs.values)
|
b, err := EncodeGob(fs.values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) {
|
|||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = decodeGob(b)
|
kv, err = DecodeGob(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -222,7 +222,7 @@ func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, err
|
|||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
} else {
|
} else {
|
||||||
kv, err = decodeGob(b)
|
kv, err = DecodeGob(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,11 @@ func Test_gob(t *testing.T) {
|
|||||||
a := make(map[interface{}]interface{})
|
a := make(map[interface{}]interface{})
|
||||||
a["username"] = "astaxie"
|
a["username"] = "astaxie"
|
||||||
a[12] = 234
|
a[12] = 234
|
||||||
b, err := encodeGob(a)
|
b, err := EncodeGob(a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
c, err := decodeGob(b)
|
c, err := DecodeGob(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ func init() {
|
|||||||
gob.Register(map[int]int64{})
|
gob.Register(map[int]int64{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeGob(obj map[interface{}]interface{}) ([]byte, error) {
|
func EncodeGob(obj map[interface{}]interface{}) ([]byte, error) {
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
enc := gob.NewEncoder(buf)
|
enc := gob.NewEncoder(buf)
|
||||||
err := enc.Encode(obj)
|
err := enc.Encode(obj)
|
||||||
@ -37,7 +37,7 @@ func encodeGob(obj map[interface{}]interface{}) ([]byte, error) {
|
|||||||
return buf.Bytes(), nil
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeGob(encoded []byte) (map[interface{}]interface{}, error) {
|
func DecodeGob(encoded []byte) (map[interface{}]interface{}, error) {
|
||||||
buf := bytes.NewBuffer(encoded)
|
buf := bytes.NewBuffer(encoded)
|
||||||
dec := gob.NewDecoder(buf)
|
dec := gob.NewDecoder(buf)
|
||||||
var out map[interface{}]interface{}
|
var out map[interface{}]interface{}
|
||||||
@ -97,8 +97,8 @@ func decrypt(block cipher.Block, value []byte) ([]byte, error) {
|
|||||||
func encodeCookie(block cipher.Block, hashKey, name string, value map[interface{}]interface{}) (string, error) {
|
func encodeCookie(block cipher.Block, hashKey, name string, value map[interface{}]interface{}) (string, error) {
|
||||||
var err error
|
var err error
|
||||||
var b []byte
|
var b []byte
|
||||||
// 1. encodeGob.
|
// 1. EncodeGob.
|
||||||
if b, err = encodeGob(value); err != nil {
|
if b, err = EncodeGob(value); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
// 2. Encrypt (optional).
|
// 2. Encrypt (optional).
|
||||||
@ -158,8 +158,8 @@ func decodeCookie(block cipher.Block, hashKey, name, value string, gcmaxlifetime
|
|||||||
if b, err = decrypt(block, b); err != nil {
|
if b, err = decrypt(block, b); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// 5. decodeGob.
|
// 5. DecodeGob.
|
||||||
if dst, err := decodeGob(b); err != nil {
|
if dst, err := DecodeGob(b); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
return dst, nil
|
return dst, nil
|
||||||
|
90
staticfile.go
Normal file
90
staticfile.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package beego
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/context"
|
||||||
|
"github.com/astaxie/beego/middleware"
|
||||||
|
"github.com/astaxie/beego/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func serverStaticRouter(ctx *context.Context) bool {
|
||||||
|
requestPath := path.Clean(ctx.Input.Request.URL.Path)
|
||||||
|
for prefix, staticDir := range StaticDir {
|
||||||
|
if len(prefix) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if requestPath == "/favicon.ico" {
|
||||||
|
file := path.Join(staticDir, requestPath)
|
||||||
|
if utils.FileExists(file) {
|
||||||
|
http.ServeFile(ctx.ResponseWriter, ctx.Request, file)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(requestPath, prefix) {
|
||||||
|
if len(requestPath) > len(prefix) && requestPath[len(prefix)] != '/' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if requestPath == prefix && prefix[len(prefix)-1] != '/' {
|
||||||
|
http.Redirect(ctx.ResponseWriter, ctx.Request, requestPath+"/", 302)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
file := path.Join(staticDir, requestPath[len(prefix):])
|
||||||
|
finfo, err := os.Stat(file)
|
||||||
|
if err != nil {
|
||||||
|
if RunMode == "dev" {
|
||||||
|
Warn(err)
|
||||||
|
}
|
||||||
|
http.NotFound(ctx.ResponseWriter, ctx.Request)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
//if the request is dir and DirectoryIndex is false then
|
||||||
|
if finfo.IsDir() && !DirectoryIndex {
|
||||||
|
middleware.Exception("403", ctx.ResponseWriter, ctx.Request, "403 Forbidden")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//This block obtained from (https://github.com/smithfox/beego) - it should probably get merged into astaxie/beego after a pull request
|
||||||
|
isStaticFileToCompress := false
|
||||||
|
if StaticExtensionsToGzip != nil && len(StaticExtensionsToGzip) > 0 {
|
||||||
|
for _, statExtension := range StaticExtensionsToGzip {
|
||||||
|
if strings.HasSuffix(strings.ToLower(file), strings.ToLower(statExtension)) {
|
||||||
|
isStaticFileToCompress = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isStaticFileToCompress {
|
||||||
|
var contentEncoding string
|
||||||
|
if EnableGzip {
|
||||||
|
contentEncoding = getAcceptEncodingZip(ctx.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
memzipfile, err := openMemZipFile(file, contentEncoding)
|
||||||
|
if err != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if contentEncoding == "gzip" {
|
||||||
|
ctx.Output.Header("Content-Encoding", "gzip")
|
||||||
|
} else if contentEncoding == "deflate" {
|
||||||
|
ctx.Output.Header("Content-Encoding", "deflate")
|
||||||
|
} else {
|
||||||
|
ctx.Output.Header("Content-Length", strconv.FormatInt(finfo.Size(), 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
http.ServeContent(ctx.ResponseWriter, ctx.Request, file, finfo.ModTime(), memzipfile)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
http.ServeFile(ctx.ResponseWriter, ctx.Request, file)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// most reference from github.com/realint/dbgutil
|
// Here are the features: healthcheck, profile, statistics and task.
|
||||||
package toolbox
|
package toolbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -34,7 +34,6 @@ func Display(data ...interface{}) {
|
|||||||
display(true, data...)
|
display(true, data...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// return data print string
|
// return data print string
|
||||||
func GetDisplayString(data ...interface{}) string {
|
func GetDisplayString(data ...interface{}) string {
|
||||||
return display(false, data...)
|
return display(false, data...)
|
||||||
|
Loading…
Reference in New Issue
Block a user