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 // it will may transferred to the (advanced) examples repository // 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 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) }) }) // 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) }) }) } return servemux }, } } func h(ctx *Context) { ctx.WriteString("hello from " + ctx.Path()) } type testNativeRoute struct { method, path, body string status int } func TestRouterPolicyAdaptor(t *testing.T) { 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", "Custom 404 page", StatusNotFound}, } app.OnError(404, func(ctx *Context) { ctx.HTML(404, "Custom 404 page") }) 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) expected := "/profile/?user_id=42&ref=iris-go&something=anything" if got := app.Path("profile", "user_id", 42, "ref", "iris-go", "something", "anything"); got != expected { 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() } }