Skip to content

Gin support #4128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 18, 2025
Merged

Gin support #4128

merged 11 commits into from
Apr 18, 2025

Conversation

leaanthony
Copy link
Member

@leaanthony leaanthony commented Mar 11, 2025

This PR contains:

  • Updates to the AssetServer to support Gin
  • 2 new examples for using Gin as a Router and in a Service
  • Updated documentation
  • A slight interface change for Events (non-breaking)

Based on the original PR here: #3537

Summary by CodeRabbit

  • New Features

    • Added comprehensive support and documentation for integrating the Gin web framework with Wails, including new examples, middleware, and guides for routing and service usage.
    • Introduced user management features in Gin service examples, including creating, retrieving, and deleting users with real-time event notifications.
  • Improvements

    • Enhanced event emission API for simpler and more flexible usage.
    • Improved asset server capabilities with better content type handling and serving of specific JavaScript assets.
    • Updated dependency versions for improved compatibility and stability.
  • Documentation

    • Added and updated guides, READMEs, and changelog entries to reflect new Gin integration and features.
  • Bug Fixes

    • Various bug fixes and platform improvements as documented in the changelog.

AnalogJ and others added 7 commits March 9, 2025 14:38
…ontentTypeSniffer, for Gin (and other framework) compatibility.
Serve runtime from assetserver if requested.
Serve runtime from assetserver if requested.
Add gin guide, fix asset server merge, add gin example
adding http.CloseNotifier and http.Flusher interface to assetserver.contentTypeSniffer, for Gin (and other framework) compatibility.
Copy link
Contributor

coderabbitai bot commented Mar 11, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This set of changes introduces comprehensive support for integrating the Gin web framework with Wails applications and services. It adds new examples demonstrating Gin usage for both routing and service management, including README documentation and updated Go module files. Enhancements to the asset server include a refactored contentTypeSniffer with a constructor and new methods for close notification and flushing. The Wails runtime's event emission API is updated for improved flexibility, and new routes for serving JavaScript assets are added. Documentation and changelogs are updated to reflect the new Gin integration and related features.

Changes

Files / Paths Change Summary
v3/internal/assetserver/assetserver.go, v3/internal/assetserver/assetserver_webview.go Refactored instantiation of contentTypeSniffer to use a new constructor function; updated variable declaration style in webview handler.
v3/internal/assetserver/content_type_sniffer.go Added newContentTypeSniffer constructor, new closeChannel field, and methods for close notification (CloseNotify), client closing (closeClient), and flushing (Flush) to contentTypeSniffer.
v3/internal/assetserver/bundledassets/runtime.js Renamed exported variables and functions (Wb, PD) affecting error handling and random string generation.
v3/internal/runtime/desktop/@wailsio/runtime/src/events.ts Changed Emit function signature to accept (name: string, data?: any) for more flexible event emission; updated internal logic accordingly.
v3/pkg/application/application.go Added a new route /wails/runtime.js to serve a JavaScript asset using assetserver.ServeFile; error handling for this route integrated into the application initialization.
v3/examples/gin-example/README.md, v3/examples/gin-routing/README.md, v3/examples/gin-service/README.md Added new README files explaining Gin integration examples, setup instructions, middleware usage, and frontend-backend communication.
v3/examples/gin-example/go.mod, v3/examples/gin-routing/go.mod, v3/examples/gin-service/go.mod Updated and added Go module files for Gin examples, specifying dependencies, Go versions, and local replace directives for Wails.
v3/examples/gin-example/main.go Broadened middleware route matching from exact /wails to any path with /wails prefix using strings.HasPrefix.
v3/examples/gin-example/static/index.html, v3/examples/gin-routing/static/index.html Enhanced frontend HTML examples with event emission and API call buttons; updated JavaScript to use ES module syntax and new event API.
v3/examples/gin-service/main.go Added a new main application file demonstrating Gin service integration with Wails, asset embedding, and event handling.
v3/examples/gin-service/services/gin_service.go Introduced a Gin-based service with user management (CRUD), event emission, and request logging; defined service lifecycle methods and HTTP handlers.
v3/examples/gin-service/assets/index.html Added UI and JavaScript for deleting users and handling "user-created" events, updating the frontend dynamically.
docs/src/content/docs/changelog.mdx, mkdocs-website/docs/en/changelog.md Added changelog entries documenting Gin support and related features, following Keep a Changelog conventions.
docs/src/content/docs/guides/gin-routing.mdx, docs/src/content/docs/guides/gin-services.mdx Updated guide titles and content to clarify Gin's use for routing and services, added prerequisites, new sections, and improved structure; introduced new API endpoints and frontend integration instructions.
v3/examples/events/assets/index.html Simplified event emission in frontend example to use new API signature (Emit('myevent', 'hello!')).

Sequence Diagram(s)

sequenceDiagram
    participant Frontend
    participant WailsRuntime
    participant GinEngine
    participant WailsBackend

    Frontend->>WailsRuntime: Emit('eventName', eventData)
    WailsRuntime->>WailsBackend: Receives event, processes or forwards as needed

    Frontend->>GinEngine: HTTP request to /api/endpoint
    GinEngine->>GinEngine: Middleware/route handling
    GinEngine->>WailsBackend: (Optional) Calls Wails service or emits event
    GinEngine-->>Frontend: JSON response

    WailsBackend->>Frontend: Emits event (e.g., "user-created")
    Frontend-->>Frontend: Updates UI in response
Loading

Possibly related PRs

  • [v3] Fix and optimise assetserver #4049: Improvements and fixes to the assetserver's content type sniffing and response handling, including enhancements to the contentTypeSniffer behavior and fallback response mechanisms.
  • Gin support #4128: Introduces Gin support and modifies the contentTypeSniffer instantiation and methods similarly to this PR, improving encapsulation and functionality.

Suggested labels

awaiting feedback

Poem

In a meadow of code, the Gin rabbits hop,
Routing and serving, they never do stop.
With sniffer refined and events flying free,
New guides and examples for all to see.
Users created, deleted with glee—
This warren of features is bunny-approved,
So hop in and try what Gin can do! 🥕

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f5e985 and 6344a8a.

📒 Files selected for processing (2)
  • docs/src/content/docs/changelog.mdx (1 hunks)
  • v3/pkg/application/application.go (2 hunks)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

cloudflare-workers-and-pages bot commented Mar 11, 2025

Deploying wails with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6344a8a
Status:⚡️  Build in progress...

View logs

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🔭 Outside diff range comments (2)
v3/examples/gin-service/assets/index.html (1)

217-249: ⚠️ Potential issue

Duplicated event handling code appears after the HTML closing tag.

There appears to be duplicated code after the closing HTML tag that should be removed. The duplicated section includes event listener setup that's already properly implemented in the script section.

-            
-            // Use the Wails runtime to emit an event - matching the format in the events demo
-            const eventData = {
-                message: "Hello from the frontend!",
-                timestamp: new Date().toISOString()
-            };
-            wails.Events.Emit({name: 'gin-api-event', data: eventData});
-        });
-        
-        // Set up event listener for responses from the backend
-        window.addEventListener('DOMContentLoaded', () => {
-            // Register event listener using Wails runtime
-            wails.Events.On("gin-api-response", (data) => {
-                document.getElementById('eventResponse').textContent = JSON.stringify(data, null, 2);
-            });
-            
-            // Also listen for user-created events
-            wails.Events.On("user-created", (data) => {
-                document.getElementById('eventResponse').textContent = JSON.stringify({
-                    event: "user-created",
-                    user: data
-                }, null, 2);
-            });
-            
-            // Initial API call to get service info
-            fetchAPI('/info');
-        });
-    </script>
-</body>
-</html>
v3/examples/gin-example/main.go (1)

110-114: ⚠️ Potential issue

Remove duplicate code

Lines 110-114 appear to be duplicating the error handling code from lines 105-108. These lines should be removed.

	// Run the app
	err := app.Run()
	if err != nil {
		log.Fatal(err)
	}
}
-	err := app.Run()
-	if err != nil {
-		log.Fatal(err)
-	}
-}
🧹 Nitpick comments (22)
mkdocs-website/docs/en/changelog.md (4)

20-37: "Added" Section Provides Comprehensive Details

The "### Added" section lists the new features along with GitHub references and contributor attributions. This level of detail enhances traceability. For consistency, consider reviewing punctuation uniformity among bullet points.


38-71: "Fixed" Section Thoroughly Documents Bug Resolutions

The "### Fixed" section captures a wide range of fixes in detail, correlating GitHub pull requests with each change. Although repeating "Fixed" at the beginning of each bullet point is consistent with changelog conventions, you might explore slight rewording in a few entries to enhance readability.

🧰 Tools
🪛 LanguageTool

[style] ~46-~46: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...github.com//pull/2972). - Fixed application frozen when quit (Darwin) b...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~49-~49: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...github.com//pull/2753). - Fixed hex values for arrow keys on Darwin by ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[grammar] ~54-~54: The operating system from Apple is written “macOS”.
Context: ... paths with spaces - @leaanthony. - Fix MacOS systray click handling when no attached...

(MAC_OS)


[grammar] ~56-~56: “Windows” (operating system by Microsoft) is a proper noun and needs to be capitalized.
Context: ...ailsapp/wails/pull/3208) - Fix crash on windows left clicking the systray icon when not...

(A_WINDOWS)


[grammar] ~56-~56: The verb “left-clicking” is spelled with a hyphen.
Context: ...wails/pull/3208) - Fix crash on windows left clicking the systray icon when not having an att...

(CLICK_HYPHEN)


54-54: Correct the Naming for macOS

The entry currently reads "Fix MacOS systray click handling..." Change "MacOS" to "macOS" to comply with standard naming conventions.

- - Fix MacOS systray click handling when no attached window by [thomas-senechal](https://github.com/thomas-senechal) in PR [#3207](https://github.com/wailsapp/wails/pull/3207)
+ - Fix macOS systray click handling when no attached window by [thomas-senechal](https://github.com/thomas-senechal) in PR [#3207](https://github.com/wailsapp/wails/pull/3207)
🧰 Tools
🪛 LanguageTool

[grammar] ~54-~54: The operating system from Apple is written “macOS”.
Context: ... paths with spaces - @leaanthony. - Fix MacOS systray click handling when no attached...

(MAC_OS)


56-56: Improve Capitalization and Hyphenation for Windows

In the entry "- Fix crash on windows left clicking the systray icon when not having an attached window...", update "windows" to "Windows" and change "left clicking" to "left-clicking" to maintain proper capitalization and readability.

- - Fix crash on windows left clicking the systray icon when not having an attached window [tw1nk](https://github.com/tw1nk) in PR [#3271](https://github.com/wailsapp/wails/pull/3271)
+ - Fix crash on Windows left-clicking the systray icon when not having an attached window [tw1nk](https://github.com/tw1nk) in PR [#3271](https://github.com/wailsapp/wails/pull/3271)
🧰 Tools
🪛 LanguageTool

[grammar] ~56-~56: “Windows” (operating system by Microsoft) is a proper noun and needs to be capitalized.
Context: ...ailsapp/wails/pull/3208) - Fix crash on windows left clicking the systray icon when not...

(A_WINDOWS)


[grammar] ~56-~56: The verb “left-clicking” is spelled with a hyphen.
Context: ...wails/pull/3208) - Fix crash on windows left clicking the systray icon when not having an att...

(CLICK_HYPHEN)

v3/examples/gin-routing/README.md (1)

1-27: Clear and Informative Documentation
This new README provides a concise overview and clear step-by-step instructions for using Gin as a router with Wails. As a minor nitpick, consider revising the list item “- Communicate between the Gin-served frontend and Wails backend” to “- Communicate between the Gin-served frontend and the Wails backend” for grammatical clarity.

v3/examples/gin-routing/static/index.html (1)

1-95: Well-Structured Integration Example with Minor Styling Suggestion
This HTML example effectively demonstrates the integration between Wails and Gin. The document layout clearly separates the event-triggering functionality and the API call example, and the inline JavaScript is well-organized with robust error handling. For improved maintainability in larger projects, consider externalizing the inline CSS into a dedicated stylesheet.

v3/examples/gin-example/README.md (1)

12-12: Minor grammatical suggestion.

Consider adding the preposition "to" in this line for better readability.

-Communicate between the Gin-served frontend and Wails backend
+Communicate between the Gin-served frontend and the Wails backend
🧰 Tools
🪛 LanguageTool

[uncategorized] ~12-~12: Possible missing preposition found.
Context: ...d Gin - Define API endpoints with Gin - Communicate between the Gin-served frontend and Wai...

(AI_HYDRA_LEO_MISSING_TO)

v3/examples/gin-routing/go.mod (1)

72-72: Document the replacement directive

The replacement directive points Wails to a local directory, which is appropriate for example code but should be documented in the README for clarity to users.

v3/examples/gin-routing/main.go (3)

32-53: Good logging middleware implementation

The LoggingMiddleware provides useful request logging including method, path, client IP, status, and latency. This helps with debugging and monitoring.

Consider enhancing the logging middleware with:

  1. Configurable log levels
  2. Request body size information
  3. Optional logging format selection (e.g., JSON for structured logging)
-func LoggingMiddleware() gin.HandlerFunc {
+func LoggingMiddleware(options ...LogOption) gin.HandlerFunc {
+	// Apply default options
+	opts := defaultLogOptions()
+	for _, opt := range options {
+		opt(opts)
+	}
+
	return func(c *gin.Context) {
		// Start timer
		startTime := time.Now()

		// Process request
		c.Next()

		// Calculate latency
		latency := time.Since(startTime)

+		// Skip logging if below minimum level
+		if opts.minLevel > LogLevelInfo {
+			return
+		}
+
		// Log request details
-		log.Printf("[GIN] %s | %s | %s | %d | %s",
-			c.Request.Method,
-			c.Request.URL.Path,
-			c.ClientIP(),
-			c.Writer.Status(),
-			latency,
-		)
+		if opts.jsonFormat {
+			// JSON formatted log
+			log.Printf(`{"level":"info","component":"gin","method":"%s","path":"%s","ip":"%s","status":%d,"latency":"%s","size":%d}`,
+				c.Request.Method, c.Request.URL.Path, c.ClientIP(), c.Writer.Status(), latency, c.Writer.Size())
+		} else {
+			// Plain text log
+			log.Printf("[GIN] %s | %s | %s | %d | %s | %d bytes",
+				c.Request.Method, c.Request.URL.Path, c.ClientIP(), c.Writer.Status(), latency, c.Writer.Size())
+		}
	}
}

68-74: Add better error handling for static file serving

While the current error handling returns a 500 error with a message, consider adding logging and more detailed error information for debugging purposes.

ginEngine.GET("/", func(c *gin.Context) {
	file, err := staticFiles.ReadFile("static/index.html")
	if err != nil {
+		log.Printf("ERROR: Failed to read index.html: %v", err)
		c.String(http.StatusInternalServerError, "Error reading index.html")
		return
	}
	c.Data(http.StatusOK, "text/html; charset=utf-8", file)
})

97-99: Consider enhancing event handling

The event handler implementation is straightforward but could be enhanced with more structured logging and response capabilities.

app.OnEvent("gin-button-clicked", func(event *application.CustomEvent) {
-	log.Printf("Received event from frontend: %v", event.Data)
+	log.Printf("Received event from frontend: %v, sending acknowledgment", event.Data)
+	// Send acknowledgment back to frontend
+	app.Events.EmitTo("", "event-received", map[string]interface{}{
+		"originalEvent": "gin-button-clicked",
+		"received":      time.Now().Format(time.RFC3339),
+	})
})
v3/examples/gin-service/go.mod (2)

6-7: Consider consistency in Gin version across examples

The gin-routing example uses Gin v1.9.1 while this example uses v1.10.0. For consistency across examples, consider using the same version unless there's a specific reason to use different versions.


74-74: Document the replacement directive

The replacement directive points Wails to a local directory, which is appropriate for example code but should be documented in the README for clarity to users.

v3/examples/gin-example/main.go (1)

61-68: Improve error handling when reading index.html

The current error handling simply returns a 500 error with a message. Consider logging the actual error for debugging purposes.

ginEngine.GET("/", func(c *gin.Context) {
	file, err := staticFiles.ReadFile("static/index.html")
	if err != nil {
+		log.Printf("Error reading index.html: %v", err)
		c.String(http.StatusInternalServerError, "Error reading index.html")
		return
	}
	c.Data(http.StatusOK, "text/html; charset=utf-8", file)
})
v3/internal/assetserver/content_type_sniffer.go (1)

120-134: Add documentation comments to explain the purpose of these methods

The implementation of CloseNotify, closeClient, and Flush methods is correct, but it would be helpful to add more detailed documentation comments to explain their purpose and usage.

// CloseNotify implements the http.CloseNotifier interface.
+// It returns a channel that receives a single value when the client connection has gone away.
+// This can be used to cancel long operations on the server if the client disconnects.
func (rw *contentTypeSniffer) CloseNotify() <-chan bool {
	return rw.closeChannel
}

+// closeClient sends a signal to the close channel to notify that the client connection has closed.
+// This is typically called when detecting a client disconnect.
func (rw *contentTypeSniffer) closeClient() {
	rw.closeChannel <- true
}

// Flush implements the http.Flusher interface.
+// It flushes buffered data to the client if the underlying response writer supports it.
+// This is useful for streaming responses or long-polling scenarios.
func (rw *contentTypeSniffer) Flush() {
	if f, ok := rw.rw.(http.Flusher); ok {
		f.Flush()
	}
}
docs/src/content/docs/guides/gin-routing.mdx (1)

317-320: Fix inconsistent event emission in example code

The example code uses ce.Events.Emit but other examples in the documentation use wails.Events.Emit. This could confuse users.

        document.getElementById('triggerEvent').addEventListener('click', () => {
-            ce.Events.Emit("my-event", { 
+            wails.Events.Emit({name: "my-event", data: { 
                message: "Hello from the frontend!",
                timestamp: new Date().toISOString() 
-            });
+            }});
        });
docs/src/content/docs/guides/gin.mdx (3)

34-47: Middleware Example Clarity

The GinMiddleware example clearly demonstrates how to delegate requests: allowing Wails to handle the /wails route while passing all other requests to Gin. One suggestion is to consider whether an exact match (== "/wails") best serves your use case or if a more flexible check using strings.HasPrefix(r.URL.Path, "/wails") might be more appropriate for handling sub-paths. This would align with the PR discussion about broader route matching in the actual implementation.


253-275: Build Tags and Environment Configuration

The documentation now includes examples using build tags to manage Gin’s mode based on the environment. Consider updating the build tag examples to include the modern //go:build syntax (in addition to or instead of // +build) for better compatibility with recent Go versions.


308-421: Comprehensive Integration Example

The main function example integrates Gin with Wails effectively. It demonstrates the creation of a Gin router, the registration of custom middleware (including the GinMiddleware), static file serving using embedded assets, route definition for both HTML content and an API endpoint, and event handling with app.OnEvent. One minor suggestion is to consider using strings.HasPrefix for the route check in the middleware to accommodate potential sub-paths beneath /wails if that aligns with your design goals.

v3/examples/gin-service/services/gin_service.go (3)

31-34: EventData struct should include documentation

Consider adding a comment to describe the purpose of the EventData struct and how it's used within the service. This would improve code clarity and documentation.

+// EventData represents the structure of event messages sent between frontend and backend
 type EventData struct {
 	Message   string `json:"message"`
 	Timestamp string `json:"timestamp"`
 }

165-186: Improve user deletion implementation

The current implementation has O(n) complexity and can be inefficient for large user lists. Also, the slice manipulation technique can potentially cause memory leaks by retaining references to removed users.

Consider using a more efficient approach:

 // Delete a user
 users.DELETE("/:id", func(c *gin.Context) {
 	id, err := strconv.Atoi(c.Param("id"))
 	if err != nil {
 		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
 		return
 	}

 	s.mu.Lock()
 	defer s.mu.Unlock()

-	for i, user := range s.users {
-		if user.ID == id {
-			// Remove the user from the slice
-			s.users = append(s.users[:i], s.users[i+1:]...)
-			c.JSON(http.StatusOK, gin.H{"message": "User deleted"})
-			return
-		}
-	}
+	found := false
+	newUsers := make([]User, 0, len(s.users)-1)
+	
+	for _, user := range s.users {
+		if user.ID == id {
+			found = true
+			continue
+		}
+		newUsers = append(newUsers, user)
+	}
+	
+	if found {
+		s.users = newUsers
+		c.JSON(http.StatusOK, gin.H{"message": "User deleted"})
+		return
+	}

 	c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
 })

161-163: Emit events after the mutex is unlocked

The event emission happens while the mutex is still locked, which could lead to unnecessary blocking, especially if event handling is slow.

Move the event emission after unlocking:

 	// Add to the users slice
 	s.users = append(s.users, newUser)

+	// Get a copy of the user for the event
+	userCopy := newUser
+
 	c.JSON(http.StatusCreated, newUser)
 
+	s.mu.Unlock()
+	
 	// Emit an event to notify about the new user
-	s.app.EmitEvent("user-created", newUser)
+	s.app.EmitEvent("user-created", userCopy)
+	
+	return
 })

Then remove the defer s.mu.Unlock() line from earlier in the function.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b10170 and d8671de.

⛔ Files ignored due to path filters (4)
  • v3/examples/gin-example/go.sum is excluded by !**/*.sum
  • v3/examples/gin-example/go.sum is excluded by !**/*.sum
  • v3/examples/gin-service/go.sum is excluded by !**/*.sum
  • v3/examples/gin-routing/go.sum is excluded by !**/*.sum
📒 Files selected for processing (35)
  • v3/internal/assetserver/assetserver.go (1 hunks)
  • v3/internal/assetserver/assetserver_webview.go (1 hunks)
  • v3/internal/assetserver/content_type_sniffer.go (2 hunks)
  • mkdocs-website/docs/en/changelog.md (1 hunks)
  • v3/examples/gin-example/README.md (1 hunks)
  • v3/examples/gin-example/go.mod (1 hunks)
  • v3/examples/gin-example/main.go (1 hunks)
  • v3/examples/gin-example/static/index.html (1 hunks)
  • docs/src/content/docs/guides/gin.mdx (1 hunks)
  • docs/src/content/docs/guides/gin.mdx (6 hunks)
  • v3/examples/gin-example/go.mod (1 hunks)
  • v3/examples/gin-example/main.go (2 hunks)
  • v3/examples/gin-example/static/index.html (1 hunks)
  • v3/internal/assetserver/assetserver_webview.go (1 hunks)
  • docs/src/content/docs/guides/gin-routing.mdx (2 hunks)
  • docs/src/content/docs/guides/gin-services.mdx (1 hunks)
  • v3/examples/gin-example/main.go (2 hunks)
  • v3/examples/gin-example/static/index.html (1 hunks)
  • v3/examples/gin-service/assets/index.html (1 hunks)
  • v3/examples/gin-service/go.mod (1 hunks)
  • v3/examples/gin-service/main.go (1 hunks)
  • v3/examples/gin-service/services/gin_service.go (1 hunks)
  • v3/pkg/application/application.go (2 hunks)
  • docs/src/content/docs/guides/gin-routing.mdx (1 hunks)
  • docs/src/content/docs/guides/gin-services.mdx (11 hunks)
  • v3/examples/events/assets/index.html (1 hunks)
  • v3/examples/gin-routing/README.md (1 hunks)
  • v3/examples/gin-routing/go.mod (1 hunks)
  • v3/examples/gin-routing/main.go (1 hunks)
  • v3/examples/gin-routing/static/index.html (1 hunks)
  • v3/examples/gin-service/README.md (1 hunks)
  • v3/examples/gin-service/assets/index.html (3 hunks)
  • v3/internal/assetserver/bundledassets/runtime.js (1 hunks)
  • v3/internal/runtime/desktop/@wailsio/runtime/src/events.ts (1 hunks)
  • docs/src/content/docs/changelog.mdx (1 hunks)
🧰 Additional context used
🪛 LanguageTool
v3/examples/gin-service/README.md

[uncategorized] ~12-~12: Possible missing preposition found.
Context: ...d Gin - Define API endpoints with Gin - Communicate between the Gin-served frontend and Wai...

(AI_HYDRA_LEO_MISSING_TO)

v3/examples/gin-example/README.md

[uncategorized] ~12-~12: Possible missing preposition found.
Context: ...d Gin - Define API endpoints with Gin - Communicate between the Gin-served frontend and Wai...

(AI_HYDRA_LEO_MISSING_TO)

mkdocs-website/docs/en/changelog.md

[style] ~46-~46: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...github.com//pull/2972). - Fixed application frozen when quit (Darwin) b...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~49-~49: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...github.com//pull/2753). - Fixed hex values for arrow keys on Darwin by ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[grammar] ~54-~54: The operating system from Apple is written “macOS”.
Context: ... paths with spaces - @leaanthony. - Fix MacOS systray click handling when no attached...

(MAC_OS)


[grammar] ~56-~56: “Windows” (operating system by Microsoft) is a proper noun and needs to be capitalized.
Context: ...ailsapp/wails/pull/3208) - Fix crash on windows left clicking the systray icon when not...

(A_WINDOWS)


[grammar] ~56-~56: The verb “left-clicking” is spelled with a hyphen.
Context: ...wails/pull/3208) - Fix crash on windows left clicking the systray icon when not having an att...

(CLICK_HYPHEN)

🪛 Biome (1.9.4)
v3/internal/assetserver/bundledassets/runtime.js

[error] 1-1: This array contains an empty slot.

Unsafe fix: Replace hole with undefined

(lint/suspicious/noSparseArray)


[error] 1-1: Shouldn't redeclare 'i'. Consider to delete it or rename it.

'i' is defined here:

(lint/suspicious/noRedeclare)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: Do not add then to a class.

(lint/suspicious/noThenProperty)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (go)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (45)
mkdocs-website/docs/en/changelog.md (6)

1-2: Changelog Header Looks Correct

The top-level header is clearly defined and adheres to our established changelog format.


3-16: Metadata and Format Comment Block is Informative

The introductory comment block detailing the changelog conventions provides clear context. This helps new contributors understand the format and requirements.


18-19: Unreleased Section Configured Properly

The use of the "## [Unreleased]" heading effectively distinguishes pending changes from released items.


72-82: "Changed" Section Clearly Outlines API and Runtime Updates

This section details the modifications to the bundled JS runtime, the changes in API exposure, and adjustments to the binding generator. The information is detailed and clear, which helps in understanding the scope of these changes.


83-83: Gin Support Enhancement Documented Effectively

The entry "- Modified the contentTypeSniffer struct to include the http.CloseNotifier interface. Now compatible with Gin framework." is succinct and clearly signals the Gin support update. This directly aligns with the PR’s objective.


85-90: Remaining Sections Appropriately Left Blank

The "Removed", "Deprecated", and "Security" sections are correctly empty, indicating there have been no removals, deprecations, or security fixes in this update.

v3/examples/events/assets/index.html (1)

12-12: Simplified Event Emission Syntax
The updated call wails.Events.Emit('myevent', 'hello!') aligns with the new API expectations and removes the previous object-based argument. Ensure that any event listeners are updated to expect two separate parameters rather than an object.

docs/src/content/docs/changelog.mdx (1)

78-79: Changelog Update for Gin Support
The changelog now includes a new entry for Gin support with proper attribution and PR reference. Please verify that all URLs and the PR identifiers match the intended documentation and that the attribution is consistent with earlier changelog conventions.

v3/internal/assetserver/assetserver.go (1)

62-62: Good refactoring to use a constructor function.

This change improves encapsulation by replacing a direct struct initialization with a constructor call. This pattern makes initialization more standardized and easier to extend in the future.

v3/internal/assetserver/assetserver_webview.go (1)

77-77: Good style improvement.

Using the := short variable declaration instead of explicit type declaration is more idiomatic Go and makes the code more concise while maintaining the same functionality.

v3/examples/gin-example/static/index.html (2)

44-50: Well-structured UI addition for Wails events demonstration.

The new card with button for triggering Wails events is a good addition to demonstrate the integration between Gin and Wails event system.


58-93: Good implementation of event handling.

The JavaScript code correctly:

  1. Uses ES module syntax to import Wails runtime
  2. Sets up event listeners in a structured way
  3. Includes proper error handling
  4. Updates the UI to reflect event emission success or failure

This provides a good example of how to integrate Wails events in a Gin-based application.

v3/examples/gin-service/main.go (1)

1-45: Well-structured example of Gin service integration.

This example correctly demonstrates:

  1. Setting up a Wails application with proper configuration
  2. Integrating a Gin service with route configuration
  3. Configuring asset handling
  4. Creating a webview window with appropriate parameters
  5. Including proper error handling for application execution

The structure follows best practices for Wails applications and provides a good template for users looking to integrate Gin services.

v3/pkg/application/application.go (2)

9-9: Good addition of the bundledassets import.

The new import provides access to the runtime.js file needed for the Gin integration.


102-106: Well implemented runtime.js route handling.

This new case in the switch statement properly serves the Wails runtime JavaScript file needed for Gin integration. The error handling is thorough, using the application's fatal error handling mechanism.

v3/examples/gin-example/README.md (1)

1-105: Well-structured Gin integration documentation.

This README clearly explains how to integrate the Gin web framework with Wails applications. The organization is logical, with sections for overview, running examples, and explanations of how the integration works. The code examples are clear and well-commented.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~12-~12: Possible missing preposition found.
Context: ...d Gin - Define API endpoints with Gin - Communicate between the Gin-served frontend and Wai...

(AI_HYDRA_LEO_MISSING_TO)

v3/examples/gin-service/assets/index.html (2)

110-216: Well-implemented frontend integration with the Gin service.

The JavaScript code effectively demonstrates interaction with the Gin API endpoints and proper use of the Wails runtime for event handling. The fetchAPI helper function, event listeners, and form handling follow good practices.


204-204: Updated event emission syntax using the new API.

This line correctly uses the new Events.Emit API format, which aligns with the changes made to the events.ts file in this PR.

v3/internal/runtime/desktop/@wailsio/runtime/src/events.ts (1)

127-145: Well-designed enhancement to the Emit function for improved flexibility.

The updated Emit function now provides a more flexible interface by supporting both the new parameter structure (name, data) and maintaining backward compatibility with the object-based approach. The type checking and conditional logic are well implemented.

v3/examples/gin-routing/go.mod (2)

6-8: LGTM: Dependencies are clearly defined

The direct dependencies on Gin and Wails are appropriately specified with version numbers.


3-3:

✅ Verification successful

Confirm Go version compatibility with users

Go 1.24.0 is a very recent version which may not be widely adopted yet. Consider documenting this requirement clearly or updating to a more widely adopted version like 1.22.x for better compatibility.


🏁 Script executed:

#!/bin/bash
# Check current stable Go version
curl -s https://go.dev/VERSION?m=text

Length of output: 76


Verified: Go version usage is appropriate.
The go 1.24.0 directive in v3/examples/gin-routing/go.mod aligns with the current stable release (observed as 1.24.1), so there is no immediate compatibility issue. However, to assist users who might be on older versions, it could be useful to document the minimum Go version requirement within the project’s documentation.

v3/internal/assetserver/bundledassets/runtime.js (2)

76-76: Variable naming changes in minified code

The renaming of variable W to b appears to be part of minification or code optimization. These changes shouldn't affect functionality as long as all references are updated consistently.


78-78:

❓ Verification inconclusive

Function renaming in minified code

The renaming of function P to D seems to be part of code optimization. Ensure all references to this function throughout the codebase have been updated to maintain consistency.


🏁 Script executed:

#!/bin/bash
# Check for any remaining references to function P that should be D
rg "function P\(" --type js

Length of output: 50514


Action Required: Verify Consistent Function Renaming

In the updated file v3/internal/assetserver/bundledassets/runtime.js, the renaming appears to be applied correctly without lingering references to the old function name P. However, our search shows that in v2/internal/frontend/runtime/runtime_prod_desktop.js there are still definitions and references using function P(. Please confirm whether these v2 implementations are legacy code not subject to the recent renaming or if they also require updates to use D for consistency across the entire codebase.

v3/examples/gin-routing/main.go (2)

17-30: Well-designed middleware for routing between Wails and Gin

The GinMiddleware implementation correctly routes requests between Wails and Gin based on path prefixes. This approach ensures that Wails-specific routes are handled by Wails while all other routes are handled by Gin.


91-93: Good integration of Gin with Wails assets

The approach of using Gin as both the asset handler and middleware is a clean way to integrate the frameworks. This makes routing seamless between Wails and Gin.

v3/examples/gin-service/go.mod (1)

3-3:

✅ Verification successful

Confirm Go version compatibility with users

Go 1.24.0 is a very recent version which may not be widely adopted yet. Consider documenting this requirement clearly or updating to a more widely adopted version like 1.22.x for better compatibility.


🏁 Script executed:

#!/bin/bash
# Check current stable Go version
curl -s https://go.dev/VERSION?m=text

Length of output: 76


Go Version Compatibility Confirmed

The go.mod file in v3/examples/gin-service specifies go 1.24.0, which aligns well with the latest stable release (1.24.1 as verified). Since Go 1.24.x is now standard, it's acceptable to use this version. However, please consider adding documentation (e.g., in the README) to explicitly state that the module requires Go 1.24.x to ensure users are aware of the minimum version requirement.

v3/internal/assetserver/content_type_sniffer.go (2)

7-12: Good implementation of the constructor

The constructor correctly initializes the struct with a response writer and a buffered channel for close notifications.


20-20: New field added correctly

The closeChannel field is properly added to the struct to support close notifications.

docs/src/content/docs/guides/gin-services.mdx (5)

8-16: Well-structured introduction and outline

The introduction clearly explains the purpose of integrating Gin with Wails, and the numbered list provides a good roadmap for the tutorial.


62-66: Good addition of EventData structure

The EventData type is well-defined and will be useful for structured event communication between frontend and backend.


230-251: Complete CRUD implementation with DELETE endpoint

The DELETE endpoint implementation is correct and includes proper error handling for invalid IDs and cases where the user is not found.


488-507: Comprehensive frontend implementation for user deletion

The implementation of the delete user functionality is thorough, including user prompting, error handling, and UI feedback.


389-404: Well-designed user creation form

The user creation form is well-structured with proper input fields, labels, and buttons for submission and cancellation.

docs/src/content/docs/guides/gin-routing.mdx (4)

32-46: Improved Wails route handling

Good update to use strings.HasPrefix(r.URL.Path, "/wails") instead of an exact path match. This correctly allows Wails to handle any routes under the "/wails" path, which is necessary for serving runtime files and handling events.


211-357: Excellent addition of event communication documentation

The event communication section is comprehensive and provides clear guidance on enabling event communication between the frontend and backend. The code examples are well-structured and include proper error handling.


229-266: Well-implemented GinService for serving Wails runtime

The GinService struct and ServeHTTP method correctly implement handling for the Wails runtime.js file. The serveWailsRuntime method properly serves the runtime file with appropriate content type headers.


274-297: Good implementation of event handling endpoint

The event handling endpoint is well-designed and correctly bridges HTTP requests to the Wails event system. The JSON binding and error handling are properly implemented.

docs/src/content/docs/guides/gin.mdx (4)

3-10: Header and Introduction Update

Changing the section header from "Overview" to "Introduction" is a clear improvement that refocuses the guide as an introductory resource. Please ensure that any cross-references in the documentation are updated accordingly.


49-50: Middleware Comment Addition

The additional comment explaining that "This middleware passes all HTTP requests to the Gin router" is a helpful summary. No further action is required unless you wish to elaborate on edge-case routing scenarios.


209-222: Event Handling Update

The revised event handler snippet now uses app.OnEvent("my-event", func(event *application.CustomEvent) { ... }) which correctly reflects the updated API. Ensure that any other parts of the documentation referencing the old app.Events.On syntax are similarly updated.


225-240: JavaScript API Example Improvement

The new JavaScript example demonstrating an API call to the /api/hello endpoint is well structured. The use of async/await, proper error handling, and clear DOM updates effectively communicates the intended functionality.

v3/examples/gin-service/services/gin_service.go (1)

190-220: Good implementation of logging middleware

The logging middleware is well implemented, capturing important request details and properly using the application logger. It includes status code, method, path, client IP and latency which are essential for monitoring and debugging.

v3/examples/gin-example/go.mod (3)

10-70: Security improvements from dependency updates

The updates to security-related packages like go-crypto, circl, and golang.org/x/crypto are beneficial as they likely include security fixes and improvements.


3-3:

❓ Verification inconclusive

Verify Go version compatibility with deployment targets

The Go version has been updated to 1.24.0, which is very recent. Make sure all development and deployment environments support this version before merging.


🌐 Web query:

When was Go 1.24.0 released? What's the current stable version of Go?

💡 Result:

Go 1.24.0 was released on February 11, 2025, as announced in the official release notes and developer communications[1][3][4][7]. The current stable version is Go 1.24.1, released on March 4, 2025, which includes security fixes for the net/http package and various bug fixes across the toolchain[2][5][6][10]. This follows Google's standard practice of maintaining two supported major releases, with Go 1.24 receiving updates until Go 1.26 is released[2][4].

Citations:


Action: Confirm Go version compatibility and consider aligning with the stable release

  • The go.mod file at v3/examples/gin-example/go.mod now specifies:
    go 1.24.0
    
  • Note that Go 1.24.0 was released on February 11, 2025, while the current stable release is Go 1.24.1 (released on March 4, 2025).
  • Please ensure that all development and deployment environments support Go 1.24.0, or consider updating to 1.24.1 if appropriate.

66-66:

❓ Verification inconclusive

Consider pinning to specific protobuf version

The update to google.golang.org/protobuf v1.33.0 is a significant version jump. Protobuf changes can sometimes affect serialization compatibility.


🌐 Web query:

Are there any breaking changes in google.golang.org/protobuf v1.33.0? What security fixes does it include?

💡 Result:

The google.golang.org/protobuf v1.33.0 release primarily addresses security vulnerabilities while introducing one notable compatibility issue with older dependencies. Here's a breakdown:

Security Fixes

CVE-2024-24786:

  • Vulnerability: The protojson.Unmarshal function could enter an infinite loop when unmarshaling invalid JSON inputs containing google.protobuf.Any values or when using UnmarshalOptions.DiscardUnknown[1][6][7].
  • Resolution: Unmarshaling now returns an error instead of looping indefinitely[1][6].

Compatibility Considerations

  1. Breaking Change with Older Protobuf Modules:
    v1.33.0 introduced incompatibility with the deprecated github.com/golang/protobuf module. Users of the older module must update to github.com/golang/protobuf v1.5.4 to resolve this[2][5].

  2. Reflection API Stability:
    While not directly breaking, the release emphasizes that internal implementation changes (e.g., reflection-based JSON/text serialization) may affect code relying on undocumented behavior[9][11].


Recommendations

  • Update to v1.33.0 immediately if using protojson with untrusted inputs.
  • Migrate from github.com/golang/protobuf to google.golang.org/protobuf where possible[5].
  • Verify compatibility with downstream dependencies (e.g., etcd, heimdall) that might require updates[10][14].

This release balances critical security fixes with minimal breaking changes, primarily affecting legacy integration scenarios.

Citations:


Action Required: Verify and Pin Protobuf Dependency Version

The update to google.golang.org/protobuf v1.33.0 brings important security fixes—most notably, it resolves CVE‑2024‑24786 by preventing infinite loops in protojson.Unmarshal. However, it also introduces a breaking change with respect to the deprecated github.com/golang/protobuf module. This could lead to compatibility issues if any parts of the codebase or downstream dependencies still expect the older API behavior.

  • Review Dependency Compatibility: Ensure that no part of the project still relies on github.com/golang/protobuf. If so, confirm these dependencies are updated or managed appropriately.
  • Pinning Recommendation: Consider explicitly pinning the protobuf dependency in go.mod to avoid accidental version bumps that might reintroduce compatibility issues.
  • Check Internal API Usage: Verify that any internal implementations relying on undocumented reflection or serialization behaviors are not inadvertently affected by the changes in v1.33.0.

Comment on lines +17 to +24
// GinMiddleware creates a middleware that passes requests to Gin if they're not handled by Wails
func GinMiddleware(ginEngine *gin.Engine) application.Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Let Wails handle the `/wails` route
if strings.HasPrefix(r.URL.Path, "/wails") {
next.ServeHTTP(w, r)
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug in GinMiddleware: All requests are being passed to Gin

The current implementation passes all requests directly to Gin without first checking if Wails should handle them. This will prevent Wails from serving its runtime files at /wails/runtime.js, which is necessary for frontend/backend communication.

Update the middleware to check for Wails routes first:

func GinMiddleware(ginEngine *gin.Engine) application.Middleware {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			// Let Wails handle the `/wails` route
+			if strings.HasPrefix(r.URL.Path, "/wails") {
+				next.ServeHTTP(w, r)
+				return
+			}
			// Let Gin handle everything else
			ginEngine.ServeHTTP(w, r)
		})
	}
}

Don't forget to add the import:

import (
	"embed"
	"log"
	"net/http"
+	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/wailsapp/wails/v3/pkg/application"
)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// GinMiddleware creates a middleware that passes requests to Gin if they're not handled by Wails
func GinMiddleware(ginEngine *gin.Engine) application.Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Let Wails handle the `/wails` route
if strings.HasPrefix(r.URL.Path, "/wails") {
next.ServeHTTP(w, r)
return
// --- Updated Import Block ---
import (
"embed"
"log"
"net/http"
"strings" // Added import for strings
"time"
"github.com/gin-gonic/gin"
"github.com/wailsapp/wails/v3/pkg/application"
)
// --- Updated GinMiddleware Function ---
func GinMiddleware(ginEngine *gin.Engine) application.Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Let Wails handle the `/wails` route
if strings.HasPrefix(r.URL.Path, "/wails") {
next.ServeHTTP(w, r)
return
}
// Let Gin handle everything else
ginEngine.ServeHTTP(w, r)
})
}
}

Comment on lines +67 to +85
func (s *GinService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
// You can access the application instance via ctx
s.app = application.Get()

// Register an event handler that can be triggered from the frontend
s.app.OnEvent("gin-api-event", func(event *application.CustomEvent) {
// Log the event data
// Parse the event data
s.app.Logger.Info("Received event from frontend", "data", event.Data)

// You could also emit an event back to the frontend
s.app.EmitEvent("gin-api-response", map[string]interface{}{
"message": "Response from Gin API Service",
"time": time.Now().Format(time.RFC3339),
})
})

return nil
}
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

The app field is accessed in routes before being initialized

The app field is only initialized in ServiceStartup but is used in setupRoutes (called during NewGinService). If ServeHTTP is called before ServiceStartup, the app reference could be nil when the user creation route is accessed.

Consider refactoring initialization to ensure the app is available when needed:

 func NewGinService() *GinService {
 	// Create a new Gin router
 	ginEngine := gin.New()

 	// Add middlewares
 	ginEngine.Use(gin.Recovery())
 	ginEngine.Use(LoggingMiddleware())

 	service := &GinService{
 		ginEngine: ginEngine,
 		users: []User{
 			{ID: 1, Name: "Alice", Email: "[email protected]", CreatedAt: time.Now().Add(-72 * time.Hour)},
 			{ID: 2, Name: "Bob", Email: "[email protected]", CreatedAt: time.Now().Add(-48 * time.Hour)},
 			{ID: 3, Name: "Charlie", Email: "[email protected]", CreatedAt: time.Now().Add(-24 * time.Hour)},
 		},
 		nextID: 4,
+		app: application.Get(),
 	}

 	// Define routes
 	service.setupRoutes()

 	return service
 }

Then update ServiceStartup accordingly:

 // ServiceStartup is called when the service starts
 func (s *GinService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
-	// You can access the application instance via ctx
-	s.app = application.Get()
+	// Verify we have access to the application
+	if s.app == nil {
+		s.app = application.Get()
+	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (s *GinService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
// You can access the application instance via ctx
s.app = application.Get()
// Register an event handler that can be triggered from the frontend
s.app.OnEvent("gin-api-event", func(event *application.CustomEvent) {
// Log the event data
// Parse the event data
s.app.Logger.Info("Received event from frontend", "data", event.Data)
// You could also emit an event back to the frontend
s.app.EmitEvent("gin-api-response", map[string]interface{}{
"message": "Response from Gin API Service",
"time": time.Now().Format(time.RFC3339),
})
})
return nil
}
// NewGinService initializes a new GinService instance
func NewGinService() *GinService {
// Create a new Gin router
ginEngine := gin.New()
// Add middlewares
ginEngine.Use(gin.Recovery())
ginEngine.Use(LoggingMiddleware())
service := &GinService{
ginEngine: ginEngine,
users: []User{
{ID: 1, Name: "Alice", Email: "[email protected]", CreatedAt: time.Now().Add(-72 * time.Hour)},
{ID: 2, Name: "Bob", Email: "[email protected]", CreatedAt: time.Now().Add(-48 * time.Hour)},
{ID: 3, Name: "Charlie", Email: "[email protected]", CreatedAt: time.Now().Add(-24 * time.Hour)},
},
nextID: 4,
app: application.Get(), // Initialize the app to ensure it's available in routes
}
// Define routes
service.setupRoutes()
return service
}
Suggested change
func (s *GinService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
// You can access the application instance via ctx
s.app = application.Get()
// Register an event handler that can be triggered from the frontend
s.app.OnEvent("gin-api-event", func(event *application.CustomEvent) {
// Log the event data
// Parse the event data
s.app.Logger.Info("Received event from frontend", "data", event.Data)
// You could also emit an event back to the frontend
s.app.EmitEvent("gin-api-response", map[string]interface{}{
"message": "Response from Gin API Service",
"time": time.Now().Format(time.RFC3339),
})
})
return nil
}
// ServiceStartup is called when the service starts
func (s *GinService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
// Verify we have access to the application
if s.app == nil {
s.app = application.Get()
}
// Register an event handler that can be triggered from the frontend
s.app.OnEvent("gin-api-event", func(event *application.CustomEvent) {
// Log the event data
// Parse the event data
s.app.Logger.Info("Received event from frontend", "data", event.Data)
// You could also emit an event back to the frontend
s.app.EmitEvent("gin-api-response", map[string]interface{}{
"message": "Response from Gin API Service",
"time": time.Now().Format(time.RFC3339),
})
})
return nil
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not required

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leaanthony Understood! I'll note that this initialization pattern is acceptable for Wails services.

(_/)
(^.^)
(> <)


✏️ Learnings added
Learnt from: leaanthony
PR: wailsapp/wails#4128
File: v3/examples/gin-service/services/gin_service.go:67-85
Timestamp: 2025-04-18T05:57:34.702Z
Learning: In Wails services (like GinService), initializing the app field in ServiceStartup rather than in the constructor is an acceptable pattern, as ServiceStartup is guaranteed to be called before any HTTP requests are handled.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

leaanthony and others added 2 commits April 18, 2025 15:47
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
v3/examples/gin-service/services/gin_service.go (2)

45-53: ⚠️ Potential issue

app may be nil when routes are hit – initialise earlier

NewGinService returns a service that is immediately mounted as an http.Handler.
If the browser calls an endpoint before ServiceStartup is executed, s.app is still nil and EmitEvent (line 189) will panic.

Guard against this by initialising app up‑front:

 service := &GinService{
     ginEngine: ginEngine,
     users: []User{ … },
     nextID: 4,
-}
+    app: application.Get(),   // safe even in tests
+}

and/or add a nil‑check before emitting events.
This matches the concern raised in the previous review.


3-12: ⚠️ Potential issue

Missing strings import will break compilation

strings.Contains is used in the Create User handler (see lines 170‑172) but the symbol is not imported in the main import block.
Add it here (and keep imports sorted by goimports):

 import (
 	"context"
 	"net/http"
 	"strconv"
+	"strings"
 	"sync"
 	"time"

 	"github.com/gin-gonic/gin"
 	"github.com/wailsapp/wails/v3/pkg/application"
 )
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e97c390 and 1f5e985.

📒 Files selected for processing (1)
  • v3/examples/gin-service/services/gin_service.go (1 hunks)
🧰 Additional context used
🪛 golangci-lint (1.64.8)
v3/examples/gin-service/services/gin_service.go

141-141: expected statement, found 'import'

(typecheck)


190-190: expected statement, found ')'

(typecheck)


213-213: expected declaration, found ')'

(typecheck)

⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: CodeQL
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
  • GitHub Check: Cloudflare Pages

Comment on lines +188 to +190
// Emit an event to notify about the new user
s.app.EmitEvent("user-created", newUser)
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Prevent panic when emitting the “user-created” event

Even with the earlier initialisation fix, adding a nil‑check makes the handler more robust and test‑friendly:

-	s.app.EmitEvent("user-created", newUser)
+	if s.app != nil {
+		s.app.EmitEvent("user-created", newUser)
+	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Emit an event to notify about the new user
s.app.EmitEvent("user-created", newUser)
})
// Emit an event to notify about the new user
if s.app != nil {
s.app.EmitEvent("user-created", newUser)
}
})
🧰 Tools
🪛 golangci-lint (1.64.8)

190-190: expected statement, found ')'

(typecheck)

Comment on lines +140 to +150
// import block (ensure this exists in your file)
import (
"context"
"net/http"
"strconv"
"strings"
"sync"
"time"
)

// ...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Embedded import block inside a function → syntactically invalid Go

These lines are left‑over from an earlier suggestion and sit inside setupRoutes, producing the expected statement, found 'import' error reported by golangci‑lint.

-// import block (ensure this exists in your file)
-import (
-	"context"
-	"net/http"
-	"strconv"
-	"strings"
-	"sync"
-	"time"
-)
-
-// ...
+// (removed obsolete embedded import block)

Remove the entire block; the proper imports already exist at the top of the file.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// import block (ensure this exists in your file)
import (
"context"
"net/http"
"strconv"
"strings"
"sync"
"time"
)
// ...
// (removed obsolete embedded import block)
// ...
🧰 Tools
🪛 golangci-lint (1.64.8)

141-141: expected statement, found 'import'

(typecheck)

@leaanthony leaanthony merged commit b80ec34 into v3-alpha Apr 18, 2025
3 of 7 checks passed
@leaanthony leaanthony deleted the v3-alpha-bugfix/gin-support branch April 18, 2025 05:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants