无法访问在Heroku上运行的简单golang HTTP代理

时间:2019-03-07 16:15:02

标签: go heroku http-proxy

我最近部署了一个简单的用Go to Heroku编写的HTTP代理,似乎连接到代理端口时遇到问题。

这是启动侦听器的代码:

package main

import (
    "io"
    "log"
    "net"
    "net/http"
    "strings"
    "os"
    "fmt"
)

// Hop-by-hop headers. These are removed when sent to the backend.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
var hopHeaders = []string{
    "Connection",
    "Keep-Alive",
    "Proxy-Authenticate",
    "Proxy-Authorization",
    "Te", // canonicalized version of "TE"
    "Trailers",
    "Transfer-Encoding",
    "Upgrade",
}

func copyHeader(dst, src http.Header) {
    for k, vv := range src {
        for _, v := range vv {
            dst.Add(k, v)
        }
    }
}

func delHopHeaders(header http.Header) {
    for _, h := range hopHeaders {
        header.Del(h)
    }
}

func appendHostToXForwardHeader(header http.Header, host string) {
    // If we aren't the first proxy retain prior
    // X-Forwarded-For information as a comma+space
    // separated list and fold multiple headers into one.
    if prior, ok := header["X-Forwarded-For"]; ok {
        host = strings.Join(prior, ", ") + ", " + host
    }
    header.Set("X-Forwarded-For", host)
}

type proxy struct {
}

func (p *proxy) ServeHTTP(wr http.ResponseWriter, req *http.Request) {
    log.Println(req.RemoteAddr, " ", req.Method, " ", req.URL)

    if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
        msg := "unsupported protocal scheme "+req.URL.Scheme
        http.Error(wr, msg, http.StatusBadRequest)
        log.Println(msg)
        return
    }

    client := &http.Client{}

    //http: Request.RequestURI can't be set in client requests.
    //http://golang.org/src/pkg/net/http/client.go
    req.RequestURI = ""

    delHopHeaders(req.Header)

    if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
        appendHostToXForwardHeader(req.Header, clientIP)
    }

    resp, err := client.Do(req)
    if err != nil {
        http.Error(wr, "Server Error", http.StatusInternalServerError)
        log.Fatal("ServeHTTP:", err)
    }
    defer resp.Body.Close()

    log.Println(req.RemoteAddr, " ", resp.Status)

    delHopHeaders(resp.Header)

    copyHeader(wr.Header(), resp.Header)
    wr.WriteHeader(resp.StatusCode)
    io.Copy(wr, resp.Body)
}

func determineListenAddress() (string, error) {
    port := os.Getenv("PORT")
    if port == "" {
        return "", fmt.Errorf("$PORT not set")
    }
    return ":" + port, nil
}

func main() {
    addr, err := determineListenAddress()
    if err != nil {
        log.Fatal(err)
    }

    handler := &proxy{}

    log.Println("Starting proxy server on", addr)
    if err := http.ListenAndServe(addr, handler); err != nil {
        log.Fatal("ListenAndServe:", err)
    }
}

应用程序正确启动:

2019-03-07T14:52:56.712482+00:00 heroku[web.1]: Starting process with command `go_proxy`
2019-03-07T14:52:58.410575+00:00 heroku[web.1]: State changed from starting to up
2019-03-07T14:52:58.288473+00:00 app[web.1]: 2019/03/07 14:52:58 Starting proxy server on :51264

,但它似乎仅侦听端口80。尝试通过telnet到日志中显示的我的应用程序主机名和端口时,连接超时。当我尝试通过端口80到达它时,它仅显示一些空的HTML页面。

我已经看过许多简单的Go webapp应用程序示例,但似乎都没有类似的问题。

非常感谢您的帮助。

0 个答案:

没有答案