0

I hope you can help me out since this gave me quite a headache.

I'm creating a chain for the middleware which is executed afterwards. But it looks like it has become recurring. The variable next within the anonymous function points to itself.

type MiddlewareInterface interface {
    // Run the middleware for the given request, and receive the next handler.
    Run(http.ResponseWriter, *http.Request, http.Handler)
}

createChain(collection []MiddlewareInterface, handler http.Handler) http.Handler
    next := handler

    for _, middlew := range collection {
        next = func(w http.ResponseWriter, res *http.Request) {
            middlew.Run(w, res, next)
        }
    }

    return next
}

I know it's kind of a noob question, but I sincerely do want to understand what causes this and how this can be resolved. Looking forward to your answers!

2
  • I think I'm being stupid, the anonymous function is invoked after the creation of the chain, which will probably be the value of the last time next has been set (so the last middleware). Which will always cause the function to point to itself. Isn't it? Commented Apr 24, 2018 at 21:23
  • You only have one next variable here at all. If you don't reuse the same one each time, they won't all be the same value at the end. (I'm not sure exactly what you're trying to do here, because this code isn't valid) Commented Apr 24, 2018 at 21:25

1 Answer 1

3

Seems this is a closure variable in loop problem. You are creating a function which is capturing next in each loop, but what this will mean is that all of the functions share the same variable next and they will all have the value that is left on the last loop. I think you can fix it by introducing a new temporary variable inside the loop scope:

func createChain(collection []MiddlewareInterface, handler http.Handler) http.Handler
    next := handler

    for _, middlew := range collection {
        thisNext:= next
        mw := middlew
        next = func(w http.ResponseWriter, res *http.Request) {
            mw.Run(w, res, thisNext)
        }
    }

    return next
}

Possibly the placement of the new variable definition isn't quite right but the closure issue will definitely be the source of your problem. It's not normally how http middleware handlers work as they normally wrap each other rather than being chained.

Sign up to request clarification or add additional context in comments.

2 Comments

I think you also have to make a copy of middlew for the same reason (it's the same variable every time through the loop).
You guys are hero's! That makes sense. I did copy the next variable in a previous attempt, hadn't thought about copying middlew. Thanks guys!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.