Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why GetBy can't be accessed, but PostBy can #1487

Open
weigun opened this issue Apr 16, 2020 · 5 comments
Open

Why GetBy can't be accessed, but PostBy can #1487

weigun opened this issue Apr 16, 2020 · 5 comments

Comments

@weigun
Copy link

weigun commented Apr 16, 2020

Hello everyone, we are currently experiencing a strange problem and would like to ask for your help, as follows.

GET, visit http://127.0.0.1:8080/project/1, return 404

POST, visit http://127.0.0.1:8080/project/1, return 200

Only GetBy(id int64) is defined in the controller, not PostBy.

The code is as follows.

iris version:V12

controller:

// http://127.0.0.1:8080/project/1
func (p *ProjectController) GetBy(id int64) *proto.RspProject {
	p.Ctx.Application().Logger().Infof(`get project info`)  //should be prinf
	ret := proto.NewRspProject()
        return ret
}

route defined:

//route interface
type router interface {
	setup(*mvc.Application)
	path() string
}

//router manager:
func (r *routerMgr) Init(app *iris.Application) {
	for _, v := range r.routers {
		mvc.Configure(app.Party(v.path(), crs).AllowMethods(iris.MethodGet, iris.MethodPost), v.setup)
	}
}

func (r *routerMgr) register(route ...router) {
	r.routers = append(r.routers, route...)
}
//
//
//
//route define:
type projectRoute int

func (r *projectRoute) path() string {
	return `/project`
}

func (r *projectRoute) setup(app *mvc.Application) {
	servPro := services.NewProjectService()
	sessManager := sessions.New(sessions.Config{
		Cookie:       "project",
		Expires:      60 * time.Minute,
		AllowReclaim: true,
	})
	app.Register(servPro, sessManager.Start)
	app.Handle(new(controllers.ProjectController))
}
//
//
//
//somewhere register
NewRouterMgr().register(
	new(usersRoute),
	new(projectRoute),
)

debug log here:

[DBUG] 2020/04/16 15:22 MVC Controller [controllers.UserController] [Scope=Stateless]
[DBUG] 2020/04/16 15:22 Dependencies:
	[1] Static binding: &services.userService{repo:(*dao.userDao)(0xc0000ca3a8)} for field 'UserServ services.UserService'

[DBUG] 2020/04/16 15:22 MVC dependencies of method 'controllers.UserController.GetBy':
[1] Dynamic binding: 'int64' for input position: 1 and type: 'int64'

[DBUG] 2020/04/16 15:22 MVC Controller [controllers.ProjectController] [Scope=Stateless]
[DBUG] 2020/04/16 15:22 Dependencies:
	[1] Static binding: &services.projectService{repo:(*dao.projectDao)(0xc0000ca788)} for field 'ProServ services.ProjectService'

[DBUG] 2020/04/16 15:22 MVC dependencies of method 'controllers.ProjectController.GetBy':
[1] Dynamic binding: 'int64' for input position: 1 and type: 'int64'

[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] GET: /users/{param1:int64} -> controllers.UserController.GetBy() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\project.go:29] GET: /project/{param1:int64} -> controllers.ProjectController.GetBy() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] GET: /users/search -> github.com/kataras/iris/v12/mvc.(*ControllerActivator).handlerOf.func2() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] GET: /users/add -> github.com/kataras/iris/v12/mvc.(*ControllerActivator).handlerOf.func2() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\project.go:29] GET: /project/allmembers -> github.com/kataras/iris/v12/mvc.(*ControllerActivator).handlerOf.func2() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] GET: /users/delete -> github.com/kataras/iris/v12/mvc.(*ControllerActivator).handlerOf.func2() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] GET: /users/login -> github.com/kataras/iris/v12/mvc.(*ControllerActivator).handlerOf.func2() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\project.go:29] POST: /project/{param1:int64} -> github.com/kataras/iris/v12/mvc.(*ControllerActivator).handlerOf.func2() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] GET: /users/logout -> github.com/kataras/iris/v12/mvc.(*ControllerActivator).handlerOf.func2() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] GET: /users/update -> github.com/kataras/iris/v12/mvc.(*ControllerActivator).handlerOf.func2() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] GET: /users/reg -> github.com/kataras/iris/v12/mvc.(*ControllerActivator).handlerOf.func2() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] POST: /users/{param1:int64} -> github.com/kataras/iris/v12/mvc.(*ControllerActivator).handlerOf.func2() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] POST: /users/reg -> controllers.UserController.PostReg() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] POST: /users/search -> controllers.UserController.PostSearch() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] POST: /users/logout -> controllers.UserController.PostLogout() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] POST: /users/update -> controllers.UserController.PostUpdate() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] POST: /users/login -> controllers.UserController.PostLogin() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] POST: /users/delete -> controllers.UserController.PostDelete() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\users.go:29] POST: /users/add -> controllers.UserController.PostAdd() and 1 more
[DBUG] 2020/04/16 15:22 [./web\routers\project.go:29] POST: /project/allmembers -> controllers.ProjectController.PostAllmembers() and 1 more
[DBUG] 2020/04/16 15:22 Application: running using 1 host(s)
[DBUG] 2020/04/16 15:22 Host: addr is localhost:8080
[DBUG] 2020/04/16 15:22 Host: virtual host is localhost:8080
[DBUG] 2020/04/16 15:22 Host: register startup notifier
[DBUG] 2020/04/16 15:22 Host: register server shutdown on interrupt(CTRL+C/CMD+C)
[DBUG] 2020/04/16 15:22 Host: server will ignore the following errors: [http: Server closed]
Now listening on: http://localhost:8080
Application started. Press CTRL+C to shut down.
@kataras
Copy link
Owner

kataras commented Apr 17, 2020

Hello @weigun, it seems that the route is registered correctly, there is nothing wrong here, are you sure it finds POST instead of GET? Because I can't re-produce your issue, take look at the example and test below:

// file: main.go
package main

import (
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/mvc"
)

func main() {
	app := newApp()

	app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
}

func newApp() *iris.Application {
	app := iris.New().Configure(iris.WithFireMethodNotAllowed)

	mvc.New(app.Party("/project")).Handle(new(testControllerGetBy))

	return app
}

type testCustomStruct struct {
	Name string `json:"name" xml:"name"`
	Age  int    `json:"age" xml:"age"`
}

type testControllerGetBy struct{}

func (c *testControllerGetBy) GetBy(age int64) *testCustomStruct {
	return &testCustomStruct{
		Age:  int(age),
		Name: "name",
	}
}

And its main_test.go:

package main

import (
	"testing"

	"github.com/kataras/iris/v12/httptest"
)

func TestControllerGetBy(t *testing.T) {
	// Tests only GetBy.
	app := newApp()

	e := httptest.New(t, app)
	e.GET("/project/42").Expect().Status(httptest.StatusOK).
		JSON().Equal(&testCustomStruct{Age: 42, Name: "name"})
	e.POST("/project/42").Expect().Status(httptest.StatusMethodNotAllowed)
}

Output:

PS C:\mygopath\src\github.com\kataras\iris\_examples\1487> go test -v
=== RUN   TestControllerGetBy
--- PASS: TestControllerGetBy (0.00s)
PASS
ok      github.com/kataras/iris/v12/_examples/1487      0.141s

Tested on v12 (and master) branch

@weigun
Copy link
Author

weigun commented Apr 21, 2020

Hello @weigun, it seems that the route is registered correctly, there is nothing wrong here, are you sure it finds POST instead of GET? Because I can't re-produce your issue, take look at the example and test below:

// file: main.go
package main

import (
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/mvc"
)

func main() {
	app := newApp()

	app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
}

func newApp() *iris.Application {
	app := iris.New().Configure(iris.WithFireMethodNotAllowed)

	mvc.New(app.Party("/project")).Handle(new(testControllerGetBy))

	return app
}

type testCustomStruct struct {
	Name string `json:"name" xml:"name"`
	Age  int    `json:"age" xml:"age"`
}

type testControllerGetBy struct{}

func (c *testControllerGetBy) GetBy(age int64) *testCustomStruct {
	return &testCustomStruct{
		Age:  int(age),
		Name: "name",
	}
}

And its main_test.go:

package main

import (
	"testing"

	"github.com/kataras/iris/v12/httptest"
)

func TestControllerGetBy(t *testing.T) {
	// Tests only GetBy.
	app := newApp()

	e := httptest.New(t, app)
	e.GET("/project/42").Expect().Status(httptest.StatusOK).
		JSON().Equal(&testCustomStruct{Age: 42, Name: "name"})
	e.POST("/project/42").Expect().Status(httptest.StatusMethodNotAllowed)
}

Output:

PS C:\mygopath\src\github.com\kataras\iris\_examples\1487> go test -v
=== RUN   TestControllerGetBy
--- PASS: TestControllerGetBy (0.00s)
PASS
ok      github.com/kataras/iris/v12/_examples/1487      0.141s

Tested on v12 (and master) branch

I'm very sorry for the late reply. I'll test it again today.

@weigun
Copy link
Author

weigun commented Apr 21, 2020

I found that the problem stems from the ''AllowMethods'' method.
My test code is as follows.

package main

import (
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/mvc"
)

func main() {
	app := newApp()
	app.Logger().SetLevel(`debug`)

	app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
}

func newApp() *iris.Application {
	app := iris.New().Configure(iris.WithFireMethodNotAllowed)

	mvc.New(app.Party("/project").AllowMethods(iris.MethodGet, iris.MethodPost)).Handle(new(testControllerGetBy))

	return app
}

type testCustomStruct struct {
	Name string `json:"name" xml:"name"`
	Age  int    `json:"age" xml:"age"`
}

type testControllerGetBy struct{}

func (c *testControllerGetBy) GetBy(age int64) *testCustomStruct {
	return &testCustomStruct{
		Age:  int(age),
		Name: "name",
	}
}

And its main_test.go:

package main

import (
	"testing"

	"github.com/kataras/iris/v12/httptest"
)

func TestControllerGetBy(t *testing.T) {
	// Tests only GetBy.
	app := newApp()

	e := httptest.New(t, app)
	e.GET("/project/42").Expect().Status(httptest.StatusOK).
		JSON().Equal(&testCustomStruct{Age: 42, Name: "name"})
	e.POST("/project/42").Expect().Status(httptest.StatusMethodNotAllowed)
}

Output:

D:/Go/bin/go.exe test -v [D:/test-area/oschina/APITester/test]
=== RUN   TestControllerGetBy
    TestControllerGetBy: reporter.go:23: 
        	Error Trace:	reporter.go:23
        	            				chain.go:21
        	            				response.go:585
        	            				response.go:151
        	            				main_test.go:14
        	Error:      	
        	            	expected status equal to:
        	            	 "200 OK"
        	            	
        	            	but got:
        	            	 "405 Method Not Allowed"
        	Test:       	TestControllerGetBy
    TestControllerGetBy: reporter.go:23: 
        	Error Trace:	reporter.go:23
        	            				chain.go:21
        	            				response.go:585
        	            				response.go:151
        	            				main_test.go:16
        	Error:      	
        	            	expected status equal to:
        	            	 "405 Method Not Allowed"
        	            	
        	            	but got:
        	            	 "200 OK"
        	Test:       	TestControllerGetBy
--- FAIL: TestControllerGetBy (0.00s)
FAIL
exit status 1
FAIL	APITester/test	0.320s

@kataras
Copy link
Owner

kataras commented Apr 21, 2020

@weigun that's the point of AllowMethods, to register routes, under particular Party, to a set of HTTP Method verbs if a route for that method is missing, for example with GetBy the framework will register a GET route but because you have AllowMethods(iris.MethodPost, ...) it will also register the same route on the POST.

So, the correct test is that:

func TestControllerGetByWithAllowMethods(t *testing.T) {
	app := iris.New()
	app.Configure(iris.WithFireMethodNotAllowed) 
        // ^ this 405 status will not be fired on POST: project/... because of 
        // .AllowMethods, but it will on PUT.

	New(app.Party("/project").AllowMethods(iris.MethodGet, iris.MethodPost)).
             Handle(new(testControllerGetBy))

	e := httptest.New(t, app)

	e.GET("/project/42").Expect().Status(httptest.StatusOK).
		JSON().Equal(&testCustomStruct{Age: 42, Name: "name"})
	e.POST("/project/42").Expect().Status(httptest.StatusOK)

	e.PUT("/project/42").Expect().Status(httptest.StatusMethodNotAllowed)
}

Tested on master branch.

=== RUN   TestControllerGetByWithAllowMethods
--- PASS: TestControllerGetByWithAllowMethods (0.00s)
PASS
ok      github.com/kataras/iris/v12/mvc 0.151s

At the current state of the v12 branch that will fail, it will not find the GET route, it had a small bug which tried to override the GET method in that case:

                        expected status equal to:
                                 "200 OK"

                                but got:
                                 "405 Method Not Allowed"

This is fixed on master branch, future v12.2.0 release. So you did well opening this issue, as MVC had conflicts with the AllowMethods. Thank you @weigun!

@weigun
Copy link
Author

weigun commented Apr 21, 2020

Just as I was about to reply to you that the test was still failing, I found that you had updated the comments. It's great that the problem is fixed.
Thank you @kataras

kataras added a commit that referenced this issue Jul 26, 2020
…1487

Former-commit-id: 5f4abd4a8c6528d666d91315fa515a4a607326fc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants