263 lines
7.3 KiB
Text
263 lines
7.3 KiB
Text
---
|
|
title: Using Gin for Routing
|
|
description: A comprehensive guide to integrating Gin web framework with Wails v3 applications
|
|
---
|
|
|
|
This guide demonstrates how to integrate the [Gin web framework](https://github.com/gin-gonic/gin) with Wails v3. Gin is a high-performance HTTP web framework written in Go that makes it easy to build web applications and APIs.
|
|
|
|
## Introduction
|
|
|
|
Wails v3 provides a flexible asset system that allows you to use any HTTP handler, including popular web frameworks like Gin. This integration enables you to:
|
|
|
|
- Serve web content using Gin's routing and middleware
|
|
- Create RESTful APIs accessible from your Wails application
|
|
- Use Gin's features while maintaining Wails desktop integration
|
|
|
|
## Setting Up Gin with Wails
|
|
|
|
To integrate Gin with Wails, you need to create a Gin router and configure it as the asset handler in your Wails application. Here's a step-by-step guide:
|
|
|
|
### 1. Install Dependencies
|
|
|
|
First, ensure you have the Gin package installed:
|
|
|
|
```bash
|
|
go get -u github.com/gin-gonic/gin
|
|
```
|
|
|
|
### 2. Create a Middleware for Gin
|
|
|
|
Create a middleware function that will handle the integration between Wails and Gin:
|
|
|
|
```go
|
|
// 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
|
|
}
|
|
// Let Gin handle everything else
|
|
ginEngine.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
}
|
|
```
|
|
|
|
This middleware passes all HTTP requests to the Gin router.
|
|
|
|
### 3. Configure Your Gin Router
|
|
|
|
Set up your Gin router with routes, middlewares, and handlers:
|
|
|
|
```go
|
|
// Create a new Gin router
|
|
ginEngine := gin.New() // Using New() instead of Default() to add custom middleware
|
|
|
|
// Add middlewares
|
|
ginEngine.Use(gin.Recovery())
|
|
ginEngine.Use(LoggingMiddleware()) // Your custom middleware
|
|
|
|
// Define routes
|
|
ginEngine.GET("/", func(c *gin.Context) {
|
|
// Serve your main page
|
|
})
|
|
|
|
ginEngine.GET("/api/hello", func(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"message": "Hello from Gin API!",
|
|
"time": time.Now().Format(time.RFC3339),
|
|
})
|
|
})
|
|
```
|
|
|
|
### 4. Integrate with Wails Application
|
|
|
|
Configure your Wails application to use the Gin router as its asset handler:
|
|
|
|
```go
|
|
// Create a new Wails application
|
|
app := application.New(application.Options{
|
|
Name: "Gin Example",
|
|
Description: "A demo of using Gin with Wails",
|
|
Mac: application.MacOptions{
|
|
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
|
},
|
|
Assets: application.AssetOptions{
|
|
Handler: ginEngine,
|
|
Middleware: GinMiddleware(ginEngine),
|
|
},
|
|
})
|
|
|
|
// Create window
|
|
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
|
Title: "Wails + Gin Example",
|
|
Width: 900,
|
|
Height: 700,
|
|
URL: "/", // This will load the route handled by Gin
|
|
})
|
|
```
|
|
|
|
## Serving Static Content
|
|
|
|
Use Go's `embed` package to embed static files into your binary:
|
|
|
|
```go
|
|
//go:embed static
|
|
var staticFiles embed.FS
|
|
|
|
ginEngine.StaticFS("/static", http.FS(staticFiles))
|
|
ginEngine.GET("/", func(c *gin.Context) {
|
|
file, _ := staticFiles.ReadFile("static/index.html")
|
|
c.Data(http.StatusOK, "text/html; charset=utf-8", file)
|
|
})
|
|
```
|
|
|
|
For development, serve files directly from disk using `ginEngine.Static("/static", "./static")`.
|
|
|
|
## Custom Middleware
|
|
|
|
Gin allows you to create custom middleware for various purposes. Here's an example of a logging middleware:
|
|
|
|
```go
|
|
// LoggingMiddleware is a Gin middleware that logs request details
|
|
func LoggingMiddleware() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
// Start timer
|
|
startTime := time.Now()
|
|
|
|
// Process request
|
|
c.Next()
|
|
|
|
// Calculate latency
|
|
latency := time.Since(startTime)
|
|
|
|
// Log request details
|
|
log.Printf("[GIN] %s | %s | %s | %d | %s",
|
|
c.Request.Method,
|
|
c.Request.URL.Path,
|
|
c.ClientIP(),
|
|
c.Writer.Status(),
|
|
latency,
|
|
)
|
|
}
|
|
}
|
|
```
|
|
|
|
## Handling API Requests
|
|
|
|
Gin makes it easy to create RESTful APIs. Here's how to define API endpoints:
|
|
|
|
```go
|
|
// GET endpoint
|
|
ginEngine.GET("/api/users", func(c *gin.Context) {
|
|
c.JSON(http.StatusOK, users)
|
|
})
|
|
|
|
// POST endpoint with JSON binding
|
|
ginEngine.POST("/api/users", func(c *gin.Context) {
|
|
var newUser User
|
|
if err := c.ShouldBindJSON(&newUser); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
// Process the new user...
|
|
c.JSON(http.StatusCreated, newUser)
|
|
})
|
|
|
|
// Path parameters
|
|
ginEngine.GET("/api/users/:id", func(c *gin.Context) {
|
|
id := c.Param("id")
|
|
// Find user by ID...
|
|
c.JSON(http.StatusOK, user)
|
|
})
|
|
|
|
// Query parameters
|
|
ginEngine.GET("/api/search", func(c *gin.Context) {
|
|
query := c.DefaultQuery("q", "")
|
|
limit := c.DefaultQuery("limit", "10")
|
|
// Perform search...
|
|
c.JSON(http.StatusOK, results)
|
|
})
|
|
```
|
|
|
|
## Using Wails Features
|
|
|
|
Your Gin-served web content can interact with Wails features using the `@wailsio/runtime` package.
|
|
|
|
### Event Handling
|
|
|
|
Register event handlers in Go:
|
|
|
|
```go
|
|
app.Event.On("my-event", func(event *application.CustomEvent) {
|
|
log.Printf("Received event: %v", event.Data)
|
|
})
|
|
```
|
|
|
|
Call from JavaScript using the runtime:
|
|
|
|
```html
|
|
<script type="module">
|
|
import { Events } from '@wailsio/runtime';
|
|
|
|
Events.Emit("my-event", { message: "Hello from frontend" });
|
|
Events.On("response-event", (data) => console.log(data));
|
|
</script>
|
|
```
|
|
|
|
## Advanced Configuration
|
|
|
|
### Customising Gin's Mode
|
|
|
|
Set Gin to release mode for production:
|
|
|
|
```go
|
|
gin.SetMode(gin.ReleaseMode) // Use gin.DebugMode for development
|
|
ginEngine := gin.New()
|
|
```
|
|
|
|
### Handling WebSockets
|
|
|
|
You can integrate WebSockets with Gin using libraries like Gorilla WebSocket:
|
|
|
|
```go
|
|
import "github.com/gorilla/websocket"
|
|
|
|
var upgrader = websocket.Upgrader{
|
|
ReadBufferSize: 1024,
|
|
WriteBufferSize: 1024,
|
|
CheckOrigin: func(r *http.Request) bool {
|
|
return true // Allow all connections
|
|
},
|
|
}
|
|
|
|
// In your route handler:
|
|
ginEngine.GET("/ws", func(c *gin.Context) {
|
|
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
|
if err != nil {
|
|
log.Println(err)
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
|
|
// Handle WebSocket connection...
|
|
})
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
- **Use Go's embed Package:** Embed static files into your binary for better distribution.
|
|
- **Separate Concerns:** Keep your API logic separate from your UI logic.
|
|
- **Error Handling:** Implement proper error handling in both Gin routes and frontend code.
|
|
- **Security:** Be mindful of security considerations, especially when handling user input.
|
|
- **Performance:** Use Gin's release mode in production for better performance.
|
|
- **Testing:** Write tests for your Gin routes using Gin's testing utilities.
|
|
|
|
## Conclusion
|
|
|
|
Integrating Gin with Wails provides a powerful combination for building desktop applications with web technologies. Gin's performance and feature set complement Wails' desktop integration capabilities, allowing you to create sophisticated applications that use the best of both worlds.
|
|
|
|
For more information, refer to the [Gin documentation](https://github.com/gin-gonic/gin) and the [Wails documentation](https://wails.io).
|