go - 如何使用 proxy.ModifyResponse?

标签 go reverse-proxy httpwebresponse

我已经实现了最基本的反向代理来拉取页面,然后向正文添加一些内容。不幸的是,我添加到 html 的尝试没有生效。下面的代码只显示原始页面,但没有我在响应前添加的“猴子”。需要什么额外的电话才能让它工作?我最终想用它来替换自定义 css 的 css。

package main

import (
    "log"
    "net/http"
    "net/http/httputil"
    "net/url"
    "fmt"
    "github.com/PuerkitoBio/goquery"
    "bytes"
)

type Director func(*http.Request)

func (f Director) Then(g Director) Director {
    return func(req *http.Request) {
        f(req)
        g(req)
    }
}

func hostDirector(host string) Director {
    return func(req *http.Request) {
        req.Host = host
    }
}

func UpdateResponse(r *http.Response) error {
    doc, err := goquery.NewDocumentFromReader(r.Body)
    if err != nil{
        //log.New("Research")
        log.Fatal("Bad doc %v", err)
        return err
    }
    html, err := goquery.OuterHtml(doc.First())
    if err != nil{
        log.Fatal("Bad html %v", err)
        return err
    }
    fmt.Printf("Body %v", html)
    r.Write(bytes.NewBufferString("monkeys"+html))

    return nil
}

func main() {
    url, _ := url.Parse("http://cnn.com/")
    proxy := httputil.NewSingleHostReverseProxy(url)

    d := proxy.Director
    // sequence the default director with our host director
    proxy.Director = Director(d).Then(hostDirector(url.Hostname()))
    proxy.ModifyResponse = UpdateResponse
    http.Handle("/", proxy)
    log.Fatal(http.ListenAndServe(":9090", nil))
}

最佳答案

您的 ModifyResponse 代码没有修改响应。在您的代码中,您有:

r.Write(bytes.NewBufferString("monkeys"+html))

看起来您正在写回复,但不是。 r 属于 *http.Response,它有一个 Write 方法:

func (r *Response) Write(w io.Writer) error

document说:

Write writes r to w in the HTTP/1.x server response format, including the status line, headers, body, and optional trailer.

因为 bytes.Buffer 也实现了 io.Writer,所以代码可以编译,但不是写入缓冲区的响应,而是将响应写入缓冲区,这是绝对不希望的。

事实是,http.Response 根本不提供修改其Body 的方法。很明显 Bodey 是一个 io.ReadCloser。您可以做的是用正文创建一个新的 io.ReadCloser。请记住更改 Header 中的 Content-Length 字段,否则可能会导致问题。

func UpdateResponse(r *http.Response) error {
    b, _ := ioutil.ReadAll(r.Body)
    buf := bytes.NewBufferString("Monkey")
    buf.Write(b)
    r.Body = ioutil.NopCloser(buf)
    r.Header["Content-Length"] = []string{fmt.Sprint(buf.Len())}
    return nil
}

Playground :https://play.golang.org/p/_Tyvo6GVN3x

关于go - 如何使用 proxy.ModifyResponse?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51356104/

相关文章:

go - 如何正确运行 evans(gRPC 客户端)?

go - 将 stdout/stderr 重定向到一个函数的最佳方法是什么,该函数反过来格式化消息并将其打印到控制台?

javascript - 使用 go 和 Otto 调用 javascript 回调函数

reverse-proxy - 应如何配置 Tinyproxy 以将流量正确路由回客户端?

c# - HttpWebRequest/HttpWebResponse 的速度

c# - 在 C# 中使用 Windows 应用程序执行 http 方法

ssh - 使用 SSH 和带有 golang 的 pem/key 连接到服务器

tomcat - 两个 tomcat 服务器使用相同的端口,为 iis 重写规则

docker - 无法通过 docker-compose.yml 中的 "labels"设置 Traefik

c# - 如何获取 HTTP Web 请求以返回完整源代码