Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
张磊
/
FileStorageBeego
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
82ca85dc
authored
2014-04-08 17:49:12 +0800
by
astaxie
Browse Files
Options
Browse Files
Tag
Download
Plain Diff
release new version 1.1.4
2 parents
8cbea70e
f9cc9e9e
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
258 additions
and
203 deletions
admin.go
beego.go
cache/memcache.go → cache/memcache/memcache.go
cache/redis.go → cache/redis/redis.go
config.go
config/xml.go → config/xml/xml.go
config/xml_test.go → config/xml/xml_test.go
config/yaml.go → config/yaml/yaml.go
config/yaml_test.go → config/yaml/yaml_test.go
context/input.go
memzipfile.go
reload.go
router.go
session/sess_couchbase.go → session/couchbase/sess_couchbase.go
session/sess_mysql.go → session/mysql/sess_mysql.go
session/sess_postgresql.go → session/postgres/sess_postgresql.go
session/sess_redis.go → session/redis/sess_redis.go
session/sess_file.go
session/sess_test.go
session/sess_utils.go
staticfile.go
toolbox/debug.go
admin.go
View file @
82ca85d
...
...
@@ -9,8 +9,8 @@ import (
"github.com/astaxie/beego/utils"
)
// BeeAdminApp is the default
A
dminApp used by admin module.
var
BeeAdminApp
*
A
dminApp
// BeeAdminApp is the default
a
dminApp used by admin module.
var
beeAdminApp
*
a
dminApp
// 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.
...
...
@@ -31,22 +31,22 @@ var BeeAdminApp *AdminApp
var
FilterMonitorFunc
func
(
string
,
string
,
time
.
Duration
)
bool
func
init
()
{
BeeAdminApp
=
&
A
dminApp
{
beeAdminApp
=
&
a
dminApp
{
routers
:
make
(
map
[
string
]
http
.
HandlerFunc
),
}
BeeAdminApp
.
Route
(
"/"
,
A
dminIndex
)
BeeAdminApp
.
Route
(
"/qps"
,
Q
psIndex
)
BeeAdminApp
.
Route
(
"/prof"
,
P
rofIndex
)
BeeAdminApp
.
Route
(
"/healthcheck"
,
H
ealthcheck
)
BeeAdminApp
.
Route
(
"/task"
,
T
askStatus
)
BeeAdminApp
.
Route
(
"/runtask"
,
R
unTask
)
BeeAdminApp
.
Route
(
"/listconf"
,
L
istConf
)
beeAdminApp
.
Route
(
"/"
,
a
dminIndex
)
beeAdminApp
.
Route
(
"/qps"
,
q
psIndex
)
beeAdminApp
.
Route
(
"/prof"
,
p
rofIndex
)
beeAdminApp
.
Route
(
"/healthcheck"
,
h
ealthcheck
)
beeAdminApp
.
Route
(
"/task"
,
t
askStatus
)
beeAdminApp
.
Route
(
"/runtask"
,
r
unTask
)
beeAdminApp
.
Route
(
"/listconf"
,
l
istConf
)
FilterMonitorFunc
=
func
(
string
,
string
,
time
.
Duration
)
bool
{
return
true
}
}
// AdminIndex is the default http.Handler for admin module.
// it matches url pattern "/".
func
A
dminIndex
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
a
dminIndex
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
rw
.
Write
([]
byte
(
"Welcome to Admin Dashboard
\n
"
))
rw
.
Write
([]
byte
(
"There are servral functions:
\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.
// it's registered with url pattern "/qbs" in admin module.
func
Q
psIndex
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
q
psIndex
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
toolbox
.
StatisticsMap
.
GetMap
(
rw
)
}
// 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.
func
L
istConf
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
l
istConf
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
r
.
ParseForm
()
command
:=
r
.
Form
.
Get
(
"command"
)
if
command
!=
""
{
...
...
@@ -183,7 +183,7 @@ func ListConf(rw http.ResponseWriter, r *http.Request) {
// ProfIndex is a http.Handler for showing profile command.
// it's in url pattern "/prof" in admin module.
func
P
rofIndex
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
p
rofIndex
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
r
.
ParseForm
()
command
:=
r
.
Form
.
Get
(
"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.
// it's in "/healthcheck" pattern in admin module.
func
H
ealthcheck
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
func
h
ealthcheck
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
for
name
,
h
:=
range
toolbox
.
AdminCheckList
{
if
err
:=
h
.
Check
();
err
!=
nil
{
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).
// it's in "/task" pattern in admin module.
func
T
askStatus
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
func
t
askStatus
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
for
tname
,
tk
:=
range
toolbox
.
AdminTaskList
{
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.
// the request url likes /runtask?taskname=sendmail.
func
R
unTask
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
func
r
unTask
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
req
.
ParseForm
()
taskname
:=
req
.
Form
.
Get
(
"taskname"
)
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 B
eeAdminApp.
type
A
dminApp
struct
{
//
adminApp is an http.HandlerFunc map used as b
eeAdminApp.
type
a
dminApp
struct
{
routers
map
[
string
]
http
.
HandlerFunc
}
// Route adds http.HandlerFunc to
A
dminApp with url pattern.
func
(
admin
*
A
dminApp
)
Route
(
pattern
string
,
f
http
.
HandlerFunc
)
{
// Route adds http.HandlerFunc to
a
dminApp with url pattern.
func
(
admin
*
a
dminApp
)
Route
(
pattern
string
,
f
http
.
HandlerFunc
)
{
admin
.
routers
[
pattern
]
=
f
}
// Run
A
dminApp http server.
// Run
a
dminApp http server.
// Its addr is defined in configuration file as adminhttpaddr and adminhttpport.
func
(
admin
*
A
dminApp
)
Run
()
{
func
(
admin
*
a
dminApp
)
Run
()
{
if
len
(
toolbox
.
AdminTaskList
)
>
0
{
toolbox
.
StartTask
()
}
...
...
beego.go
View file @
82ca85d
// beego is an open-source, high-performance web framework for the Go programming language
package
beego
import
(
...
...
@@ -13,7 +14,7 @@ import (
)
// beego web framework version.
const
VERSION
=
"1.1.
3
"
const
VERSION
=
"1.1.
4
"
type
hookfunc
func
()
error
//hook function to run
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
,
"/"
)
{
url
=
"/"
+
url
}
url
=
strings
.
TrimRight
(
url
,
"/"
)
StaticDir
[
url
]
=
path
return
BeeApp
}
...
...
@@ -178,7 +180,7 @@ func Run() {
initBeforeHttpRun
()
if
EnableAdmin
{
go
B
eeAdminApp
.
Run
()
go
b
eeAdminApp
.
Run
()
}
BeeApp
.
Run
()
...
...
cache/memcache.go
→
cache/memcache
/memcache
.go
View file @
82ca85d
...
...
@@ -5,6 +5,8 @@ import (
"errors"
"github.com/beego/memcache"
"github.com/astaxie/beego/cache"
)
// Memcache adapter.
...
...
@@ -147,5 +149,5 @@ func (rc *MemcacheCache) connectInit() (*memcache.Connection, error) {
}
func
init
()
{
Register
(
"memcache"
,
NewMemCache
())
cache
.
Register
(
"memcache"
,
NewMemCache
())
}
...
...
cache/redis.go
→
cache/redis
/redis
.go
View file @
82ca85d
...
...
@@ -6,6 +6,8 @@ import (
"time"
"github.com/beego/redigo/redis"
"github.com/astaxie/beego/cache"
)
var
(
...
...
@@ -130,5 +132,5 @@ func (rc *RedisCache) connectInit() {
}
func
init
()
{
Register
(
"redis"
,
NewRedisCache
())
cache
.
Register
(
"redis"
,
NewRedisCache
())
}
...
...
config.go
View file @
82ca85d
...
...
@@ -306,9 +306,9 @@ func ParseConfig() (err error) {
sds
:=
strings
.
Fields
(
sd
)
for
_
,
v
:=
range
sds
{
if
url2fsmap
:=
strings
.
SplitN
(
v
,
":"
,
2
);
len
(
url2fsmap
)
==
2
{
StaticDir
[
"/"
+
url2fsmap
[
0
]
]
=
url2fsmap
[
1
]
StaticDir
[
"/"
+
strings
.
TrimRight
(
url2fsmap
[
0
],
"/"
)
]
=
url2fsmap
[
1
]
}
else
{
StaticDir
[
"/"
+
url2fsmap
[
0
]
]
=
url2fsmap
[
0
]
StaticDir
[
"/"
+
strings
.
TrimRight
(
url2fsmap
[
0
],
"/"
)
]
=
url2fsmap
[
0
]
}
}
}
...
...
config/xml.go
→
config/xml
/xml
.go
View file @
82ca85d
File moved
config/xml_test.go
→
config/xml
/xml
_test.go
View file @
82ca85d
File moved
config/yaml.go
→
config/yaml
/yaml
.go
View file @
82ca85d
File moved
config/yaml_test.go
→
config/yaml
/yaml
_test.go
View file @
82ca85d
File moved
context/input.go
View file @
82ca85d
...
...
@@ -2,6 +2,7 @@ package context
import
(
"bytes"
"errors"
"io/ioutil"
"net/http"
"reflect"
...
...
@@ -92,6 +93,41 @@ func (input *BeegoInput) Is(method string) bool {
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.
func
(
input
*
BeegoInput
)
IsAjax
()
bool
{
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..
func
(
input
*
BeegoInput
)
IsUpload
()
bool
{
return
input
.
Request
.
MultipartForm
!=
nil
return
input
.
Header
(
"Content-Type"
)
==
"multipart/form-data"
}
// 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.
func
(
input
*
BeegoInput
)
Query
(
key
string
)
string
{
if
input
.
Request
.
Form
==
nil
{
input
.
Request
.
ParseForm
()
}
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.
func
(
input
*
BeegoInput
)
Body
()
[]
byte
{
func
(
input
*
BeegoInput
)
Copy
Body
()
[]
byte
{
requestbody
,
_
:=
ioutil
.
ReadAll
(
input
.
Request
.
Body
)
input
.
Request
.
Body
.
Close
()
bf
:=
bytes
.
NewBuffer
(
requestbody
)
...
...
@@ -222,3 +260,21 @@ func (input *BeegoInput) GetData(key interface{}) interface{} {
func
(
input
*
BeegoInput
)
SetData
(
key
,
val
interface
{})
{
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
}
...
...
memzipfile.go
View file @
82ca85d
...
...
@@ -14,12 +14,12 @@ import (
"time"
)
var
gmfim
map
[
string
]
*
MemFileInfo
=
make
(
map
[
string
]
*
M
emFileInfo
)
var
gmfim
map
[
string
]
*
memFileInfo
=
make
(
map
[
string
]
*
m
emFileInfo
)
var
lock
sync
.
RWMutex
// OpenMemZipFile returns MemFile object with a compressed static file.
// it's used for serve static file if gzip enable.
func
OpenMemZipFile
(
path
string
,
zip
string
)
(
*
M
emFile
,
error
)
{
func
openMemZipFile
(
path
string
,
zip
string
)
(
*
m
emFile
,
error
)
{
osfile
,
e
:=
os
.
Open
(
path
)
if
e
!=
nil
{
return
nil
,
e
...
...
@@ -36,12 +36,9 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
lock
.
RLock
()
cfi
,
ok
:=
gmfim
[
zip
+
":"
+
path
]
lock
.
RUnlock
()
if
ok
&&
cfi
.
ModTime
()
==
modtime
&&
cfi
.
fileSize
==
fileSize
{
}
else
{
if
!
(
ok
&&
cfi
.
ModTime
()
==
modtime
&&
cfi
.
fileSize
==
fileSize
)
{
var
content
[]
byte
if
zip
==
"gzip"
{
//将文件内容压缩到zipbuf中
var
zipbuf
bytes
.
Buffer
gzipwriter
,
e
:=
gzip
.
NewWriterLevel
(
&
zipbuf
,
gzip
.
BestCompression
)
if
e
!=
nil
{
...
...
@@ -52,13 +49,11 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
if
e
!=
nil
{
return
nil
,
e
}
//读zipbuf到content
content
,
e
=
ioutil
.
ReadAll
(
&
zipbuf
)
if
e
!=
nil
{
return
nil
,
e
}
}
else
if
zip
==
"deflate"
{
//将文件内容压缩到zipbuf中
var
zipbuf
bytes
.
Buffer
deflatewriter
,
e
:=
flate
.
NewWriter
(
&
zipbuf
,
flate
.
BestCompression
)
if
e
!=
nil
{
...
...
@@ -69,7 +64,6 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
if
e
!=
nil
{
return
nil
,
e
}
//将zipbuf读入到content
content
,
e
=
ioutil
.
ReadAll
(
&
zipbuf
)
if
e
!=
nil
{
return
nil
,
e
...
...
@@ -81,17 +75,17 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
}
}
cfi
=
&
M
emFileInfo
{
osfileinfo
,
modtime
,
content
,
int64
(
len
(
content
)),
fileSize
}
cfi
=
&
m
emFileInfo
{
osfileinfo
,
modtime
,
content
,
int64
(
len
(
content
)),
fileSize
}
lock
.
Lock
()
defer
lock
.
Unlock
()
gmfim
[
zip
+
":"
+
path
]
=
cfi
}
return
&
M
emFile
{
fi
:
cfi
,
offset
:
0
},
nil
return
&
m
emFile
{
fi
:
cfi
,
offset
:
0
},
nil
}
// MemFileInfo contains a compressed file bytes and file information.
// it implements os.FileInfo interface.
type
M
emFileInfo
struct
{
type
m
emFileInfo
struct
{
os
.
FileInfo
modTime
time
.
Time
content
[]
byte
...
...
@@ -100,62 +94,62 @@ type MemFileInfo struct {
}
// Name returns the compressed filename.
func
(
fi
*
M
emFileInfo
)
Name
()
string
{
func
(
fi
*
m
emFileInfo
)
Name
()
string
{
return
fi
.
Name
()
}
// Size returns the raw file content size, not compressed size.
func
(
fi
*
M
emFileInfo
)
Size
()
int64
{
func
(
fi
*
m
emFileInfo
)
Size
()
int64
{
return
fi
.
contentSize
}
// Mode returns file mode.
func
(
fi
*
M
emFileInfo
)
Mode
()
os
.
FileMode
{
func
(
fi
*
m
emFileInfo
)
Mode
()
os
.
FileMode
{
return
fi
.
Mode
()
}
// ModTime returns the last modified time of raw file.
func
(
fi
*
M
emFileInfo
)
ModTime
()
time
.
Time
{
func
(
fi
*
m
emFileInfo
)
ModTime
()
time
.
Time
{
return
fi
.
modTime
}
// IsDir returns the compressing file is a directory or not.
func
(
fi
*
M
emFileInfo
)
IsDir
()
bool
{
func
(
fi
*
m
emFileInfo
)
IsDir
()
bool
{
return
fi
.
IsDir
()
}
// return nil. implement the os.FileInfo interface method.
func
(
fi
*
M
emFileInfo
)
Sys
()
interface
{}
{
func
(
fi
*
m
emFileInfo
)
Sys
()
interface
{}
{
return
nil
}
// MemFile contains MemFileInfo and bytes offset when reading.
// it implements io.Reader,io.ReadCloser and io.Seeker.
type
M
emFile
struct
{
fi
*
M
emFileInfo
type
m
emFile
struct
{
fi
*
m
emFileInfo
offset
int64
}
// Close memfile.
func
(
f
*
M
emFile
)
Close
()
error
{
func
(
f
*
m
emFile
)
Close
()
error
{
return
nil
}
// Get os.FileInfo of memfile.
func
(
f
*
M
emFile
)
Stat
()
(
os
.
FileInfo
,
error
)
{
func
(
f
*
m
emFile
)
Stat
()
(
os
.
FileInfo
,
error
)
{
return
f
.
fi
,
nil
}
// read os.FileInfo of files in directory of memfile.
// it returns empty slice.
func
(
f
*
M
emFile
)
Readdir
(
count
int
)
([]
os
.
FileInfo
,
error
)
{
func
(
f
*
m
emFile
)
Readdir
(
count
int
)
([]
os
.
FileInfo
,
error
)
{
infos
:=
[]
os
.
FileInfo
{}
return
infos
,
nil
}
// Read bytes from the compressed file bytes.
func
(
f
*
M
emFile
)
Read
(
p
[]
byte
)
(
n
int
,
err
error
)
{
func
(
f
*
m
emFile
)
Read
(
p
[]
byte
)
(
n
int
,
err
error
)
{
if
len
(
f
.
fi
.
content
)
-
int
(
f
.
offset
)
>=
len
(
p
)
{
n
=
len
(
p
)
}
else
{
...
...
@@ -171,7 +165,7 @@ var errWhence = errors.New("Seek: invalid whence")
var
errOffset
=
errors
.
New
(
"Seek: invalid offset"
)
// Read bytes from the compressed file bytes by seeker.
func
(
f
*
M
emFile
)
Seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
error
)
{
func
(
f
*
m
emFile
)
Seek
(
offset
int64
,
whence
int
)
(
ret
int64
,
err
error
)
{
switch
whence
{
default
:
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.
// zip is first, then deflate if both accepted.
// If no accepted, return empty string.
func
G
etAcceptEncodingZip
(
r
*
http
.
Request
)
string
{
func
g
etAcceptEncodingZip
(
r
*
http
.
Request
)
string
{
ss
:=
r
.
Header
.
Get
(
"Accept-Encoding"
)
ss
=
strings
.
ToLower
(
ss
)
if
strings
.
Contains
(
ss
,
"gzip"
)
{
...
...
@@ -203,22 +197,3 @@ func GetAcceptEncodingZip(r *http.Request) string {
}
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()
*/
}
}
...
...
reload.go
View file @
82ca85d
// Zero-downtime restarts in Go.
package
beego
import
(
...
...
router.go
View file @
82ca85d
...
...
@@ -7,8 +7,6 @@ import (
"net"
"net/http"
"net/url"
"os"
"path"
"reflect"
"regexp"
"runtime"
...
...
@@ -33,7 +31,7 @@ const (
var
(
// 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
exceptMethod
=
[]
string
{
"Init"
,
"Prepare"
,
"Finish"
,
"Render"
,
"RenderString"
,
"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
)
goto
Admin
}
if
do_filter
(
BeforeRouter
)
{
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"
)
if
serverStaticRouter
(
context
)
{
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
context
.
Input
.
IsPost
()
{
if
CopyRequestBody
&&
!
context
.
Input
.
IsUpload
()
{
context
.
Input
.
CopyBody
()
}
context
.
Input
.
ParseFormOrMulitForm
(
MaxMemory
)
}
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
if
do_filter
(
BeforeRouter
)
{
goto
Admin
}
}
if
do_filter
(
AfterStatic
)
{
goto
Admin
}
if
CopyRequestBody
{
context
.
Input
.
Body
()
}
if
context
.
Input
.
RunController
!=
nil
&&
context
.
Input
.
RunMethod
!=
""
{
findrouter
=
true
runMethod
=
context
.
Input
.
RunMethod
...
...
@@ -757,9 +693,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
}
if
findrouter
{
if
r
.
Method
==
"POST"
{
r
.
ParseMultipartForm
(
MaxMemory
)
}
//execute middleware filters
if
do_filter
(
BeforeExec
)
{
goto
Admin
...
...
@@ -830,9 +763,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
}
}
Admin
:
do_filter
(
FinishRouter
)
Admin
:
//admin module record QPS
if
EnableAdmin
{
timeend
:=
time
.
Since
(
starttime
)
...
...
@@ -894,7 +826,6 @@ type responseWriter struct {
writer
http
.
ResponseWriter
started
bool
status
int
contentEncoding
string
}
// 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
()
}
// 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,
// and sets `started` to true.
// started means the response has sent out.
...
...
session/sess_couchbase.go
→
session/
couchbase/
sess_couchbase.go
View file @
82ca85d
package
session
import
(
"github.com/couchbaselabs/go-couchbase"
"net/http"
"strings"
"sync"
"github.com/couchbaselabs/go-couchbase"
"github.com/astaxie/beego/session"
)
var
couchbpder
=
&
CouchbaseProvider
{}
...
...
@@ -70,7 +73,7 @@ func (cs *CouchbaseSessionStore) SessionRelease(w http.ResponseWriter) {
return
}
bo
,
err
:=
e
ncodeGob
(
cs
.
values
)
bo
,
err
:=
session
.
E
ncodeGob
(
cs
.
values
)
if
err
!=
nil
{
return
}
...
...
@@ -117,7 +120,7 @@ func (cp *CouchbaseProvider) SessionInit(maxlifetime int64, savePath string) err
}
// 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
()
var
doc
[]
byte
...
...
@@ -127,7 +130,7 @@ func (cp *CouchbaseProvider) SessionRead(sid string) (SessionStore, error) {
if
doc
==
nil
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
d
ecodeGob
(
doc
)
kv
,
err
=
session
.
D
ecodeGob
(
doc
)
if
err
!=
nil
{
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
()
var
doc
[]
byte
...
...
@@ -172,7 +175,7 @@ func (cp *CouchbaseProvider) SessionRegenerate(oldsid, sid string) (SessionStore
if
doc
==
nil
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
d
ecodeGob
(
doc
)
kv
,
err
=
session
.
D
ecodeGob
(
doc
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -199,5 +202,5 @@ func (cp *CouchbaseProvider) SessionAll() int {
}
func
init
()
{
Register
(
"couchbase"
,
couchbpder
)
session
.
Register
(
"couchbase"
,
couchbpder
)
}
...
...
session/sess_mysql.go
→
session/
mysql/
sess_mysql.go
View file @
82ca85d
...
...
@@ -14,6 +14,8 @@ import (
"sync"
"time"
"github.com/astaxie/beego/session"
_
"github.com/go-sql-driver/mysql"
)
...
...
@@ -73,7 +75,7 @@ func (st *MysqlSessionStore) SessionID() string {
// must call this method to save values to database.
func
(
st
*
MysqlSessionStore
)
SessionRelease
(
w
http
.
ResponseWriter
)
{
defer
st
.
c
.
Close
()
b
,
err
:=
e
ncodeGob
(
st
.
values
)
b
,
err
:=
session
.
E
ncodeGob
(
st
.
values
)
if
err
!=
nil
{
return
}
...
...
@@ -106,7 +108,7 @@ func (mp *MysqlProvider) SessionInit(maxlifetime int64, savePath string) error {
}
// 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
()
row
:=
c
.
QueryRow
(
"select session_data from session where session_key=?"
,
sid
)
var
sessiondata
[]
byte
...
...
@@ -119,7 +121,7 @@ func (mp *MysqlProvider) SessionRead(sid string) (SessionStore, error) {
if
len
(
sessiondata
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
d
ecodeGob
(
sessiondata
)
kv
,
err
=
session
.
D
ecodeGob
(
sessiondata
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -143,7 +145,7 @@ func (mp *MysqlProvider) SessionExist(sid string) bool {
}
// 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
()
row
:=
c
.
QueryRow
(
"select session_data from session where session_key=?"
,
oldsid
)
var
sessiondata
[]
byte
...
...
@@ -156,7 +158,7 @@ func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er
if
len
(
sessiondata
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
d
ecodeGob
(
sessiondata
)
kv
,
err
=
session
.
D
ecodeGob
(
sessiondata
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -194,5 +196,5 @@ func (mp *MysqlProvider) SessionAll() int {
}
func
init
()
{
Register
(
"mysql"
,
mysqlpder
)
session
.
Register
(
"mysql"
,
mysqlpder
)
}
...
...
session/sess_postgresql.go
→
session/
postgres/
sess_postgresql.go
View file @
82ca85d
...
...
@@ -34,6 +34,9 @@ import (
"net/http"
"sync"
"time"
"github.com/astaxie/beego/session"
_
"github.com/lib/pq"
)
...
...
@@ -93,7 +96,7 @@ func (st *PostgresqlSessionStore) SessionID() string {
// must call this method to save values to database.
func
(
st
*
PostgresqlSessionStore
)
SessionRelease
(
w
http
.
ResponseWriter
)
{
defer
st
.
c
.
Close
()
b
,
err
:=
e
ncodeGob
(
st
.
values
)
b
,
err
:=
session
.
E
ncodeGob
(
st
.
values
)
if
err
!=
nil
{
return
}
...
...
@@ -126,7 +129,7 @@ func (mp *PostgresqlProvider) SessionInit(maxlifetime int64, savePath string) er
}
// 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
()
row
:=
c
.
QueryRow
(
"select session_data from session where session_key=$1"
,
sid
)
var
sessiondata
[]
byte
...
...
@@ -146,7 +149,7 @@ func (mp *PostgresqlProvider) SessionRead(sid string) (SessionStore, error) {
if
len
(
sessiondata
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
d
ecodeGob
(
sessiondata
)
kv
,
err
=
session
.
D
ecodeGob
(
sessiondata
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -171,7 +174,7 @@ func (mp *PostgresqlProvider) SessionExist(sid string) bool {
}
// 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
()
row
:=
c
.
QueryRow
(
"select session_data from session where session_key=$1"
,
oldsid
)
var
sessiondata
[]
byte
...
...
@@ -185,7 +188,7 @@ func (mp *PostgresqlProvider) SessionRegenerate(oldsid, sid string) (SessionStor
if
len
(
sessiondata
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
d
ecodeGob
(
sessiondata
)
kv
,
err
=
session
.
D
ecodeGob
(
sessiondata
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -223,5 +226,5 @@ func (mp *PostgresqlProvider) SessionAll() int {
}
func
init
()
{
Register
(
"postgresql"
,
postgresqlpder
)
session
.
Register
(
"postgresql"
,
postgresqlpder
)
}
...
...
session/sess_redis.go
→
session/
redis/
sess_redis.go
View file @
82ca85d
...
...
@@ -6,6 +6,8 @@ import (
"strings"
"sync"
"github.com/astaxie/beego/session"
"github.com/beego/redigo/redis"
)
...
...
@@ -77,7 +79,7 @@ func (rs *RedisSessionStore) SessionRelease(w http.ResponseWriter) {
return
}
b
,
err
:=
e
ncodeGob
(
rs
.
values
)
b
,
err
:=
session
.
E
ncodeGob
(
rs
.
values
)
if
err
!=
nil
{
return
}
...
...
@@ -134,7 +136,7 @@ func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
}
// 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
()
defer
c
.
Close
()
...
...
@@ -143,7 +145,7 @@ func (rp *RedisProvider) SessionRead(sid string) (SessionStore, error) {
if
len
(
kvs
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
d
ecodeGob
([]
byte
(
kvs
))
kv
,
err
=
session
.
D
ecodeGob
([]
byte
(
kvs
))
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -166,7 +168,7 @@ func (rp *RedisProvider) SessionExist(sid string) bool {
}
// 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
()
defer
c
.
Close
()
...
...
@@ -185,7 +187,7 @@ func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er
if
len
(
kvs
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
d
ecodeGob
([]
byte
(
kvs
))
kv
,
err
=
session
.
D
ecodeGob
([]
byte
(
kvs
))
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -215,5 +217,5 @@ func (rp *RedisProvider) SessionAll() int {
}
func
init
()
{
Register
(
"redis"
,
redispder
)
session
.
Register
(
"redis"
,
redispder
)
}
...
...
session/sess_file.go
View file @
82ca85d
...
...
@@ -70,7 +70,7 @@ func (fs *FileSessionStore) SessionID() string {
// Write file session to local file with Gob string
func
(
fs
*
FileSessionStore
)
SessionRelease
(
w
http
.
ResponseWriter
)
{
defer
fs
.
f
.
Close
()
b
,
err
:=
e
ncodeGob
(
fs
.
values
)
b
,
err
:=
E
ncodeGob
(
fs
.
values
)
if
err
!=
nil
{
return
}
...
...
@@ -123,7 +123,7 @@ func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) {
if
len
(
b
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
d
ecodeGob
(
b
)
kv
,
err
=
D
ecodeGob
(
b
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -222,7 +222,7 @@ func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, err
if
len
(
b
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
d
ecodeGob
(
b
)
kv
,
err
=
D
ecodeGob
(
b
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
session/sess_test.go
View file @
82ca85d
...
...
@@ -10,11 +10,11 @@ func Test_gob(t *testing.T) {
a
:=
make
(
map
[
interface
{}]
interface
{})
a
[
"username"
]
=
"astaxie"
a
[
12
]
=
234
b
,
err
:=
e
ncodeGob
(
a
)
b
,
err
:=
E
ncodeGob
(
a
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
c
,
err
:=
d
ecodeGob
(
b
)
c
,
err
:=
D
ecodeGob
(
b
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
...
...
session/sess_utils.go
View file @
82ca85d
...
...
@@ -27,7 +27,7 @@ func init() {
gob
.
Register
(
map
[
int
]
int64
{})
}
func
e
ncodeGob
(
obj
map
[
interface
{}]
interface
{})
([]
byte
,
error
)
{
func
E
ncodeGob
(
obj
map
[
interface
{}]
interface
{})
([]
byte
,
error
)
{
buf
:=
bytes
.
NewBuffer
(
nil
)
enc
:=
gob
.
NewEncoder
(
buf
)
err
:=
enc
.
Encode
(
obj
)
...
...
@@ -37,7 +37,7 @@ func encodeGob(obj map[interface{}]interface{}) ([]byte, error) {
return
buf
.
Bytes
(),
nil
}
func
d
ecodeGob
(
encoded
[]
byte
)
(
map
[
interface
{}]
interface
{},
error
)
{
func
D
ecodeGob
(
encoded
[]
byte
)
(
map
[
interface
{}]
interface
{},
error
)
{
buf
:=
bytes
.
NewBuffer
(
encoded
)
dec
:=
gob
.
NewDecoder
(
buf
)
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
)
{
var
err
error
var
b
[]
byte
// 1.
e
ncodeGob.
if
b
,
err
=
e
ncodeGob
(
value
);
err
!=
nil
{
// 1.
E
ncodeGob.
if
b
,
err
=
E
ncodeGob
(
value
);
err
!=
nil
{
return
""
,
err
}
// 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
{
return
nil
,
err
}
// 5.
d
ecodeGob.
if
dst
,
err
:=
d
ecodeGob
(
b
);
err
!=
nil
{
// 5.
D
ecodeGob.
if
dst
,
err
:=
D
ecodeGob
(
b
);
err
!=
nil
{
return
nil
,
err
}
else
{
return
dst
,
nil
...
...
staticfile.go
0 → 100644
View file @
82ca85d
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
}
toolbox/debug.go
View file @
82ca85d
//
most reference from github.com/realint/dbgutil
//
Here are the features: healthcheck, profile, statistics and task.
package
toolbox
import
(
...
...
@@ -34,7 +34,6 @@ func Display(data ...interface{}) {
display
(
true
,
data
...
)
}
// return data print string
func
GetDisplayString
(
data
...
interface
{})
string
{
return
display
(
false
,
data
...
)
...
...
Write
Preview
Styling with
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment