• With issues:
  • Use the search tool before opening a new issue.
  • Please provide source code and commit sha if you found a bug.
  • Review existing issues and provide feedback or react to them.

Description

I want to use the prefix tree of Gin now. I hope to register a DINGEVENT method and build a prefix tree for this method at the same time. This step is no problem, and the following code can be used:

type MyRouterGroup struct {
    RouterGroup *gin.RouterGroup
}

func (group *MyRouterGroup) DingEvent(event_url string, handlerFunc gin.HandlerFunc) {
    group.RouterGroup.Handle("DINGEVENT", event_url, handlerFunc)
}

However, I have no way to enter this routing tree (unless I modify the Gin source code), because only when an HTTP request is sent, will it be matched in the routing tree.

Is there a custom method that allows me to match the routing tree like processing HTTP requests?

Environment

  • go version: 1.21
  • gin version (or commit ref): 1.8
  • operating system: Mac

Comment From: ljluestc


package main

import (
    "fmt"
    "net/http"
    "strings"

    "github.com/gin-gonic/gin"
)

type MyRouterGroup struct {
    RouterGroup *gin.RouterGroup
    routes      map[string]gin.HandlerFunc // Custom routing tree for DINGEVENT
}

// NewMyRouterGroup creates a new MyRouterGroup instance
func NewMyRouterGroup(router *gin.Engine, prefix string) *MyRouterGroup {
    return &MyRouterGroup{
        RouterGroup: router.Group(prefix),
        routes:      make(map[string]gin.HandlerFunc),
    }
}

// DingEvent registers a new DINGEVENT route
func (group *MyRouterGroup) DingEvent(eventURL string, handlerFunc gin.HandlerFunc) {
    // Add the route to the custom routing tree
    group.routes[eventURL] = handlerFunc

    // Optionally: Register with Gin for debugging or future use
    group.RouterGroup.Handle("DINGEVENT", eventURL, handlerFunc)
}

// MatchDingEvent allows manual matching of a DINGEVENT route
func (group *MyRouterGroup) MatchDingEvent(eventURL string) (gin.HandlerFunc, bool) {
    // Match the route in the custom routing tree
    handler, exists := group.routes[eventURL]
    return handler, exists
}

func main() {
    router := gin.Default()

    // Create a custom router group
    myGroup := NewMyRouterGroup(router, "/api")

    // Register a DINGEVENT route
    myGroup.DingEvent("/ding", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{"message": "Ding Event Triggered"})
    })

    // Add an HTTP endpoint to trigger a DINGEVENT manually
    router.GET("/trigger-ding/:path", func(c *gin.Context) {
        // Extract the event path
        eventPath := fmt.Sprintf("/%s", strings.TrimPrefix(c.Param("path"), "/"))

        // Match the DINGEVENT route
        if handler, exists := myGroup.MatchDingEvent(eventPath); exists {
            // Create a new Gin context to invoke the handler
            context := &gin.Context{
                Writer:  c.Writer,
                Request: c.Request,
            }
            handler(context) // Call the matched handler
        } else {
            c.JSON(http.StatusNotFound, gin.H{"error": "Ding Event Not Found"})
        }
    })

    // Start the server
    router.Run(":8080")
}