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