douwen3362 2019-03-08 05:50
浏览 31
已采纳

重写中间件中的内容长度

below code rewrites the http body response of some queries.

However, it fails to update the "content length" header field, it always remains the same original value.

How can i update the content length header field of the http response ?

type writeReplacer struct {
    http.ResponseWriter
    search  []byte
    replace func(*http.Request) string
    buf     []byte
    r       *http.Request
    dir     string
}

func (w *writeReplacer) Write(in []byte) (int, error) {
    if w.buf == nil {
        w.buf = []byte{}
    }
    w.buf = append(w.buf, in...)
    n := len(in)
    if index := bytes.LastIndex(w.buf, w.search); index > -1 {
        var r []byte
        if w.dir == "before" {
            g := []byte(w.replace(w.r))
            n += len(g)
            r = append(g, w.buf[index:]...)
            w.buf = append(w.buf[:index], r...)
        } else {
            g := []byte(w.replace(w.r))
            n += len(g)
            r = append(r, w.buf[:index+len(w.search)]...)
            r = append(r, g...)
            r = append(r, w.buf[index:]...)
            w.buf = r
        }
    }
    return n, nil
}

func (w *writeReplacer) Flush() {
    w.ResponseWriter.Header().Set("Content-Length", fmt.Sprint(len(w.buf)))
    w.ResponseWriter.Write(w.buf[:])
    w.buf = w.buf[:0]
}

func InsertAfter(h http.Handler, path string, search []byte, replace func(*http.Request) string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if r.URL.Path == path {
            w.Header().Del("Content-length")
            w = &writeReplacer{ResponseWriter: w, search: search, replace: replace, r: r, dir: "after"}
            defer w.(http.Flusher).Flush()
        }
        h.ServeHTTP(w, r)
    })
}

func InsertBefore(h http.Handler, path string, search []byte, replace func(*http.Request) string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if r.URL.Path == path {
            w.Header().Del("Content-length")
            w = &writeReplacer{ResponseWriter: w, search: search, replace: replace, r: r, dir: "before"}
            defer w.(http.Flusher).Flush()
        }
        h.ServeHTTP(w, r)
    })
}

I receive two errors message, the first one from nginx

2019/03/08 05:58:37 [error] 31194#0: *19 
upstream prematurely closed connection while reading upstream, 
client: 82.21.18.16, server: buycoffee.online, request: 
"GET / HTTP/1.1", upstream: "http://127.0.0.1:8081/", host: "buycoffee.online"

the second one from curl

curl: (18) transfer closed with 6237 bytes remaining to read
  • 写回答

1条回答 默认 最新

  • doudun5009 2019-03-08 07:45
    关注

    as mkopriva suggested the trick was to rewrite ResponseWriter.WriteHeader.

    I believe it has to do with the fact that write might call writeheader at first call, and from there i was not putting the instructions at the right place.

    in order to prevent further difficulties i prefer to use chunked transfer.

    the code change is:

    func (w *writeReplacer) WriteHeader(statusCode int) {
        w.Header().Del("Content-length")
        w.Header().Set("Transfer-Encoding", "chunked")
        w.ResponseWriter.WriteHeader(statusCode)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 mmocr的训练错误,结果全为0
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀