Skip to content
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

How remove route ? online!!! #776

Open
monikaYZ opened this issue Dec 29, 2016 · 26 comments
Open

How remove route ? online!!! #776

monikaYZ opened this issue Dec 29, 2016 · 26 comments
Assignees
Labels

Comments

@monikaYZ
Copy link

How can i remove route ? online!!!

@appleboy
Copy link
Member

Why ? What is your scenario?

@monikaYZ
Copy link
Author

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

@widnyana
Copy link

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

@monikaYZ
Copy link
Author

and I did not find the corresponding method。

@monikaYZ
Copy link
Author

@widnyana Yes!

@widnyana
Copy link

@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.

@widnyana
Copy link

pardon me if I miss-interpret your question.

@monikaYZ
Copy link
Author

I need to do a configuration service, and configure memory

@cch123
Copy link

cch123 commented Dec 29, 2016

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

@metalmatze
Copy link

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.

@javierprovecho javierprovecho self-assigned this Jan 2, 2017
@javierprovecho
Copy link
Member

@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.

@bonjefir
Copy link

bonjefir commented Jul 2, 2018

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

@nhu-duong
Copy link

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.

@john8329
Copy link

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.

@YiuTerran
Copy link

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.

@xiaolonggezte
Copy link

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

@pi314pi
Copy link

pi314pi commented Apr 26, 2020

I need the feature, also.

@hantmac
Copy link

hantmac commented Apr 27, 2020

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

@john8329
Copy link

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.

@binbin0325
Copy link

I need the feature, also.

@wudi
Copy link

wudi commented Jun 23, 2020

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

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

@mirusky
Copy link

mirusky commented Aug 19, 2020

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 ...

@miyazawatomoka
Copy link

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

@mirusky
Copy link

mirusky commented Sep 10, 2020

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

@jiankunking
Copy link

you can reset gin.Engine and *http.Server

@wangpengcheng
Copy link

wangpengcheng commented Sep 26, 2024

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"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests