2013-04-10 2 views
2

Я хочу, чтобы создать обработчик HTTP для обработки одного сеанса:Как отменить подписку на http-обработчик?

func init(){ 
    http.HandleFunc("/sess/215489598", func(w http.ResponseWriter, r *http.Request) { 
     //do something 
    }) 
} 

, а затем удалить его, когда сеанс заканчивается (истекает).

Как я могу это сделать?

ответ

4

Это напрямую не возможно: мультиплексор HTTP (тип ServeMux) делает не выставлять операцию удаления.

Использование мультиплексора HTTP для управления сеансом оказывается плохой идеей. Текущая реализация HTTP-обслуживания - kind of inefficient.. Сканирует всю таблицу мультиплексора для каждого URL-адреса, поэтому чем больше обработчиков, тем хуже производительность. Это хорошо для нескольких путей, но вы не можете справиться даже с несколькими сотнями сеансов, а тем более сотнями тысяч.

Для мультиплексора HTTP потребуется какая-то синхронизация, которая будет использоваться в качестве инструмента управления сеансом. Представьте, что существует метод Unhandle. Если вы удалите путь, вы должны ожидать, что мультиплексор перестанет обрабатывать ваш путь с его предыдущими данными. Но, разные goroutines aren't guaranteed to see each other's changes to the same data without some kind of synchronization. Итак, обработчик HTTP все еще мог видеть старый вид мультиплексора, а затем отвечать на запрос с помощью обработчика, который, как вы считали, вы забыли.

Таким образом, обработчик HTTP сам по себе не может сделать это для вас - и не должен, потому что у вас нет средств для синхронизации продолжительности сеанса.

Создайте один обработчик для "/sess/". Этот обработчик должен нести ответственность за делегирование отдельных сеансов. Он может использовать map[sessionID]sessionHandler, чтобы сделать это эффективно, и может либо подключить все управление сеансом по каналам, чтобы позволить одному goroutine отслеживать созданные и уничтоженные сеансы, либо использовать более традиционный подход, используя блокировки чтения-записи вокруг вашей карты сеанса. Таким образом, вы можете убедиться, что после его удаления вы не будете отправлять новый запрос обработчику сеанса.

Конечно, вы можете получить HTTP-запрос в любое время, поэтому кто-то может перейти в сеанс и подключиться к сеансу за минуту до того, как вы заблокируете карту, чтобы удалить сеанс, если переключатель контекста произошел в инструкции после того, как вы решил, что вы хотите заблокировать карту, но прежде, чем вы это сделаете, поэтому тщательно контролируйте свои блокировки и политики сеансов. «Правильная вещь» здесь зависит в основном от потребностей вашего индивидуального приложения.

+2

Если вы используете Gorilla takeit, вам не нужно сканировать всю таблицу маршрутизации для каждого запроса. –

2

Боюсь golang http пакет не реализован метод, чтобы удалить или изменить обработчик HTTP сейчас, читайте:

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) 

Это просто реализована функция регистра HandleFunc() ,

У вас есть 2 способа работы вокруг:

1 исходный код Modify для реализации функции незарегистрированный. Это нецелесообразно, так как использование ServerMux напрямую - это не очень хорошая идея.

Или:

2 Может быть, вы сделать вещи намного сложнее. Вам просто нужно разобрать /sess/215489598 в общей функции обработчика, например:

func Handler(response http.ResponseWriter, request *http.Request) { 
    modules := strings.Split(request.URL.Path, "/") 

    if modules[1] == "sess" { 
    session_id := modules[2] 
    } 
} 

Тогда вы знаете, как делать дальше :)