I want to create http handler to handle one session:
func init(){
http.HandleFunc("/sess/215489598", func(w http.ResponseWriter, r *http.Request) {
//do something
})
}
and then remove it when session ends(expires).
How can I do that ?
This isn't directly possible: an HTTP multiplexer (type ServeMux) does not expose a deletion operation.
Using an HTTP multiplexer for session management turns out to be a bad idea. The current implementation of HTTP serving is kind of inefficient. It scans the entire multiplexer table for each URL, so the more handlers you have, the worse performance gets. That's fine for a few paths, but you can't manage even a few hundred sessions that way, much less hundreds of thousands.
The HTTP multiplexer would need some kind of synchronization to be used as a session management tool. Imagine there was an Unhandle method. If you Unhandle a path, you would expect the multiplexer to no longer handle your path with its previous data. But, different goroutines aren't guaranteed to see each other's changes to the same data without some kind of synchronization. So, the HTTP handler could still see the old view of the multiplexer, then respond to the request using the handler you thought you deregistered.
So, the HTTP handler itself can't do this for you- nor should it, because you don't have any means to synchronize your session lifespan.
Create a single handler for "/sess/"
. That handler should be responsible for delegating to individual sessions. It can use a map[sessionID]sessionHandler
to do this efficiently, and can either pipe all session management over channels to let a single goroutine keep track of sessions being created and destroyed, or go with a more traditional approach using reader-writer locks around your session map. This way, you can ensure that you won't try to dispatch a new request to a session handler after you've removed it.
Of course, you can get an HTTP request at any time, so someone might jump in and connect to a session the moment before you lock the map to delete the session, if a context switch happens in the instruction after you have decided you want to lock the map but before you actually do it, so manage your locks and session policies carefully. The "right thing" to do here depends mostly on the needs of your individual application.
I'm afraid golang http
package hasn't implemented method to remove or modify http handler for now, read:
src/pkg/net/http/server.go
http://golang.org/src/pkg/net/http/server.go?s=28409:28496#L962
type ServeMux
func NewServeMux() *ServeMux
func (mux *ServeMux) Handle(pattern string, handler Handler)
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)
It just implemented register function HandleFunc()
.
You have 2 ways to work around:
1 Modify source code to implement an unregister function. This is not advisable, since using ServerMux
directly is not a good idea.
Or:
2 Maybe you are make things much more complicated. You just need to parse /sess/215489598
in a general handler function, for example:
func Handler(response http.ResponseWriter, request *http.Request) {
modules := strings.Split(request.URL.Path, "/")
if modules[1] == "sess" {
session_id := modules[2]
}
}
Then you know how to do next :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With