Неиспользуемое тело ответа в обратном прокси-сервере WebSocket - PullRequest
0 голосов
/ 04 ноября 2018

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)
}

Источник

Сравните с текущим здесь .

Есть идеи как решить?

...