mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 18:51:03 +01:00
Implement the Status Method Not Allowed for gorilla mux too and add some tests
Former-commit-id: b157bacfa15567b8c98f959f3359e025fdf1b205
This commit is contained in:
parent
6fca78d12a
commit
b25d99870e
|
@ -34,6 +34,15 @@ import (
|
|||
|
||||
const dynamicSymbol = '{'
|
||||
|
||||
func staticPath(path string) string {
|
||||
i := strings.IndexByte(path, dynamicSymbol)
|
||||
if i > -1 {
|
||||
return path[0:i]
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
// New returns a new gorilla mux router which can be plugged inside iris.
|
||||
// This is magic.
|
||||
func New() iris.Policies {
|
||||
|
@ -46,14 +55,7 @@ func New() iris.Policies {
|
|||
}},
|
||||
RouterReversionPolicy: iris.RouterReversionPolicy{
|
||||
// path normalization done on iris' side
|
||||
StaticPath: func(path string) string {
|
||||
i := strings.IndexByte(path, dynamicSymbol)
|
||||
if i > -1 {
|
||||
return path[0:i]
|
||||
}
|
||||
|
||||
return path
|
||||
},
|
||||
StaticPath: staticPath,
|
||||
WildcardPath: func(requestPath string, paramName string) string {
|
||||
return requestPath + "/{" + paramName + ":.*}"
|
||||
},
|
||||
|
@ -94,10 +96,48 @@ func New() iris.Policies {
|
|||
|
||||
router.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.Acquire(w, r)
|
||||
// to catch custom 404 not found http errors may registered by user
|
||||
ctx.EmitError(iris.StatusNotFound)
|
||||
// gorilla mux doesn't supports fire method not allowed like iris
|
||||
// so this is my hack to support it:
|
||||
if ctx.Framework().Config.FireMethodNotAllowed {
|
||||
stopVisitor := false
|
||||
repo.Visit(func(route iris.RouteInfo) {
|
||||
if stopVisitor {
|
||||
return
|
||||
}
|
||||
// this is not going to work 100% for all routes especially the coblex
|
||||
// but this is the best solution, to check via static path, subdomain and cors to find the 'correct' route to
|
||||
// compare its method in order to implement the status method not allowed in gorilla mux which doesn't support it
|
||||
// and if I edit its internal implementation it will be complicated for new releases to be updated.
|
||||
p := staticPath(route.Path())
|
||||
if route.Subdomain() == "" || route.Subdomain() == ctx.Subdomain() {
|
||||
if p == ctx.Path() {
|
||||
// we don't care about this route because it has cors and this method is options
|
||||
// or its method is equal with the requests but the router didn't select this route
|
||||
// that means that the dynamic path didn't match, so we skip it.
|
||||
if (route.HasCors() && ctx.Method() == iris.MethodOptions) || ctx.Method() == route.Method() {
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.Method() != route.Method() {
|
||||
// RCF rfc2616 https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
// The response MUST include an Allow header containing a list of valid methods for the requested resource.
|
||||
ctx.SetHeader("Allow", route.Method())
|
||||
ctx.EmitError(iris.StatusMethodNotAllowed)
|
||||
stopVisitor = true
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
} else {
|
||||
// to catch custom 404 not found http errors may registered by user
|
||||
ctx.EmitError(iris.StatusNotFound)
|
||||
}
|
||||
context.Release(ctx)
|
||||
})
|
||||
|
||||
return router
|
||||
},
|
||||
}
|
||||
|
|
|
@ -702,12 +702,17 @@ func (mux *serveMux) buildHandler(pool iris.ContextPool) http.Handler {
|
|||
}
|
||||
// https://github.com/kataras/iris/issues/469
|
||||
if context.Framework().Config.FireMethodNotAllowed {
|
||||
var methodAllowed string
|
||||
for i := range mux.garden {
|
||||
tree := mux.garden[i]
|
||||
methodAllowed = tree.method // keep track of the allowed method of the last checked tree
|
||||
if !mux.methodEqual(context.Method(), tree.method) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// RCF rfc2616 https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
// The response MUST include an Allow header containing a list of valid methods for the requested resource.
|
||||
context.SetHeader("Allow", methodAllowed)
|
||||
context.EmitError(iris.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
|
61
handler_test.go
Normal file
61
handler_test.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
// black-box
|
||||
package iris_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/httptest"
|
||||
)
|
||||
|
||||
const testCustomHandlerParamName = "myparam"
|
||||
|
||||
type myTestHandlerData struct {
|
||||
Sysname string // this will be the same for all requests
|
||||
Version int // this will be the same for all requests
|
||||
URLParameter string // this will be different for each request
|
||||
}
|
||||
|
||||
type myTestCustomHandler struct {
|
||||
data myTestHandlerData
|
||||
}
|
||||
|
||||
func (m *myTestCustomHandler) Serve(ctx *iris.Context) {
|
||||
data := &m.data
|
||||
data.URLParameter = ctx.URLParam(testCustomHandlerParamName)
|
||||
ctx.JSON(iris.StatusOK, data)
|
||||
}
|
||||
|
||||
func TestCustomHandler(t *testing.T) {
|
||||
app := iris.New()
|
||||
app.Adapt(newTestNativeRouter())
|
||||
|
||||
myData := myTestHandlerData{
|
||||
Sysname: "Redhat",
|
||||
Version: 1,
|
||||
}
|
||||
app.Handle("GET", "/custom_handler_1", &myTestCustomHandler{myData})
|
||||
app.Handle("GET", "/custom_handler_2", &myTestCustomHandler{myData})
|
||||
|
||||
e := httptest.New(app, t, httptest.Debug(true))
|
||||
// two times per testRoute
|
||||
param1 := "thisimyparam1"
|
||||
expectedData1 := myData
|
||||
expectedData1.URLParameter = param1
|
||||
e.GET("/custom_handler_1/").WithQuery(testCustomHandlerParamName, param1).Expect().Status(iris.StatusOK).JSON().Equal(expectedData1)
|
||||
|
||||
param2 := "thisimyparam2"
|
||||
expectedData2 := myData
|
||||
expectedData2.URLParameter = param2
|
||||
e.GET("/custom_handler_1/").WithQuery(testCustomHandlerParamName, param2).Expect().Status(iris.StatusOK).JSON().Equal(expectedData2)
|
||||
|
||||
param3 := "thisimyparam3"
|
||||
expectedData3 := myData
|
||||
expectedData3.URLParameter = param3
|
||||
e.GET("/custom_handler_2/").WithQuery(testCustomHandlerParamName, param3).Expect().Status(iris.StatusOK).JSON().Equal(expectedData3)
|
||||
|
||||
param4 := "thisimyparam4"
|
||||
expectedData4 := myData
|
||||
expectedData4.URLParameter = param4
|
||||
e.GET("/custom_handler_2/").WithQuery(testCustomHandlerParamName, param4).Expect().Status(iris.StatusOK).JSON().Equal(expectedData4)
|
||||
}
|
|
@ -255,3 +255,27 @@ func TestGorillaMuxRouteURLPath(t *testing.T) {
|
|||
t.Fatalf("gorillamux' reverse routing 'URLPath' error: expected %s but got %s", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGorillaMuxFireMethodNotAllowed(t *testing.T) {
|
||||
app := iris.New()
|
||||
app.Adapt(gorillamux.New())
|
||||
app.Config.FireMethodNotAllowed = true
|
||||
h := func(ctx *iris.Context) {
|
||||
ctx.WriteString(ctx.Method())
|
||||
}
|
||||
|
||||
app.OnError(iris.StatusMethodNotAllowed, func(ctx *iris.Context) {
|
||||
ctx.WriteString("Hello from my custom 405 page")
|
||||
})
|
||||
|
||||
app.Get("/mypath", h)
|
||||
app.Put("/mypath", h)
|
||||
|
||||
e := httptest.New(app, t)
|
||||
|
||||
e.GET("/mypath").Expect().Status(iris.StatusOK).Body().Equal("GET")
|
||||
e.PUT("/mypath").Expect().Status(iris.StatusOK).Body().Equal("PUT")
|
||||
// this should fail with 405 and catch by the custom http error
|
||||
|
||||
e.POST("/mypath").Expect().Status(iris.StatusMethodNotAllowed).Body().Equal("Hello from my custom 405 page")
|
||||
}
|
||||
|
|
|
@ -268,3 +268,27 @@ func TestHTTPRouterRouteURLPath(t *testing.T) {
|
|||
t.Fatalf("httprouter's reverse routing 'URLPath' error: expected %s but got %s", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPRouterFireMethodNotAllowed(t *testing.T) {
|
||||
app := iris.New()
|
||||
app.Adapt(httprouter.New())
|
||||
app.Config.FireMethodNotAllowed = true
|
||||
h := func(ctx *iris.Context) {
|
||||
ctx.WriteString(ctx.Method())
|
||||
}
|
||||
|
||||
app.OnError(iris.StatusMethodNotAllowed, func(ctx *iris.Context) {
|
||||
ctx.WriteString("Hello from my custom 405 page")
|
||||
})
|
||||
|
||||
app.Get("/mypath", h)
|
||||
app.Put("/mypath", h)
|
||||
|
||||
e := httptest.New(app, t)
|
||||
|
||||
e.GET("/mypath").Expect().Status(iris.StatusOK).Body().Equal("GET")
|
||||
e.PUT("/mypath").Expect().Status(iris.StatusOK).Body().Equal("PUT")
|
||||
// this should fail with 405 and catch by the custom http error
|
||||
|
||||
e.POST("/mypath").Expect().Status(iris.StatusMethodNotAllowed).Body().Equal("Hello from my custom 405 page")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user