Description

Currently, there's no good way to add headers in middlewares after the status header (aka status code) gets written, since Go's implementation starts sending the headers as soon as the status gets written. The only way to do this at the moment is to hijack WriteHeader on the context's Writer. Although for simpler cases this is not that hard to implement by yourself (see this), it does not give access to the request's context, besides not being intuitive and incurring in some extra boilerplate for the structures + implementations.

The objective of this ticket is not to change the behavior of headers being non-writable after the status gets written, but instead to provide a streamlined way to do this.

Proposals

I can think of 2 options:

  1. Provide a AddStatusHook (or similar) method to gin.Context, which receives a func(*gin.Context). 'Hooked' functions get called on gin.Context's Status, and have access to context information. The issue with this approach is that it incurs an additional check for hooked functions on Status, even for people who are not using the 'feature'.
  2. Provide a MiddlewareWriter (or similar) struct, somewhere along the lines of:
type MiddlewareWriter struct {
    gin.ResponseWriter
    context *gin.Context
    hooks   []func(c *gin.Context)
}

func (w *MiddlewareWriter) WriteHeader(statusCode int) {
    for _, hook := range w.hooks {
        hook(w.context)
    }
    w.ResponseWriter.WriteHeader(statusCode)
}

The issue with this approach is that I'm not really sure wether the holding of a gin.Context reference may incur in any hidden issues. As long as there aren't any, although this is slightly more annoying to use than the first option, it would achieve the same result without incurring any changes in current code's performance.

I could write a PR for either options, but I would first like to know wether the maintainers are interested in such a feature in the first place.