如何使用proxy.ModifyResponse?

时间:2018-07-16 06:52:36

标签: 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))
}

1 个答案:

答案 0 :(得分:2)

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

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

您似乎正在写回复,但没有。 r属于*http.Response,具有Write方法:

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

document说:

  

Write以HTTP / 1.x服务器响应格式将r写入w,包括状态行,标头,正文和可选的尾部。

由于bytes.Buffer也实现了io.Writer,因此代码得以编译,但是与其将响应写入缓冲区,还不将其写入缓冲区,这是绝对不希望的。

事实是,http.Response根本没有提供修改其Body的方法。显然Bodeyio.ReadCloser。您可以做的是使用主体创建一个新的io.ReadCloser。记住要更改Content-Length中的Header字段,否则可能会导致问题。

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
}

游乐场:https://play.golang.org/p/_Tyvo6GVN3x