Golang RoundTripper доставляет пустой ответ - PullRequest
0 голосов
/ 30 января 2020

Я создал небольшие запросы переадресации прокси на другой порт на той же машине и доставил результат обратно вызывающей стороне.

В моем случае результатом службы является простая html страница, содержащая ссылки , Поскольку обратный прокси-сервер работает на другом порту, чем служба, я должен настроить ссылки. Я попытался сделать это, используя пользовательскую реализацию Transport:

type transport struct {
    http.RoundTripper
}

func (t *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
    resp, err = t.RoundTripper.RoundTrip(req)
    if err != nil {
        return nil, err
    }

    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    err = resp.Body.Close()
    if err != nil {
        return nil, err
    }

    // This works
    b = bytes.Replace(b, []byte("http://localhost:5000"), []byte("http://localhost:8080"), -1)

   // This doesn't
    b = bytes.Replace(b, []byte("api"), []byte("auth-api"), -1)

    resp.Body = ioutil.NopCloser(bytes.NewReader(b))
    resp.ContentLength = int64(len(b))

    return resp, nil
}

. Вот как я инициализирую обратный прокси-сервер в обработчике запросов:

proxy := httputil.NewSingleHostReverseProxy(target)
proxy.Transport = &transport{http.DefaultTransport}
proxy.ServeHTTP(res, req)

Первая замена в моем коде работает , Но секунды приводят к нескольким дополнительным вызовам клиента (распознаваемым по нескольким попаданиям точки останова) и безрезультатным:

curl: (52) Empty reply from server

Если я раскомментирую

b = bytes.Replace(b, []byte("api"), []byte("auth-api"), -1)

, все работает просто отлично и имя хоста заменяется, как и ожидалось. Я так старался отлаживать, но не смог выяснить, в чем дело. Если я сохраню тело в файл после того, как замена будет сделана, все будет в порядке, и префикс также будет заменен. Он просто не может доставить его через ответ.

1 Ответ

0 голосов
/ 31 января 2020

Это определенно не проблема моего кода. Я создал минимальный рабочий пример, который полностью независим и может быть опробован любым из вас. Если вы прокомментируете строку 37 (вторая замена), порт 8080 (обратный прокси-сервер) больше не будет отвечать.

<code>package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httputil"
    "net/url"
)

type transport struct {
    http.RoundTripper
}

func (t *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
    resp, err = t.RoundTripper.RoundTrip(req)
    if err != nil {
        return nil, err
    }

    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    err = resp.Body.Close()
    if err != nil {
        return nil, err
    }

    // This works
    b = bytes.Replace(b, []byte("localhost:5000"), []byte("localhost:8080"), -1)

    // This doesn't
    // b = bytes.Replace(b, []byte("api"), []byte("auth-api"), -1)

    reader := bytes.NewReader(b)
    closer := ioutil.NopCloser(reader)
    body := closer
    resp.Body = body
    resp.ContentLength = int64(len(b))

    return resp, nil
}

func main() {
    infoPageServer := http.NewServeMux()
    infoPageServer.HandleFunc("/", serveHTML)

    reverseProxy := http.NewServeMux()
    reverseProxy.HandleFunc("/", serveProxy)

    // Running Info Page Server
    go func() {
        log.Println("Starting Info Page service on port 5000")
        http.ListenAndServe(":5000", infoPageServer)
    }()

    // Running Reverse Proxy Server
    log.Println("Starting Reverse Proxy service on port 8080")
    http.ListenAndServe(":8080", reverseProxy)
}

func serveHTML(resp http.ResponseWriter, req *http.Request) {
    const html = `<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <title>Info Page</title>
  </head>
  <body>
    <pre>http://localhost:5000/api/
`fmt.Fprint (resp, html)} fun c serveProxy (соответственно http.ResponseWriter, req * http.Request) {target, err: = url.Parse ("http://localhost: 5000"), если err! = Nil {pani c (err)} proxy: = httputil.NewSingleHostReverseProxy (target) proxy.Transport = & transport {http.DefaultTransport} proxy.ServeHTTP (соответственно, req)} * ​​1006 *
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...