From f5e250b1147f835f9aeac566bdcfdb4926f62ad2 Mon Sep 17 00:00:00 2001 From: Aofei Sheng Date: Tue, 28 May 2024 15:24:28 +0800 Subject: [PATCH] AppV2: ensure isolation of handler state per request Implemented a new duplication mechanism for the handler to create separate instances per request. This change addresses an issue where the same handler instance was shared across multiple requests, leading to state leakage and inconsistencies in AppV2. Each request now uses a fresh handler instance, ensuring isolated and consistent state management. Updates goplus/builder#532 Signed-off-by: Aofei Sheng --- classfile_v2.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/classfile_v2.go b/classfile_v2.go index 27d7414..fe085f1 100644 --- a/classfile_v2.go +++ b/classfile_v2.go @@ -57,12 +57,22 @@ type iHandler interface { func Gopt_AppV2_Main(app AppType, handlers ...iHandler) { app.InitYap() for _, h := range handlers { - reflect.ValueOf(h).Elem().Field(1).Set(reflect.ValueOf(app)) // (*handler).AppV2 = app + hVal := reflect.ValueOf(h).Elem() + hVal.FieldByName("AppV2").Set(reflect.ValueOf(app)) + hType := hVal.Type() + handle := func(ctx *Context) { + // We must duplicate the handler instance for each request + // to ensure state isolation. + h2Val := reflect.New(hType).Elem() + h2Val.Set(hVal) + h2 := h2Val.Addr().Interface().(iHandler) + h2.Main(ctx) + } switch method, path := parseClassfname(h.Classfname()); method { case "handle": - app.Handle(path, h.Main) + app.Handle(path, handle) default: - app.Route(strings.ToUpper(method), path, h.Main) + app.Route(strings.ToUpper(method), path, handle) } } if me, ok := app.(interface{ MainEntry() }); ok {