Go's httputil.ReverseProxy не работает для WebSocket трафика. Проблемы с этим подробно здесь . Похоже, что исправление / функция может быть выпущена в Go 1.12 (см. «Добавлено это к этапу Go1.12» здесь ).
Поскольку исправление / функция еще не выпущена, я пытаюсь написать собственный обратный прокси-сервер для решения проблемы до ее выпуска. На моем сервере я написал простой обработчик gorilla / websocket , который обновляет соединение и затем ожидает сообщения от клиента.
На моем обратном прокси-сервере я написал обработчик обратного прокси, основанный на отправке изменений в Go 1.12 здесь , особенно в reverseproxy.go . Вот ядро моего обработчика обратного прокси, в соответствующей части:
outreq := r.WithContext(ctx)
if r.ContentLength == 0 {
outreq.Body = nil
}
p.director(outreq)
outreq.Header = copyHeaders(browserHeaders)
setForwardHeader(r.RemoteAddr, outreq)
log.Infof("outreq URL is %+v", outreq.URL)
transport := http.DefaultTransport
res, err := transport.RoundTrip(outreq)
if err != nil {
log.Errorf("RoundTrip(outreq) failed: %s", err)
}
log.Infof("Server response was %+v", res)
if res.StatusCode != http.StatusSwitchingProtocols {
log.Errorf("Did not receive HTTP status 101 switchingn protocols: %d\n", res.StatusCode)
return
}
if !hasUpgradeHeaders(res.Header) {
log.Error("request does not contain upgrade headers")
return
}
backConn, ok := res.Body.(io.ReadWriteCloser)
if !ok {
log.Errorf("internal error: 101 switching protocols response with non-writable body: %v (%T)", res.Body, res.Body)
return
}
Когда я пытаюсь подключить веб-сокет из моего браузера, я получаю до этого последнего оператора if. Утверждение типа тела ответа на тип io.ReadWriteCloser
не выполнено. Когда я регистрирую ответ, я вижу это:
Server response was &{Status:101 Switching Protocols StatusCode:101 Proto:HTTP/1.1
ProtoMajor:1 ProtoMinor:1 Header:map[Upgrade:[websocket] Connection:[Upgrade]
Sec-Websocket-Accept:[B1fWETPTtNo0bAHFWkFn2lAm9iw=]] Body:{} ContentLength:0
TransferEncoding:[] Close:false Uncompressed:false
Trailer:map[] Request:0xc000112100 TLS:<nil>}
Вывод журнала ошибок:
ERRO[0012] internal error: 101 switching protocols response with non-writable body: {} (http.noBody)
Почему я получаю http.noBody
в теле ответа, а не что-то, реализующее интерфейс io.ReadWriteCloser
? Как я могу решить эту проблему, чтобы я мог захватить соединение и облегчить связь между браузером и сервером?
Обновление
Я думаю, что нашел ответ на вопрос "почему". Последний выпуск Go не включает эту строку в функцию readLoop persistConn в transport.go в пакете net / http:
if resp.isProtocolSwitch() {
resp.Body = newReadWriteCloserBody(pc.br, pc.conn)
}
Источник
Сравните с текущим здесь .
Есть идеи как решить?