2017-02-14 04:54:11 +01:00
|
|
|
package iris_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
. "gopkg.in/kataras/iris.v6"
|
|
|
|
"gopkg.in/kataras/iris.v6/httptest"
|
|
|
|
)
|
|
|
|
|
|
|
|
// This will be removed at the final release
|
|
|
|
// it's here just for my tests
|
2017-02-17 09:45:47 +01:00
|
|
|
// it will may transferred to the (advanced) examples repository
|
2017-02-14 04:54:11 +01:00
|
|
|
// in order to show the users how they can adapt any third-party router.
|
|
|
|
// They can also view the ./adaptors/httprouter and ./adaptors/gorillamux.
|
|
|
|
func newTestNativeRouter() Policies {
|
|
|
|
fireMethodNotAllowed := false
|
|
|
|
return Policies{
|
|
|
|
EventPolicy: EventPolicy{
|
|
|
|
Boot: func(s *Framework) {
|
|
|
|
fireMethodNotAllowed = s.Config.FireMethodNotAllowed
|
|
|
|
},
|
|
|
|
},
|
|
|
|
RouterReversionPolicy: RouterReversionPolicy{
|
|
|
|
// path normalization done on iris' side
|
|
|
|
StaticPath: func(path string) string { return path },
|
|
|
|
WildcardPath: func(requestPath string, paramName string) string { return requestPath },
|
|
|
|
URLPath: func(r RouteInfo, args ...string) string {
|
|
|
|
if r == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
// note:
|
|
|
|
// as we already know, net/http servemux doesn't provides parameterized paths so we will
|
|
|
|
// use the passed args(if any) to build the url query
|
|
|
|
path := r.Path()
|
|
|
|
if len(args) > 0 {
|
|
|
|
if len(args)%2 != 0 {
|
|
|
|
// key=value
|
|
|
|
// so the result of len args should be %2==0.
|
|
|
|
// if not return just the path.
|
|
|
|
return path
|
|
|
|
}
|
|
|
|
path += "?"
|
|
|
|
for i := 0; i < len(args)-1; i++ {
|
|
|
|
path += args[i] + "=" + args[i+1]
|
|
|
|
i++
|
|
|
|
if i != len(args)-1 {
|
|
|
|
path += "&"
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return path
|
|
|
|
},
|
|
|
|
},
|
|
|
|
RouterBuilderPolicy: func(repo RouteRepository, context ContextPool) http.Handler {
|
|
|
|
servemux := http.NewServeMux()
|
|
|
|
noIndexRegistered := true
|
2017-02-17 01:14:46 +01:00
|
|
|
|
2017-02-14 04:54:11 +01:00
|
|
|
repo.Visit(func(route RouteInfo) {
|
|
|
|
path := route.Path()
|
|
|
|
if path == "/" {
|
|
|
|
noIndexRegistered = false // this goes before the handlefunc("/")
|
|
|
|
}
|
|
|
|
if path[len(path)-1] != '/' { // append a slash (net/http works this way)
|
|
|
|
path += "/"
|
|
|
|
repo.ChangePath(route, path)
|
|
|
|
}
|
|
|
|
servemux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
ctx := context.Acquire(w, r)
|
|
|
|
|
|
|
|
if ctx.Method() == route.Method() || ctx.Method() == MethodOptions && route.HasCors() {
|
|
|
|
ctx.Middleware = route.Middleware()
|
|
|
|
recorder := ctx.Recorder()
|
|
|
|
ctx.Do()
|
|
|
|
|
|
|
|
statusCode := recorder.StatusCode()
|
|
|
|
if statusCode >= 400 { // if we have an error status code try to find a custom error handler
|
|
|
|
errorHandler := ctx.Framework().Errors.Get(statusCode)
|
|
|
|
if errorHandler != nil {
|
|
|
|
// it will reset the response and write its own response by the user's handler
|
|
|
|
errorHandler.Serve(ctx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if fireMethodNotAllowed {
|
|
|
|
ctx.EmitError(StatusMethodNotAllowed) // fire method not allowed if enabled
|
|
|
|
} else { // else fire not found
|
|
|
|
ctx.EmitError(StatusNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
context.Release(ctx)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2017-02-17 01:14:46 +01:00
|
|
|
// ok, we can't bypass the net/http server.go's err handlers
|
|
|
|
// we have two options:
|
|
|
|
// - create the mux by ourselve, not an ideal because we already done two of them.
|
|
|
|
// - create a new response writer which will check once if user has registered error handler,if yes write that response instead.
|
|
|
|
// - on "/" path(which net/http fallbacks if no any registered route handler found) make if requested_path != "/" or ""
|
|
|
|
// and emit the 404 error, but for the rest of the custom errors...?
|
|
|
|
// - use our custom context's recorder to record the status code, this will be a bit slower solution(maybe not)
|
|
|
|
// but it covers all our scenarios.
|
|
|
|
if noIndexRegistered {
|
|
|
|
servemux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
context.Run(w, r, func(ctx *Context) {
|
|
|
|
ctx.EmitError(StatusNotFound)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2017-02-14 04:54:11 +01:00
|
|
|
return servemux
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func h(ctx *Context) {
|
|
|
|
ctx.WriteString("hello from " + ctx.Path())
|
|
|
|
}
|
|
|
|
|
|
|
|
type testNativeRoute struct {
|
|
|
|
method, path, body string
|
|
|
|
status int
|
|
|
|
}
|
|
|
|
|
2017-02-18 07:03:14 +01:00
|
|
|
func TestNativeRouterPolicyAdaptor(t *testing.T) {
|
2017-02-14 04:54:11 +01:00
|
|
|
expectedWrongMethodStatus := StatusNotFound
|
|
|
|
app := New(Configuration{FireMethodNotAllowed: true})
|
|
|
|
app.Adapt(newTestNativeRouter())
|
|
|
|
// 404 or 405
|
|
|
|
if app.Config.FireMethodNotAllowed {
|
|
|
|
expectedWrongMethodStatus = StatusMethodNotAllowed
|
|
|
|
}
|
|
|
|
|
|
|
|
var testRoutes = []testNativeRoute{
|
|
|
|
{"GET", "/hi", "Should be /hi/ \nhello from /hi/", StatusOK},
|
|
|
|
{"GET", "/other", "Should be /other/ \nhello from /other/", StatusOK},
|
|
|
|
{"GET", "/hi/you", "Should be /hi/you/ \nhello from /hi/you/", StatusOK},
|
|
|
|
{"POST", "/hey", "hello from /hey/", StatusOK},
|
|
|
|
{"GET", "/hey", "Method Not Allowed", expectedWrongMethodStatus},
|
|
|
|
{"GET", "/doesntexists", "<b>Custom 404 page</b>", StatusNotFound},
|
|
|
|
}
|
|
|
|
app.OnError(404, func(ctx *Context) {
|
|
|
|
ctx.HTML(404, "<b>Custom 404 page</b>")
|
|
|
|
})
|
|
|
|
|
|
|
|
app.Get("/hi", func(ctx *Context) {
|
|
|
|
ctx.Writef("Should be /hi/ \n")
|
|
|
|
ctx.Next()
|
|
|
|
}, h)
|
|
|
|
|
|
|
|
app.Get("/other", func(ctx *Context) {
|
|
|
|
ctx.Writef("Should be /other/ \n")
|
|
|
|
ctx.Next()
|
|
|
|
}, h)
|
|
|
|
|
|
|
|
app.Get("/hi/you", func(ctx *Context) {
|
|
|
|
ctx.Writef("Should be /hi/you/ \n")
|
|
|
|
ctx.Next()
|
|
|
|
}, h)
|
|
|
|
|
|
|
|
app.Post("/hey", h)
|
|
|
|
|
|
|
|
app.None("/profile", func(ctx *Context) {
|
|
|
|
userid, _ := ctx.URLParamInt("user_id")
|
|
|
|
ref := ctx.URLParam("ref")
|
|
|
|
ctx.Writef("%s\n%d", userid, ref)
|
|
|
|
}).ChangeName("profile")
|
|
|
|
|
|
|
|
e := httptest.New(app, t)
|
2017-02-18 07:03:14 +01:00
|
|
|
expected := "/profile/?user_id=42&ref=iris-go&anything=something"
|
2017-02-14 04:54:11 +01:00
|
|
|
|
2017-02-18 07:03:14 +01:00
|
|
|
if got := app.Path("profile", "user_id", 42, "ref", "iris-go", "anything", "something"); got != expected {
|
2017-02-14 04:54:11 +01:00
|
|
|
t.Fatalf("URLPath expected %s but got %s", expected, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, r := range testRoutes {
|
|
|
|
// post should be passed with ending / here, it's not iris-specific.
|
|
|
|
if r.method == "POST" {
|
|
|
|
r.path += "/"
|
|
|
|
}
|
|
|
|
e.Request(r.method, r.path).Expect().Status(r.status).Body().Equal(r.body).Raw()
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|