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

🤔 Dynamically Remove Routes #600

Closed
Zeedinstein opened this issue Jul 13, 2020 · 9 comments
Closed

🤔 Dynamically Remove Routes #600

Zeedinstein opened this issue Jul 13, 2020 · 9 comments
Assignees

Comments

@Zeedinstein
Copy link

Is there a way to dynamically remove routes from fiber.App or a fiber.Group, so that the route can not be accessed anymore and removed from memory. This is something I could do in express by accessing the app.stack which was just an array of the configured routes.

I see in fiber I can get all the configured routes using app.Routes() but I don't have access to app.stack

Is this possible to do with fiber?

@welcome
Copy link

welcome bot commented Jul 13, 2020

Thanks for opening your first issue here! 🎉 Be sure to follow the issue template! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord

@Fenny
Copy link
Member

Fenny commented Jul 13, 2020

Hi @Zeedinstein, our private stack is not really user friendly and rather complex that could cause problems when changing it.

We could add a safe method like Remove() / Delete() for the Route struct, I have have to think this through before making any changes, so feedback is welcome!

func main() {
	app := fiber.New()

	tmp := app.Get("/", func(c *fiber.Ctx) {
		c.Send("I'm reserved for 1 request 😭")
		c.Route().Remove()
	})

	app.Get("/remove", func(c *fiber.Ctx) {
		tmp.Remove()
	})

	log.Fatal(app.Listen(3000))
}

@Zeedinstein
Copy link
Author

Yeah looking at the source code I can see why it's complicated.

You would probably have to rebuild the app's stack array.

@Zeedinstein
Copy link
Author

Here is the code I tried to get working(It's probably not the best code to do this):

func (app *App) Remove(method string, path string) {
	method = strings.ToUpper(method)
	methodINT := methodInt(method)
	if methodINT != -1 {
		removed := false
		newStack := make([][]*Route, len(intMethod))
		for x, route := range app.stack[methodINT] {
			if route.path == path {
				app.routes--
				removed = true
				continue
			}
			if removed {
				app.stack[methodINT][x].pos = x - 1
				newStack[methodINT] = append(app.stack[methodINT], app.stack[methodINT][x])
			} else {
				newStack[methodINT] = append(app.stack[methodINT], app.stack[methodINT][x])
			}
		}
		app.stack = newStack
	}
}

This passes this test:

func Test_App_Remove(t *testing.T) {
	app := New()
	h := func(c *Ctx) {}
	app.Get("/Get", h)
	app.Head("/Head", h)
	app.Post("/post", h)
	utils.AssertEqual(t, 3, len(app.Routes()))
	app.Remove("GET", "/Get")
	utils.AssertEqual(t, 2, len(app.Routes()))
}

But fails for this test:

func Test_App_Remove(t *testing.T) {
	app := New()
	h := func(c *Ctx) {}
	app.Get("/Get", h)
	app.Head("/Head", h)
	app.Post("/post", h)
	utils.AssertEqual(t, 3, len(app.Routes()))
	app.Remove("GET", "/Get")
	utils.AssertEqual(t, 2, len(app.Routes()))
	resp, err := app.Test(httptest.NewRequest("GET", "/Get", nil))
	utils.AssertEqual(t, nil, err)
	utils.AssertEqual(t, 404, resp.StatusCode)
}

So it updates the app.stack but not the actual routes. So I'm not sure how the routes are getting registered in memory.

@kiyonlin
Copy link
Contributor

kiyonlin commented Jul 13, 2020

Thanks for your suggestion @Zeedinstein . Removing routes dynamically will effect requests which are matching. That’ll cost a lot to ensure data security and consistency.

Let us know whether the issue is resolved!

@Fenny
Copy link
Member

Fenny commented Jul 14, 2020

I have to agree with @kiyonlin, I don't think a web framework should solve dynamic problems like this.

A better approach would be to have an one catch all handler and lookup the user registered paths and respond accordingly.

It would achieve the same results but with faster response time, because if the route is removed from the stack it would loop trough all routes looking for a match on each request resulting in a slower 404 versus providing one yourself on a early match 👍

I hope this answered your question, feel free to close this issue 👍

@jozsefsallai
Copy link
Member

I would like to see a real-world use case of deleting routes dynamically

@mirusky
Copy link
Contributor

mirusky commented Aug 21, 2020

Instead of removing it is possible to overwrite the handler? Like Iris

@camdenorrb
Copy link

Modular routes, boom big use case

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

No branches or pull requests

8 participants