Context: use timeout in JSON writer

This commit is contained in:
Muyao CHEN 2024-09-15 22:38:41 +02:00
parent f804f175e0
commit 33e9d1e613

View File

@ -28,14 +28,21 @@ type Context struct {
// NewContext create a new context // NewContext create a new context
func NewContext(w http.ResponseWriter, r *http.Request) *Context { func NewContext(w http.ResponseWriter, r *http.Request) *Context {
return &Context{ return &Context{
ctx: r.Context(),
request: r, request: r,
responseWriter: w, responseWriter: w,
writerMux: &sync.Mutex{},
} }
} }
// {{{ Basic functions // {{{ Basic functions
// WriterMux returns the writer mutex // WriterMux returns the writer mutex.
//
// This is useful when goroutines concurrently write into responseWriter,
// while at the same time we are writing into the responseWriter for a
// panic or timeout.
// We can protect it at the context level.
func (ctx *Context) WriterMux() *sync.Mutex { func (ctx *Context) WriterMux() *sync.Mutex {
return ctx.writerMux return ctx.writerMux
} }
@ -51,6 +58,8 @@ func (ctx *Context) GetResponseWriter() http.ResponseWriter {
} }
// SetHasTimeout indicates that the context has timeout. // SetHasTimeout indicates that the context has timeout.
//
// So that other goroutines won't write into the responseWriter anymore
func (ctx *Context) SetHasTimeout() { func (ctx *Context) SetHasTimeout() {
ctx.hasTimeout = true ctx.hasTimeout = true
} }
@ -237,6 +246,11 @@ func (ctx *Context) ReadJSON(obj any) error {
// WriteJSON send back an object in JSON format with the status code // WriteJSON send back an object in JSON format with the status code
func (ctx *Context) WriteJSON(status int, obj any) error { func (ctx *Context) WriteJSON(status int, obj any) error {
// There is a timeout, some error message data must have already been
// written to the output. Stop writing anything into the responseWriter.
if ctx.HasTimeout() {
return nil
}
data, err := json.Marshal(obj) data, err := json.Marshal(obj)
if err != nil { if err != nil {
return err return err