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
cd9e614a
Commit
cd9e614a
authored
Aug 15, 2014
by
astaxie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
plugins: basic auth & cors
parent
c1234e7c
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
525 additions
and
24 deletions
+525
-24
basic.go
plugins/auth/basic.go
+43
-24
cors.go
plugins/cors/cors.go
+229
-0
cors_test.go
plugins/cors/cors_test.go
+253
-0
No files found.
plugins/auth/basic.go
View file @
cd9e614a
//
Beego (http://beego.me/)
//
Copyright 2014 beego Author. All Rights Reserved.
//
// @description beego is an open-source, high-performance web framework for the Go programming language.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//
@link http://github.com/astaxie/beego for the canonical source repository
//
http://www.apache.org/licenses/LICENSE-2.0
//
// @license http://github.com/astaxie/beego/blob/master/LICENSE
//
// @authors astaxie
package
auth
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Example:
// Package auth provides handlers to enable basic auth support.
// Simple Usage:
// import(
// "github.com/astaxie/beego"
// "github.com/astaxie/beego/plugins/auth"
// )
//
// func main(){
// // authenticate every request
// beego.InsertFilter("*", beego.BeforeRouter,auth.Basic("username","secretpassword"))
// beego.Run()
// }
//
//
// Advanced Usage:
// func SecretAuth(username, password string) bool {
// if username == "astaxie" && password == "helloBeego" {
// return true
// }
// return false
// return username == "astaxie" && password == "helloBeego"
// }
// authPlugin := auth.NewBasicAuthenticator(SecretAuth, "
My Realm
")
// authPlugin := auth.NewBasicAuthenticator(SecretAuth, "
Authorization Required
")
// beego.InsertFilter("*", beego.BeforeRouter,authPlugin)
package
auth
import
(
"encoding/base64"
...
...
@@ -28,6 +43,15 @@ import (
"github.com/astaxie/beego/context"
)
var
defaultRealm
=
"Authorization Required"
func
Basic
(
username
string
,
password
string
)
beego
.
FilterFunc
{
secrets
:=
func
(
user
,
pass
string
)
bool
{
return
user
==
username
&&
pass
==
password
}
return
NewBasicAuthenticator
(
secrets
,
defaultRealm
)
}
func
NewBasicAuthenticator
(
secrets
SecretProvider
,
Realm
string
)
beego
.
FilterFunc
{
return
func
(
ctx
*
context
.
Context
)
{
a
:=
&
BasicAuth
{
Secrets
:
secrets
,
Realm
:
Realm
}
...
...
@@ -44,13 +68,10 @@ type BasicAuth struct {
Realm
string
}
/*
Checks the username/password combination from the request. Returns
either an empty string (authentication failed) or the name of the
authenticated user.
Supports MD5 and SHA1 password entries
*/
//Checks the username/password combination from the request. Returns
//either an empty string (authentication failed) or the name of the
//authenticated user.
//Supports MD5 and SHA1 password entries
func
(
a
*
BasicAuth
)
CheckAuth
(
r
*
http
.
Request
)
string
{
s
:=
strings
.
SplitN
(
r
.
Header
.
Get
(
"Authorization"
),
" "
,
2
)
if
len
(
s
)
!=
2
||
s
[
0
]
!=
"Basic"
{
...
...
@@ -72,10 +93,8 @@ func (a *BasicAuth) CheckAuth(r *http.Request) string {
return
""
}
/*
http.Handler for BasicAuth which initiates the authentication process
(or requires reauthentication).
*/
//http.Handler for BasicAuth which initiates the authentication process
//(or requires reauthentication).
func
(
a
*
BasicAuth
)
RequireAuth
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
Header
()
.
Set
(
"WWW-Authenticate"
,
`Basic realm="`
+
a
.
Realm
+
`"`
)
w
.
WriteHeader
(
401
)
...
...
plugins/cors/cors.go
0 → 100644
View file @
cd9e614a
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package cors provides handlers to enable CORS support.
// Usage
//
// import (
// "github.com/astaxie/beego"
// "github.com/astaxie/beego/plugins/cors"
// )
//func main() {
// // CORS for https://foo.* origins, allowing:
// // - PUT and PATCH methods
// // - Origin header
// // - Credentials share
// beego.InsertFilter("*", beego.BeforeRouter,cors.Allow(&cors.Options{
// AllowOrigins: []string{"https://*.foo.com"},
// AllowMethods: []string{"PUT", "PATCH"},
// AllowHeaders: []string{"Origin"},
// ExposeHeaders: []string{"Content-Length"},
// AllowCredentials: true,
// }))
// beego.Run()
//}
package
cors
import
(
"net/http"
"regexp"
"strconv"
"strings"
"time"
"github.com/astaxie/beego"
"github.com/astaxie/beego/context"
)
const
(
headerAllowOrigin
=
"Access-Control-Allow-Origin"
headerAllowCredentials
=
"Access-Control-Allow-Credentials"
headerAllowHeaders
=
"Access-Control-Allow-Headers"
headerAllowMethods
=
"Access-Control-Allow-Methods"
headerExposeHeaders
=
"Access-Control-Expose-Headers"
headerMaxAge
=
"Access-Control-Max-Age"
headerOrigin
=
"Origin"
headerRequestMethod
=
"Access-Control-Request-Method"
headerRequestHeaders
=
"Access-Control-Request-Headers"
)
var
(
defaultAllowHeaders
=
[]
string
{
"Origin"
,
"Accept"
,
"Content-Type"
,
"Authorization"
}
// Regex patterns are generated from AllowOrigins. These are used and generated internally.
allowOriginPatterns
=
[]
string
{}
)
// Options represents Access Control options.
type
Options
struct
{
// If set, all origins are allowed.
AllowAllOrigins
bool
// A list of allowed origins. Wild cards and FQDNs are supported.
AllowOrigins
[]
string
// If set, allows to share auth credentials such as cookies.
AllowCredentials
bool
// A list of allowed HTTP methods.
AllowMethods
[]
string
// A list of allowed HTTP headers.
AllowHeaders
[]
string
// A list of exposed HTTP headers.
ExposeHeaders
[]
string
// Max age of the CORS headers.
MaxAge
time
.
Duration
}
// Header converts options into CORS headers.
func
(
o
*
Options
)
Header
(
origin
string
)
(
headers
map
[
string
]
string
)
{
headers
=
make
(
map
[
string
]
string
)
// if origin is not allowed, don't extend the headers
// with CORS headers.
if
!
o
.
AllowAllOrigins
&&
!
o
.
IsOriginAllowed
(
origin
)
{
return
}
// add allow origin
if
o
.
AllowAllOrigins
{
headers
[
headerAllowOrigin
]
=
"*"
}
else
{
headers
[
headerAllowOrigin
]
=
origin
}
// add allow credentials
headers
[
headerAllowCredentials
]
=
strconv
.
FormatBool
(
o
.
AllowCredentials
)
// add allow methods
if
len
(
o
.
AllowMethods
)
>
0
{
headers
[
headerAllowMethods
]
=
strings
.
Join
(
o
.
AllowMethods
,
","
)
}
// add allow headers
if
len
(
o
.
AllowHeaders
)
>
0
{
headers
[
headerAllowHeaders
]
=
strings
.
Join
(
o
.
AllowHeaders
,
","
)
}
// add exposed header
if
len
(
o
.
ExposeHeaders
)
>
0
{
headers
[
headerExposeHeaders
]
=
strings
.
Join
(
o
.
ExposeHeaders
,
","
)
}
// add a max age header
if
o
.
MaxAge
>
time
.
Duration
(
0
)
{
headers
[
headerMaxAge
]
=
strconv
.
FormatInt
(
int64
(
o
.
MaxAge
/
time
.
Second
),
10
)
}
return
}
// PreflightHeader converts options into CORS headers for a preflight response.
func
(
o
*
Options
)
PreflightHeader
(
origin
,
rMethod
,
rHeaders
string
)
(
headers
map
[
string
]
string
)
{
headers
=
make
(
map
[
string
]
string
)
if
!
o
.
AllowAllOrigins
&&
!
o
.
IsOriginAllowed
(
origin
)
{
return
}
// verify if requested method is allowed
for
_
,
method
:=
range
o
.
AllowMethods
{
if
method
==
rMethod
{
headers
[
headerAllowMethods
]
=
strings
.
Join
(
o
.
AllowMethods
,
","
)
break
}
}
// verify if requested headers are allowed
var
allowed
[]
string
for
_
,
rHeader
:=
range
strings
.
Split
(
rHeaders
,
","
)
{
rHeader
=
strings
.
TrimSpace
(
rHeader
)
lookupLoop
:
for
_
,
allowedHeader
:=
range
o
.
AllowHeaders
{
if
strings
.
ToLower
(
rHeader
)
==
strings
.
ToLower
(
allowedHeader
)
{
allowed
=
append
(
allowed
,
rHeader
)
break
lookupLoop
}
}
}
headers
[
headerAllowCredentials
]
=
strconv
.
FormatBool
(
o
.
AllowCredentials
)
// add allow origin
if
o
.
AllowAllOrigins
{
headers
[
headerAllowOrigin
]
=
"*"
}
else
{
headers
[
headerAllowOrigin
]
=
origin
}
// add allowed headers
if
len
(
allowed
)
>
0
{
headers
[
headerAllowHeaders
]
=
strings
.
Join
(
allowed
,
","
)
}
// add exposed headers
if
len
(
o
.
ExposeHeaders
)
>
0
{
headers
[
headerExposeHeaders
]
=
strings
.
Join
(
o
.
ExposeHeaders
,
","
)
}
// add a max age header
if
o
.
MaxAge
>
time
.
Duration
(
0
)
{
headers
[
headerMaxAge
]
=
strconv
.
FormatInt
(
int64
(
o
.
MaxAge
/
time
.
Second
),
10
)
}
return
}
// IsOriginAllowed looks up if the origin matches one of the patterns
// generated from Options.AllowOrigins patterns.
func
(
o
*
Options
)
IsOriginAllowed
(
origin
string
)
(
allowed
bool
)
{
for
_
,
pattern
:=
range
allowOriginPatterns
{
allowed
,
_
=
regexp
.
MatchString
(
pattern
,
origin
)
if
allowed
{
return
}
}
return
}
// Allow enables CORS for requests those match the provided options.
func
Allow
(
opts
*
Options
)
beego
.
FilterFunc
{
// Allow default headers if nothing is specified.
if
len
(
opts
.
AllowHeaders
)
==
0
{
opts
.
AllowHeaders
=
defaultAllowHeaders
}
for
_
,
origin
:=
range
opts
.
AllowOrigins
{
pattern
:=
regexp
.
QuoteMeta
(
origin
)
pattern
=
strings
.
Replace
(
pattern
,
"
\\
*"
,
".*"
,
-
1
)
pattern
=
strings
.
Replace
(
pattern
,
"
\\
?"
,
"."
,
-
1
)
allowOriginPatterns
=
append
(
allowOriginPatterns
,
"^"
+
pattern
+
"$"
)
}
return
func
(
ctx
*
context
.
Context
)
{
var
(
origin
=
ctx
.
Input
.
Header
(
headerOrigin
)
requestedMethod
=
ctx
.
Input
.
Header
(
headerRequestMethod
)
requestedHeaders
=
ctx
.
Input
.
Header
(
headerRequestHeaders
)
// additional headers to be added
// to the response.
headers
map
[
string
]
string
)
if
ctx
.
Input
.
Method
()
==
"OPTIONS"
&&
(
requestedMethod
!=
""
||
requestedHeaders
!=
""
)
{
headers
=
opts
.
PreflightHeader
(
origin
,
requestedMethod
,
requestedHeaders
)
for
key
,
value
:=
range
headers
{
ctx
.
Output
.
Header
(
key
,
value
)
}
ctx
.
Output
.
SetStatus
(
http
.
StatusOK
)
return
}
headers
=
opts
.
Header
(
origin
)
for
key
,
value
:=
range
headers
{
ctx
.
Output
.
Header
(
key
,
value
)
}
}
}
plugins/cors/cors_test.go
0 → 100644
View file @
cd9e614a
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package cors provides handlers to enable CORS support.
package
cors
import
(
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"github.com/astaxie/beego"
"github.com/astaxie/beego/context"
)
type
HttpHeaderGuardRecorder
struct
{
*
httptest
.
ResponseRecorder
savedHeaderMap
http
.
Header
}
func
NewRecorder
()
*
HttpHeaderGuardRecorder
{
return
&
HttpHeaderGuardRecorder
{
httptest
.
NewRecorder
(),
nil
}
}
func
(
gr
*
HttpHeaderGuardRecorder
)
WriteHeader
(
code
int
)
{
gr
.
ResponseRecorder
.
WriteHeader
(
code
)
gr
.
savedHeaderMap
=
gr
.
ResponseRecorder
.
Header
()
}
func
(
gr
*
HttpHeaderGuardRecorder
)
Header
()
http
.
Header
{
if
gr
.
savedHeaderMap
!=
nil
{
// headers were written. clone so we don't get updates
clone
:=
make
(
http
.
Header
)
for
k
,
v
:=
range
gr
.
savedHeaderMap
{
clone
[
k
]
=
v
}
return
clone
}
else
{
return
gr
.
ResponseRecorder
.
Header
()
}
}
func
Test_AllowAll
(
t
*
testing
.
T
)
{
recorder
:=
httptest
.
NewRecorder
()
handler
:=
beego
.
NewControllerRegister
()
handler
.
InsertFilter
(
"*"
,
beego
.
BeforeRouter
,
Allow
(
&
Options
{
AllowAllOrigins
:
true
,
}))
handler
.
Any
(
"/foo"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
SetStatus
(
500
)
})
r
,
_
:=
http
.
NewRequest
(
"PUT"
,
"/foo"
,
nil
)
handler
.
ServeHTTP
(
recorder
,
r
)
if
recorder
.
HeaderMap
.
Get
(
headerAllowOrigin
)
!=
"*"
{
t
.
Errorf
(
"Allow-Origin header should be *"
)
}
}
func
Test_AllowRegexMatch
(
t
*
testing
.
T
)
{
recorder
:=
httptest
.
NewRecorder
()
handler
:=
beego
.
NewControllerRegister
()
handler
.
InsertFilter
(
"*"
,
beego
.
BeforeRouter
,
Allow
(
&
Options
{
AllowOrigins
:
[]
string
{
"https://aaa.com"
,
"https://*.foo.com"
},
}))
handler
.
Any
(
"/foo"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
SetStatus
(
500
)
})
origin
:=
"https://bar.foo.com"
r
,
_
:=
http
.
NewRequest
(
"PUT"
,
"/foo"
,
nil
)
r
.
Header
.
Add
(
"Origin"
,
origin
)
handler
.
ServeHTTP
(
recorder
,
r
)
headerValue
:=
recorder
.
HeaderMap
.
Get
(
headerAllowOrigin
)
if
headerValue
!=
origin
{
t
.
Errorf
(
"Allow-Origin header should be %v, found %v"
,
origin
,
headerValue
)
}
}
func
Test_AllowRegexNoMatch
(
t
*
testing
.
T
)
{
recorder
:=
httptest
.
NewRecorder
()
handler
:=
beego
.
NewControllerRegister
()
handler
.
InsertFilter
(
"*"
,
beego
.
BeforeRouter
,
Allow
(
&
Options
{
AllowOrigins
:
[]
string
{
"https://*.foo.com"
},
}))
handler
.
Any
(
"/foo"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
SetStatus
(
500
)
})
origin
:=
"https://ww.foo.com.evil.com"
r
,
_
:=
http
.
NewRequest
(
"PUT"
,
"/foo"
,
nil
)
r
.
Header
.
Add
(
"Origin"
,
origin
)
handler
.
ServeHTTP
(
recorder
,
r
)
headerValue
:=
recorder
.
HeaderMap
.
Get
(
headerAllowOrigin
)
if
headerValue
!=
""
{
t
.
Errorf
(
"Allow-Origin header should not exist, found %v"
,
headerValue
)
}
}
func
Test_OtherHeaders
(
t
*
testing
.
T
)
{
recorder
:=
httptest
.
NewRecorder
()
handler
:=
beego
.
NewControllerRegister
()
handler
.
InsertFilter
(
"*"
,
beego
.
BeforeRouter
,
Allow
(
&
Options
{
AllowAllOrigins
:
true
,
AllowCredentials
:
true
,
AllowMethods
:
[]
string
{
"PATCH"
,
"GET"
},
AllowHeaders
:
[]
string
{
"Origin"
,
"X-whatever"
},
ExposeHeaders
:
[]
string
{
"Content-Length"
,
"Hello"
},
MaxAge
:
5
*
time
.
Minute
,
}))
handler
.
Any
(
"/foo"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
SetStatus
(
500
)
})
r
,
_
:=
http
.
NewRequest
(
"PUT"
,
"/foo"
,
nil
)
handler
.
ServeHTTP
(
recorder
,
r
)
credentialsVal
:=
recorder
.
HeaderMap
.
Get
(
headerAllowCredentials
)
methodsVal
:=
recorder
.
HeaderMap
.
Get
(
headerAllowMethods
)
headersVal
:=
recorder
.
HeaderMap
.
Get
(
headerAllowHeaders
)
exposedHeadersVal
:=
recorder
.
HeaderMap
.
Get
(
headerExposeHeaders
)
maxAgeVal
:=
recorder
.
HeaderMap
.
Get
(
headerMaxAge
)
if
credentialsVal
!=
"true"
{
t
.
Errorf
(
"Allow-Credentials is expected to be true, found %v"
,
credentialsVal
)
}
if
methodsVal
!=
"PATCH,GET"
{
t
.
Errorf
(
"Allow-Methods is expected to be PATCH,GET; found %v"
,
methodsVal
)
}
if
headersVal
!=
"Origin,X-whatever"
{
t
.
Errorf
(
"Allow-Headers is expected to be Origin,X-whatever; found %v"
,
headersVal
)
}
if
exposedHeadersVal
!=
"Content-Length,Hello"
{
t
.
Errorf
(
"Expose-Headers are expected to be Content-Length,Hello. Found %v"
,
exposedHeadersVal
)
}
if
maxAgeVal
!=
"300"
{
t
.
Errorf
(
"Max-Age is expected to be 300, found %v"
,
maxAgeVal
)
}
}
func
Test_DefaultAllowHeaders
(
t
*
testing
.
T
)
{
recorder
:=
httptest
.
NewRecorder
()
handler
:=
beego
.
NewControllerRegister
()
handler
.
InsertFilter
(
"*"
,
beego
.
BeforeRouter
,
Allow
(
&
Options
{
AllowAllOrigins
:
true
,
}))
handler
.
Any
(
"/foo"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
SetStatus
(
500
)
})
r
,
_
:=
http
.
NewRequest
(
"PUT"
,
"/foo"
,
nil
)
handler
.
ServeHTTP
(
recorder
,
r
)
headersVal
:=
recorder
.
HeaderMap
.
Get
(
headerAllowHeaders
)
if
headersVal
!=
"Origin,Accept,Content-Type,Authorization"
{
t
.
Errorf
(
"Allow-Headers is expected to be Origin,Accept,Content-Type,Authorization; found %v"
,
headersVal
)
}
}
func
Test_Preflight
(
t
*
testing
.
T
)
{
recorder
:=
NewRecorder
()
handler
:=
beego
.
NewControllerRegister
()
handler
.
InsertFilter
(
"*"
,
beego
.
BeforeRouter
,
Allow
(
&
Options
{
AllowAllOrigins
:
true
,
AllowMethods
:
[]
string
{
"PUT"
,
"PATCH"
},
AllowHeaders
:
[]
string
{
"Origin"
,
"X-whatever"
,
"X-CaseSensitive"
},
}))
handler
.
Any
(
"/foo"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
SetStatus
(
200
)
})
r
,
_
:=
http
.
NewRequest
(
"OPTIONS"
,
"/foo"
,
nil
)
r
.
Header
.
Add
(
headerRequestMethod
,
"PUT"
)
r
.
Header
.
Add
(
headerRequestHeaders
,
"X-whatever, x-casesensitive"
)
handler
.
ServeHTTP
(
recorder
,
r
)
headers
:=
recorder
.
Header
()
methodsVal
:=
headers
.
Get
(
headerAllowMethods
)
headersVal
:=
headers
.
Get
(
headerAllowHeaders
)
originVal
:=
headers
.
Get
(
headerAllowOrigin
)
if
methodsVal
!=
"PUT,PATCH"
{
t
.
Errorf
(
"Allow-Methods is expected to be PUT,PATCH, found %v"
,
methodsVal
)
}
if
!
strings
.
Contains
(
headersVal
,
"X-whatever"
)
{
t
.
Errorf
(
"Allow-Headers is expected to contain X-whatever, found %v"
,
headersVal
)
}
if
!
strings
.
Contains
(
headersVal
,
"x-casesensitive"
)
{
t
.
Errorf
(
"Allow-Headers is expected to contain x-casesensitive, found %v"
,
headersVal
)
}
if
originVal
!=
"*"
{
t
.
Errorf
(
"Allow-Origin is expected to be *, found %v"
,
originVal
)
}
if
recorder
.
Code
!=
http
.
StatusOK
{
t
.
Errorf
(
"Status code is expected to be 200, found %d"
,
recorder
.
Code
)
}
}
func
Benchmark_WithoutCORS
(
b
*
testing
.
B
)
{
recorder
:=
httptest
.
NewRecorder
()
handler
:=
beego
.
NewControllerRegister
()
beego
.
RunMode
=
"prod"
handler
.
Any
(
"/foo"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
SetStatus
(
500
)
})
b
.
ResetTimer
()
for
i
:=
0
;
i
<
100
;
i
++
{
r
,
_
:=
http
.
NewRequest
(
"PUT"
,
"/foo"
,
nil
)
handler
.
ServeHTTP
(
recorder
,
r
)
}
}
func
Benchmark_WithCORS
(
b
*
testing
.
B
)
{
recorder
:=
httptest
.
NewRecorder
()
handler
:=
beego
.
NewControllerRegister
()
beego
.
RunMode
=
"prod"
handler
.
InsertFilter
(
"*"
,
beego
.
BeforeRouter
,
Allow
(
&
Options
{
AllowAllOrigins
:
true
,
AllowCredentials
:
true
,
AllowMethods
:
[]
string
{
"PATCH"
,
"GET"
},
AllowHeaders
:
[]
string
{
"Origin"
,
"X-whatever"
},
MaxAge
:
5
*
time
.
Minute
,
}))
handler
.
Any
(
"/foo"
,
func
(
ctx
*
context
.
Context
)
{
ctx
.
Output
.
SetStatus
(
500
)
})
b
.
ResetTimer
()
for
i
:=
0
;
i
<
100
;
i
++
{
r
,
_
:=
http
.
NewRequest
(
"PUT"
,
"/foo"
,
nil
)
handler
.
ServeHTTP
(
recorder
,
r
)
}
}
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