Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
f70f3380
Commit
f70f3380
authored
Dec 10, 2015
by
astaxie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
use sync.Pool to reuse Context
parent
f2edfbe7
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
80 additions
and
71 deletions
+80
-71
context.go
context/context.go
+16
-0
input.go
context/input.go
+37
-32
output.go
context/output.go
+7
-1
docs.go
docs.go
+1
-7
router.go
router.go
+18
-30
staticfile.go
staticfile.go
+1
-1
No files found.
context/context.go
View file @
f70f3380
...
...
@@ -35,6 +35,14 @@ import (
"github.com/astaxie/beego/utils"
)
// NewContext return the Context with Input and Output
func
NewContext
()
*
Context
{
return
&
Context
{
Input
:
NewInput
(),
Output
:
NewOutput
(),
}
}
// Context Http request context struct including BeegoInput, BeegoOutput, http.Request and http.ResponseWriter.
// BeegoInput and BeegoOutput provides some api to operate request and response more easily.
type
Context
struct
{
...
...
@@ -45,6 +53,14 @@ type Context struct {
_xsrfToken
string
}
// Reset init Context, BeegoInput and BeegoOutput
func
(
ctx
*
Context
)
Reset
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
ctx
.
Request
=
r
ctx
.
ResponseWriter
=
rw
ctx
.
Input
.
Reset
(
ctx
)
ctx
.
Output
.
Reset
(
ctx
)
}
// Redirect does redirection to localurl with http header status code.
// It sends http response header directly.
func
(
ctx
*
Context
)
Redirect
(
status
int
,
localurl
string
)
{
...
...
context/input.go
View file @
f70f3380
...
...
@@ -18,7 +18,6 @@ import (
"bytes"
"errors"
"io/ioutil"
"net/http"
"net/url"
"reflect"
"regexp"
...
...
@@ -39,37 +38,43 @@ var (
// BeegoInput operates the http request header, data, cookie and body.
// it also contains router params and current session.
type
BeegoInput
struct
{
Context
*
Context
CruSession
session
.
Store
Params
map
[
string
]
string
Data
map
[
interface
{}]
interface
{}
// store some values in this context when calling context in filter or controller.
Request
*
http
.
Request
RequestBody
[]
byte
RunController
reflect
.
Type
RunMethod
string
}
// NewInput return BeegoInput generated by
http.Reques
t.
func
NewInput
(
req
*
http
.
Request
)
*
BeegoInput
{
// NewInput return BeegoInput generated by
Contex
t.
func
NewInput
()
*
BeegoInput
{
return
&
BeegoInput
{
Params
:
make
(
map
[
string
]
string
),
Data
:
make
(
map
[
interface
{}]
interface
{}),
Request
:
req
,
}
}
// Reset init the BeegoInput
func
(
input
*
BeegoInput
)
Reset
(
ctx
*
Context
)
{
input
.
Context
=
ctx
input
.
CruSession
=
nil
input
.
Params
=
make
(
map
[
string
]
string
)
input
.
Data
=
make
(
map
[
interface
{}]
interface
{})
input
.
RequestBody
=
[]
byte
{}
}
// Protocol returns request protocol name, such as HTTP/1.1 .
func
(
input
*
BeegoInput
)
Protocol
()
string
{
return
input
.
Request
.
Proto
return
input
.
Context
.
Request
.
Proto
}
// URI returns full request url with query string, fragment.
func
(
input
*
BeegoInput
)
URI
()
string
{
return
input
.
Request
.
RequestURI
return
input
.
Context
.
Request
.
RequestURI
}
// URL returns request url path (without query string, fragment).
func
(
input
*
BeegoInput
)
URL
()
string
{
return
input
.
Request
.
URL
.
Path
return
input
.
Context
.
Request
.
URL
.
Path
}
// Site returns base site url as scheme://domain type.
...
...
@@ -79,10 +84,10 @@ func (input *BeegoInput) Site() string {
// Scheme returns request scheme as "http" or "https".
func
(
input
*
BeegoInput
)
Scheme
()
string
{
if
input
.
Request
.
URL
.
Scheme
!=
""
{
return
input
.
Request
.
URL
.
Scheme
if
input
.
Context
.
Request
.
URL
.
Scheme
!=
""
{
return
input
.
Context
.
Request
.
URL
.
Scheme
}
if
input
.
Request
.
TLS
==
nil
{
if
input
.
Context
.
Request
.
TLS
==
nil
{
return
"http"
}
return
"https"
...
...
@@ -97,19 +102,19 @@ func (input *BeegoInput) Domain() string {
// Host returns host name.
// if no host info in request, return localhost.
func
(
input
*
BeegoInput
)
Host
()
string
{
if
input
.
Request
.
Host
!=
""
{
hostParts
:=
strings
.
Split
(
input
.
Request
.
Host
,
":"
)
if
input
.
Context
.
Request
.
Host
!=
""
{
hostParts
:=
strings
.
Split
(
input
.
Context
.
Request
.
Host
,
":"
)
if
len
(
hostParts
)
>
0
{
return
hostParts
[
0
]
}
return
input
.
Request
.
Host
return
input
.
Context
.
Request
.
Host
}
return
"localhost"
}
// Method returns http request method.
func
(
input
*
BeegoInput
)
Method
()
string
{
return
input
.
Request
.
Method
return
input
.
Context
.
Request
.
Method
}
// Is returns boolean of this request is on given method, such as Is("POST").
...
...
@@ -196,7 +201,7 @@ func (input *BeegoInput) IP() string {
rip
:=
strings
.
Split
(
ips
[
0
],
":"
)
return
rip
[
0
]
}
ip
:=
strings
.
Split
(
input
.
Request
.
RemoteAddr
,
":"
)
ip
:=
strings
.
Split
(
input
.
Context
.
Request
.
RemoteAddr
,
":"
)
if
len
(
ip
)
>
0
{
if
ip
[
0
]
!=
"["
{
return
ip
[
0
]
...
...
@@ -236,7 +241,7 @@ func (input *BeegoInput) SubDomains() string {
// Port returns request client port.
// when error or empty, return 80.
func
(
input
*
BeegoInput
)
Port
()
int
{
parts
:=
strings
.
Split
(
input
.
Request
.
Host
,
":"
)
parts
:=
strings
.
Split
(
input
.
Context
.
Request
.
Host
,
":"
)
if
len
(
parts
)
==
2
{
port
,
_
:=
strconv
.
Atoi
(
parts
[
1
])
return
port
...
...
@@ -262,22 +267,22 @@ func (input *BeegoInput) Query(key string) string {
if
val
:=
input
.
Param
(
key
);
val
!=
""
{
return
val
}
if
input
.
Request
.
Form
==
nil
{
input
.
Request
.
ParseForm
()
if
input
.
Context
.
Request
.
Form
==
nil
{
input
.
Context
.
Request
.
ParseForm
()
}
return
input
.
Request
.
Form
.
Get
(
key
)
return
input
.
Context
.
Request
.
Form
.
Get
(
key
)
}
// Header returns request header item string by a given string.
// if non-existed, return empty string.
func
(
input
*
BeegoInput
)
Header
(
key
string
)
string
{
return
input
.
Request
.
Header
.
Get
(
key
)
return
input
.
Context
.
Request
.
Header
.
Get
(
key
)
}
// Cookie returns request cookie item string by a given key.
// if non-existed, return empty string.
func
(
input
*
BeegoInput
)
Cookie
(
key
string
)
string
{
ck
,
err
:=
input
.
Request
.
Cookie
(
key
)
ck
,
err
:=
input
.
Context
.
Request
.
Cookie
(
key
)
if
err
!=
nil
{
return
""
}
...
...
@@ -292,10 +297,10 @@ func (input *BeegoInput) Session(key interface{}) interface{} {
// CopyBody returns the raw request body data as bytes.
func
(
input
*
BeegoInput
)
CopyBody
()
[]
byte
{
requestbody
,
_
:=
ioutil
.
ReadAll
(
input
.
Request
.
Body
)
input
.
Request
.
Body
.
Close
()
requestbody
,
_
:=
ioutil
.
ReadAll
(
input
.
Context
.
Request
.
Body
)
input
.
Context
.
Request
.
Body
.
Close
()
bf
:=
bytes
.
NewBuffer
(
requestbody
)
input
.
Request
.
Body
=
ioutil
.
NopCloser
(
bf
)
input
.
Context
.
Request
.
Body
=
ioutil
.
NopCloser
(
bf
)
input
.
RequestBody
=
requestbody
return
requestbody
}
...
...
@@ -318,10 +323,10 @@ func (input *BeegoInput) SetData(key, val interface{}) {
func
(
input
*
BeegoInput
)
ParseFormOrMulitForm
(
maxMemory
int64
)
error
{
// Parse the body depending on the content type.
if
strings
.
Contains
(
input
.
Header
(
"Content-Type"
),
"multipart/form-data"
)
{
if
err
:=
input
.
Request
.
ParseMultipartForm
(
maxMemory
);
err
!=
nil
{
if
err
:=
input
.
Context
.
Request
.
ParseMultipartForm
(
maxMemory
);
err
!=
nil
{
return
errors
.
New
(
"Error parsing request body:"
+
err
.
Error
())
}
}
else
if
err
:=
input
.
Request
.
ParseForm
();
err
!=
nil
{
}
else
if
err
:=
input
.
Context
.
Request
.
ParseForm
();
err
!=
nil
{
return
errors
.
New
(
"Error parsing request body:"
+
err
.
Error
())
}
return
nil
...
...
@@ -386,13 +391,13 @@ func (input *BeegoInput) bind(key string, typ reflect.Type) reflect.Value {
}
rv
=
input
.
bindBool
(
val
,
typ
)
case
reflect
.
Slice
:
rv
=
input
.
bindSlice
(
&
input
.
Request
.
Form
,
key
,
typ
)
rv
=
input
.
bindSlice
(
&
input
.
Context
.
Request
.
Form
,
key
,
typ
)
case
reflect
.
Struct
:
rv
=
input
.
bindStruct
(
&
input
.
Request
.
Form
,
key
,
typ
)
rv
=
input
.
bindStruct
(
&
input
.
Context
.
Request
.
Form
,
key
,
typ
)
case
reflect
.
Ptr
:
rv
=
input
.
bindPoint
(
key
,
typ
)
case
reflect
.
Map
:
rv
=
input
.
bindMap
(
&
input
.
Request
.
Form
,
key
,
typ
)
rv
=
input
.
bindMap
(
&
input
.
Context
.
Request
.
Form
,
key
,
typ
)
}
return
rv
}
...
...
context/output.go
View file @
f70f3380
...
...
@@ -43,6 +43,12 @@ func NewOutput() *BeegoOutput {
return
&
BeegoOutput
{}
}
// Reset init BeegoOutput
func
(
output
*
BeegoOutput
)
Reset
(
ctx
*
Context
)
{
output
.
Context
=
ctx
output
.
Status
=
0
}
// Header sets response header item string via given key.
func
(
output
*
BeegoOutput
)
Header
(
key
,
val
string
)
{
output
.
Context
.
ResponseWriter
.
Header
()
.
Set
(
key
,
val
)
...
...
@@ -55,7 +61,7 @@ func (output *BeegoOutput) Body(content []byte) {
var
encoding
string
var
buf
=
&
bytes
.
Buffer
{}
if
output
.
EnableGzip
{
encoding
=
ParseEncoding
(
output
.
Context
.
Input
.
Request
)
encoding
=
ParseEncoding
(
output
.
Context
.
Request
)
}
if
b
,
n
,
_
:=
WriteBody
(
encoding
,
buf
,
content
);
b
{
output
.
Header
(
"Content-Encoding"
,
n
)
...
...
docs.go
View file @
f70f3380
...
...
@@ -21,13 +21,7 @@ import (
)
// GlobalDocAPI store the swagger api documents
var
GlobalDocAPI
map
[
string
]
interface
{}
func
init
()
{
if
BConfig
.
WebConfig
.
EnableDocs
{
GlobalDocAPI
=
make
(
map
[
string
]
interface
{})
}
}
var
GlobalDocAPI
=
make
(
map
[
string
]
interface
{})
func
serverDocs
(
ctx
*
context
.
Context
)
{
var
obj
interface
{}
...
...
router.go
View file @
f70f3380
...
...
@@ -24,6 +24,7 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"time"
beecontext
"github.com/astaxie/beego/context"
...
...
@@ -83,7 +84,7 @@ type logFilter struct {
}
func
(
l
*
logFilter
)
Filter
(
ctx
*
beecontext
.
Context
)
bool
{
requestPath
:=
path
.
Clean
(
ctx
.
Input
.
Request
.
URL
.
Path
)
requestPath
:=
path
.
Clean
(
ctx
.
Request
.
URL
.
Path
)
if
requestPath
==
"/favicon.ico"
||
requestPath
==
"/robots.txt"
{
return
true
}
...
...
@@ -114,14 +115,19 @@ type ControllerRegister struct {
routers
map
[
string
]
*
Tree
enableFilter
bool
filters
map
[
int
][]
*
FilterRouter
pool
sync
.
Pool
}
// NewControllerRegister returns a new ControllerRegister.
func
NewControllerRegister
()
*
ControllerRegister
{
return
&
ControllerRegister
{
cr
:=
&
ControllerRegister
{
routers
:
make
(
map
[
string
]
*
Tree
),
filters
:
make
(
map
[
int
][]
*
FilterRouter
),
}
cr
.
pool
.
New
=
func
()
interface
{}
{
return
beecontext
.
NewContext
()
}
return
cr
}
// Add controller handler and pattern rules to ControllerRegister.
...
...
@@ -132,7 +138,7 @@ func NewControllerRegister() *ControllerRegister {
// Add("/api/create",&RestController{},"post:CreateFood")
// Add("/api/update",&RestController{},"put:UpdateFood")
// Add("/api/delete",&RestController{},"delete:DeleteFood")
// Add("/api",&RestController{},"get,post:ApiFunc"
)
// Add("/api",&RestController{},"get,post:ApiFunc"
// Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
func
(
p
*
ControllerRegister
)
Add
(
pattern
string
,
c
ControllerInterface
,
mappingMethods
...
string
)
{
reflectVal
:=
reflect
.
ValueOf
(
c
)
...
...
@@ -573,26 +579,18 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin
// Implement http.Handler interface.
func
(
p
*
ControllerRegister
)
ServeHTTP
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
starttime
:=
time
.
Now
()
var
runrouter
reflect
.
Type
var
findrouter
bool
var
runMethod
string
var
routerInfo
*
controllerInfo
w
:
=
&
responseWriter
{
rw
,
false
,
0
}
var
(
runrouter
reflect
.
Type
findrouter
bool
runMethod
string
routerInfo
*
controllerInfo
w
=
&
responseWriter
{
rw
,
false
,
0
}
)
if
BConfig
.
RunMode
==
"dev"
{
w
.
Header
()
.
Set
(
"Server"
,
BConfig
.
ServerName
)
}
// init context
context
:=
&
beecontext
.
Context
{
ResponseWriter
:
w
,
Request
:
r
,
Input
:
beecontext
.
NewInput
(
r
),
Output
:
beecontext
.
NewOutput
(),
}
context
.
Output
.
Context
=
context
context
.
Output
.
EnableGzip
=
BConfig
.
EnableGzip
context
:=
p
.
pool
.
Get
()
.
(
*
beecontext
.
Context
)
context
.
Reset
(
w
,
r
)
defer
p
.
recoverPanic
(
context
)
...
...
@@ -670,23 +668,14 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
goto
Admin
}
if
context
.
Input
.
RunController
!=
nil
&&
context
.
Input
.
RunMethod
!=
""
{
findrouter
=
true
runMethod
=
context
.
Input
.
RunMethod
runrouter
=
context
.
Input
.
RunController
}
if
!
findrouter
{
httpMethod
:=
r
.
Method
if
httpMethod
==
"POST"
&&
context
.
Input
.
Query
(
"_method"
)
==
"PUT"
{
httpMethod
=
"PUT"
}
if
httpMethod
==
"POST"
&&
context
.
Input
.
Query
(
"_method"
)
==
"DELETE"
{
httpMethod
=
"DELETE"
}
if
t
,
ok
:=
p
.
routers
[
httpMethod
];
ok
{
runObject
,
p
:=
t
.
Match
(
urlPath
)
if
r
,
ok
:=
runObject
.
(
*
controllerInfo
);
ok
{
...
...
@@ -897,7 +886,6 @@ type responseWriter struct {
status
int
}
// 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.
...
...
staticfile.go
View file @
f70f3380
...
...
@@ -144,7 +144,7 @@ func isStaticCompress(filePath string) bool {
// searchFile search the file by url path
// if none the static file prefix matches ,return notStaticRequestErr
func
searchFile
(
ctx
*
context
.
Context
)
(
string
,
os
.
FileInfo
,
error
)
{
requestPath
:=
filepath
.
ToSlash
(
filepath
.
Clean
(
ctx
.
Input
.
Request
.
URL
.
Path
))
requestPath
:=
filepath
.
ToSlash
(
filepath
.
Clean
(
ctx
.
Request
.
URL
.
Path
))
// special processing : favicon.ico/robots.txt can be in any static dir
if
requestPath
==
"/favicon.ico"
||
requestPath
==
"/robots.txt"
{
file
:=
path
.
Join
(
"."
,
requestPath
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
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 comment