From ef8c886b101ab13258998cbb0cfca36db5b110e4 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 9 Sep 2024 08:36:19 +1000 Subject: [PATCH] Ignore internal service methods when binding (#3720) * Ignore internal service methods when binding * Updated changelog.md --- mkdocs-website/docs/en/changelog.md | 2 + v3/examples/services/hashes/hashes.go | 4 +- v3/examples/services/main.go | 9 ++++- v3/internal/assetserver/assetserver.go | 2 - v3/pkg/application/bindings.go | 50 +++++++++++++++++++----- v3/pkg/services/fileserver/fileserver.go | 1 - 6 files changed, 53 insertions(+), 15 deletions(-) diff --git a/mkdocs-website/docs/en/changelog.md b/mkdocs-website/docs/en/changelog.md index 43f583c0dd9..732b8ccd8fa 100644 --- a/mkdocs-website/docs/en/changelog.md +++ b/mkdocs-website/docs/en/changelog.md @@ -29,6 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [linux] Fixed linux compile error introduced by IgnoreMouseEvents addition by [atterpac](https://github.com/atterpac) in [#3721](https://github.com/wailsapp/wails/pull/3721) - [windows] Fixed syso icon file generation bug by [atterpac](https://github.com/atterpac) in [#3675](https://github.com/wailsapp/wails/pull/3675) - [linux] Fix to run natively in wayland incorporated from [#1811](https://github.com/wailsapp/wails/pull/1811) in [#3614](https://github.com/wailsapp/wails/pull/3614) by [@stendler](https://github.com/stendler) +- Do not bind internal service methods in [#3720](https://github.com/wailsapp/wails/pull/3720) + by [leaanthony](https://github.com/leaanthony) - [windows] Fixed system tray startup panic in [#3693](https://github.com/wailsapp/wails/issues/3693) by [@DeltaLaboratory](https://github.com/DeltaLaboratory) ## v3.0.0-alpha.6 - 2024-07-30 diff --git a/v3/examples/services/hashes/hashes.go b/v3/examples/services/hashes/hashes.go index f7bbed7eb98..8c9774b5917 100644 --- a/v3/examples/services/hashes/hashes.go +++ b/v3/examples/services/hashes/hashes.go @@ -1,10 +1,12 @@ package hashes import ( + "context" "crypto/md5" "crypto/sha1" "crypto/sha256" "encoding/hex" + "github.com/wailsapp/wails/v3/pkg/application" ) type Hashes struct { @@ -35,6 +37,6 @@ func (h *Hashes) Name() string { return "Hashes Service" } -func (h *Hashes) OnStartup() error { +func (h *Hashes) OnStartup(_ context.Context, _ application.ServiceOptions) error { return nil } diff --git a/v3/examples/services/main.go b/v3/examples/services/main.go index d0f8ea58221..74668cb9187 100644 --- a/v3/examples/services/main.go +++ b/v3/examples/services/main.go @@ -11,6 +11,7 @@ import ( "log/slog" "os" "path/filepath" + "runtime" ) //go:embed assets/* @@ -18,7 +19,13 @@ var assets embed.FS func main() { - rootPath, _ := filepath.Abs("./files") + // Get the local directory of this source file + // This isn't needed when running the example with `go run .` + // but is needed when running the example from an IDE + _, thisFile, _, _ := runtime.Caller(0) + localDir := filepath.Dir(thisFile) + + rootPath := filepath.Join(localDir, "files") app := application.New(application.Options{ Name: "Services Demo", Description: "A demo of the services API", diff --git a/v3/internal/assetserver/assetserver.go b/v3/internal/assetserver/assetserver.go index a52fe3c93d6..ee6919b66ef 100644 --- a/v3/internal/assetserver/assetserver.go +++ b/v3/internal/assetserver/assetserver.go @@ -112,8 +112,6 @@ func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request, userH for route, handler := range a.services { if strings.HasPrefix(reqPath, route) { req.URL.Path = strings.TrimPrefix(reqPath, route) - // Strip leading slash - req.URL.Path = strings.TrimPrefix(req.URL.Path, "/") handler.ServeHTTP(rw, req) return } diff --git a/v3/pkg/application/bindings.go b/v3/pkg/application/bindings.go index a7b1eb6c126..19ce52f337c 100644 --- a/v3/pkg/application/bindings.go +++ b/v3/pkg/application/bindings.go @@ -101,7 +101,7 @@ func NewBindings(instances []Service, aliases map[uint32]uint32) (*Bindings, err // Add the given named type pointer methods to the Bindings func (b *Bindings) Add(namedPtr interface{}) error { - methods, err := b.getMethods(namedPtr, false) + methods, err := b.getMethods(namedPtr) if err != nil { return fmt.Errorf("cannot bind value to app: %s", err.Error()) } @@ -153,7 +153,7 @@ func (b *BoundMethod) String() string { return fmt.Sprintf("%s.%s.%s", b.PackagePath, b.TypeName, b.Name) } -func (b *Bindings) getMethods(value interface{}, isPlugin bool) ([]*BoundMethod, error) { +func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) { // Create result placeholder var result []*BoundMethod @@ -188,6 +188,10 @@ func (b *Bindings) getMethods(value interface{}, isPlugin bool) ([]*BoundMethod, methodName := methodDef.Name method := namedValue.MethodByName(methodName) + if b.internalMethod(methodDef) { + continue + } + // Create new method boundMethod := &BoundMethod{ Name: methodName, @@ -204,16 +208,15 @@ func (b *Bindings) getMethods(value interface{}, isPlugin bool) ([]*BoundMethod, return nil, err } - if !isPlugin { - args := []any{"name", boundMethod, "id", boundMethod.ID} - if b.methodAliases != nil { - alias, found := lo.FindKey(b.methodAliases, boundMethod.ID) - if found { - args = append(args, "alias", alias) - } + args := []any{"name", boundMethod, "id", boundMethod.ID} + if b.methodAliases != nil { + alias, found := lo.FindKey(b.methodAliases, boundMethod.ID) + if found { + args = append(args, "alias", alias) } - globalApplication.debug("Adding method:", args...) } + globalApplication.debug("Adding method:", args...) + // Iterate inputs methodType := method.Type() inputParamCount := methodType.NumIn() @@ -245,6 +248,33 @@ func (b *Bindings) getMethods(value interface{}, isPlugin bool) ([]*BoundMethod, return result, nil } +func (b *Bindings) internalMethod(def reflect.Method) bool { + // Get the receiver type + receiverType := def.Type.In(0) + + // Create a new instance of the receiver type + instance := reflect.New(receiverType.Elem()).Interface() + + // Check if the instance implements any of our service interfaces + // and if the method matches the interface method + switch def.Name { + case "Name": + if _, ok := instance.(ServiceName); ok { + return true + } + case "OnStartup": + if _, ok := instance.(ServiceStartup); ok { + return true + } + case "OnShutdown": + if _, ok := instance.(ServiceShutdown); ok { + return true + } + } + + return false +} + var errorType = reflect.TypeFor[error]() // Call will attempt to call this bound method with the given args diff --git a/v3/pkg/services/fileserver/fileserver.go b/v3/pkg/services/fileserver/fileserver.go index ad9c11d60bd..f4cb1a0532d 100644 --- a/v3/pkg/services/fileserver/fileserver.go +++ b/v3/pkg/services/fileserver/fileserver.go @@ -47,6 +47,5 @@ func (s *Service) OnStartup(ctx context.Context, options application.ServiceOpti func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Create a new file server rooted at the given path - // Strip the base path out of the request path s.fs.ServeHTTP(w, r) }