代码之家  ›  专栏  ›  技术社区  ›  Darian Hickman

如何使用proxy.modifyresponse?

  •  0
  • Darian Hickman  · 技术社区  · 7 年前

    我已经实现了最基本的反向代理来拉一个页面,然后在正文中添加一些内容。不幸的是,我添加到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 回复  |  直到 7 年前
        1
  •  2
  •   leaf bebop    7 年前

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

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

    看来你是在回复,但没有。 r *http.Response 它有一个 Write 方法:

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

    这个 document 说:

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

    自从 bytes.Buffer 还实现了 io.Writer ,代码会编译,但它不会写入缓冲区的响应,而是将响应写入缓冲区,这是绝对不需要的。

    事实是, http.Response 只是不提供修改它的方法 Body 是的。很明显 Bodey 是一个 io.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