Правильный способ мультиплексировать HTTP-сервер в Go, который может обрабатывать не HTTP-протоколы - PullRequest
0 голосов
/ 18 февраля 2019

Я создал маршрутизатор с расширенными возможностями ведения журнала, используя Go.Это работает правильно для большинства случаев использования.Однако возникают проблемы, когда клиенты отправляют нестандартные HTTP-сообщения через порт 80.

На сегодняшний день я решил эту проблему, внедрив собственную версию ServeHTTP ():

func (myproxy *MyProxy) ServeHTTP(w http.ResponseWtier, r *http.Request) {

  // Inspect headers
  // Determine if it is a custom protocol (ie: websockets, CONNECT requests)
  // Implement handlers for each time
} 

Всобытие, в котором я определяю запрос, является нестандартным протоколом HTTP, запрос воспроизводится в исходное место назначения (через http.Request.Write ()), и все довольны.

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

Я мог бы взломать это, повторно внедрив net.Http.Server, но это кажется чрезвычайно сложным и хрупким подходом.Я бы предпочел сделать это, как-то подключиться к net / http / http / server.go прямо вокруг точки, где он получает соединение, а затем обернуть это в шпионскую оболочку, которая записывает запрос в буфер.

func (srv *Server) Serve(l net.Listener) error {

        // Lots of listener code...

    c := srv.newConn(rw)
    c.setState(c.rwc, StateNew) // before Serve can return

        // I'd like to wrap c here and save the request for possible reply later.
    go c.serve(ctx)
}

https://golang.org/src/net/http/server.go?s=93229:93284#L2805

Редактировать: Я смотрел на httpUtil: DumpRequest, но это немного изменяет исходный запрос (изменяет регистр и порядок заголовков).Если бы это не было сделано, это было бы идеальным решением.

https://godoc.org/net/http/httputil#DumpRequest

Есть ли способ перехватить соединения вокруг этой точки, прежде чем они будут проанализированы http.Request?

1 Ответ

0 голосов
/ 14 марта 2019

В интересах помощи другим, я хотел ответить на мой вопрос.Подход, который я предложил выше, на самом деле работает и является правильным способом сделать это.В итоге:

  • Реализация ListenAndServe ()
  • Завершение входящего net.Conn в TeeReader или другую оболочку мультиплексного соединения
  • Запись запроса
  • Наберите исходный пункт назначения и соединитесь с входящим соединением, при необходимости воспроизведя исходный запрос.

Аналогичный вариант использования требуется при обновлении запросов на соединение для серверов веб-сокетов.Хорошую рецензию можно найти здесь:

https://medium.freecodecamp.org/million-websockets-and-go-cc58418460bb

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...