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

how to break-out of middleware chain using Martini #428

Open
ORESoftware opened this issue Mar 14, 2020 · 2 comments
Open

how to break-out of middleware chain using Martini #428

ORESoftware opened this issue Mar 14, 2020 · 2 comments

Comments

@ORESoftware
Copy link

ORESoftware commented Mar 14, 2020

I put this question on SO and am looking for answers - this question may be based off a false assumption:

https://stackoverflow.com/questions/60679922/how-to-break-out-of-martini-middleware

but at the very least I have no idea how martini would know when to keep invoking the middleware chain and when not to? it wouldn't know even if you aleady set the http status code or wrote the response body, you may still want to keep writing in subsequent middleware funcs. someone please explain how to return early out of the chain.

Perhaps this is the best way to do it?

m.Use(func(c martini.Context, w http.ResponseWriter){

    if reqIsMalformed() {
        http.Error(w, "Bad request because xyz", 422)
        return;
    }

    c.Next()  // only invoke remaining middleware if the request is valid?

})
@ORESoftware ORESoftware changed the title how to break-out of middleware chain how to break-out of middleware chain using Martini Mar 14, 2020
@ORESoftware
Copy link
Author

ORESoftware commented Mar 15, 2020

I did some legwork and ran a test:

func check0() {
	return;
}

func check1(res http.ResponseWriter) string{
	return "1"
}

func check2(c martini.Context, res http.ResponseWriter) string{
	if true {
		return "hiii";
	}
	c.Next()
	return "2"
}

func check3(c martini.Context, res http.ResponseWriter) string{
	c.Next()
	return "3"
}

func check4(res http.ResponseWriter) {
	res.Write([]byte("4"))
}

func check5(c martini.Context, res http.ResponseWriter) string{
	res.Write([]byte("5.0"))
	c.Next()
	return "5.1"
}

func finish(res http.ResponseWriter){
	fmt.Println("in finish")
	res.Write([]byte("all done"))
}

func Routes(m *martini.ClassicMartini) {
        m.Get("/cp/meta/middleware0", check0, finish)
	m.Get("/cp/meta/middleware1", check1, finish)
	m.Get("/cp/meta/middleware2", check2, finish)
	m.Get("/cp/meta/middleware3", check3, finish)
	m.Get("/cp/meta/middleware4", check4, finish)
	m.Get("/cp/meta/middleware5", check5, finish)
}

the results I got:

GET /cp/meta/middleware0 => all done
GET /cp/meta/middleware1 => 1
GET /cp/meta/middleware2 => hiii
GET /cp/meta/middleware3 => all done3
GET /cp/meta/middleware4 => 4
GET /cp/meta/middleware5 => 5.0all done5.1

what surprised me is that the subsequent middleware (the finish() func) was not called for :

GET /cp/meta/middleware4

what is the reason for this? Other than that, the rule seems to be if the middleware func returns anything (return args length > 0), then no more middleware is called unless c.Next() is called of course).

Please document which scenarios cause middleware to stop being called and/or how to continue calling subsequent registered middleware.

@straightdave
Copy link

I add the Break() method for martini's context like this:

func (c *context) Break() {
	// skip other handlers plus one possible action
	c.index = len(c.handlers) + 1
	c.run()
}

This will skip the loop in func (c *context) run().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants