How can i remove route ? online!!!

Comment From: appleboy

Why ? What is your scenario?

Comment From: monikaYZ

i need to remove the routes online and add the routing rules online

Comment From: widnyana

@monikaYZ did you mean altering your application routes on-the-fly?

Comment From: monikaYZ

and I did not find the corresponding method。

Comment From: monikaYZ

@widnyana Yes!

Comment From: widnyana

@monikaYZ I'm afraid you can't do that. since your app source code are compiled to binary. you need to alter your source code, recompile, and deploy it again.

Comment From: widnyana

pardon me if I miss-interpret your question.

Comment From: monikaYZ

I need to do a configuration service, and configure memory

Comment From: cch123

if your service runs behind nginx, maybe you can alter nginx config to set api online/offline

Comment From: metalmatze

You really should try to write a more verbose description for this issue before hand. Nevertheless I think that a simple middleware might be what you're looking for. Then just wrap the routes with the middleware and check if active/inactive before going to the actual route.

Comment From: javierprovecho

@monikaYZ I understand what you mean.

He means to inject/remove dynamic handlers into Gin router. Although is possible to inject them after starting the server, there is no API for removing them. There may be some concurrency problems if you change the gin.Engine from different goroutines.

I'm also facing that problem, and developing a custom solution which I'll post to https://github.com/gin-contrib/graceful when ready.

I'll keep this issue open until then.

Comment From: bonjefir

Hi there

I have multiple devices which each one after registration get a token(hash string) and uses that in order to communicate with server. So I need to add/remove routes when a token add/remove from system...

Again, is it possible to add/remove routes at runtime?

Thanks in advance

Comment From: nhu-duong

Hi @bonjefir, More devices doesn’t mean you need one route for each of them. You can send token as parameter in post data or request header. Hope this helps.

Comment From: john8329

Similar use case here, I would like to attach routing subtrees in order to make entire sections available or unavailable dynamically. Restarting the http handler is not a problem.

Comment From: YiuTerran

same problem. I don't know which url should be route before i load config from cloud; and if cloud config changes, i need remove/add router on the fly. Now, i can just enable all router but return 404 when config changed.

Comment From: xiaolonggezte

same problem. it is perfect that gin supports altering handler in the routeTree.for dynamicly reloading handler.

Comment From: pi314pi

I need the feature, also.

Comment From: hantmac

Nginx CAN do this more conveniently. If your app are running on production, add/remove routes in your code at runtime is danger.

Comment From: john8329

Unless you need to load application modules and join them to a single API. But I found that creating generic endpoints and then manually using a forked version of httprouter to match the loaded ones works best, so this is not a problem for me anymore.

Comment From: binbin0325

I need the feature, also.

Comment From: wudi

Here is the way to implement change routes dynamically by change the whole handler.

https://gist.github.com/wudi/eb778531ff83ee1273f58aa7ddb353fe

Comment From: mirusky

I added the following in gin.go:

// Remove ...
func (engine *Engine) Remove(path string, tbRemoved HandlerFunc) {
    for _, tree := range engine.trees {
        for i, children := range tree.root.children {
            for _, h := range children.handlers {
                if reflect.ValueOf(h) == reflect.ValueOf(tbRemoved) && children.path == path {
                    tree.root.children = remove(tree.root.children, i)
                }
            }
        }
    }
}

func remove(s []*node, index int) []*node {
    return append(s[:index], s[index+1:]...)
}

Is totally unsafe and causes panicrecovery but works ...

Comment From: miyazawatomoka

Also need this. My scenario is use gin as api gateway, so need change routes

Comment From: mirusky

I'm currently using this solution described in fiber

Edit: I've been searching a lot in web routers frameworks, but the most similar as I need has some problems with this feature because it's unsafe... You could use fiber solution if it's enough, but if you really need add/remove routes on-the-fly I strongly recommend Iris

Comment From: jiankunking

you can reset gin.Engine and *http.Server

Comment From: wangpengcheng

Maybe you can use the method of directly reloading the router

package main

import (
    "fmt"
    "log"
    "net/http"
    "sync/atomic"
    "time"

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

type APP struct {
    globalRouter atomic.Pointer[gin.Engine]
}

func (app *APP) ReloadRouter(r *gin.Engine) {
    app.globalRouter.Store(r)
}

func (app *APP) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    router := app.globalRouter.Load()
    if router != nil {
        router.ServeHTTP(w, r)
    } else {
        w.WriteHeader(http.StatusInternalServerError)
    }
}

func main() {
    // global router
    globalAPP := APP{}
    // test handle creator
    newTestHandle := func(index int) gin.HandlerFunc {
        return func(c *gin.Context) {
            c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("Hello, %d", index)})

        }
    }
    // new router creater
    newRouter := func(handleMap map[string]gin.HandlerFunc) *gin.Engine {
        r := gin.Default()
        for path, handle := range handleMap {
            r.Handle(http.MethodGet, path, handle)
        }
        return r
    }
    // create old router
    oldRouter := newRouter(map[string]gin.HandlerFunc{
        "test1": newTestHandle(1),
        "test2": newTestHandle(2),
    })

    globalAPP.ReloadRouter(oldRouter)
    go func() {
        // change router 20 second
        time.Sleep(20 * time.Second)
        newRouter := newRouter(map[string]gin.HandlerFunc{
            "test1": newTestHandle(3),
        })
        globalAPP.ReloadRouter(newRouter)
    }()
    // create http server
    srv := &http.Server{
        Addr:    ":8080",
        Handler: &globalAPP,
    }
    if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
        log.Fatalf("listen: %s\n", err)
    }
}

with curl test curl http://127.0.0.1:8080/test2, result:

[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /test1                    --> main.main.main.func1.func4 (3 handlers)
[GIN-debug] GET    /test2                    --> main.main.main.func1.func5 (3 handlers)
[GIN] 2024/09/26 - 21:59:58 | 200 |      44.611µs |       127.0.0.1 | GET      "/test1"
[GIN] 2024/09/26 - 22:00:04 | 200 |      32.793µs |       127.0.0.1 | GET      "/test2"
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /test1                    --> main.main.func3.main.func1.1 (3 handlers)
[GIN] 2024/09/26 - 22:00:16 | 404 |         639ns |       127.0.0.1 | GET      "/test2"
[GIN] 2024/09/26 - 22:04:26 | 404 |         481ns |       127.0.0.1 | GET      "/test2"

Comment From: jiankunking

This method can be implemented https://jiankunking.com/a-way-to-implement-gateway.html