2016-07-12 11 views
0

ここでGoというミドルウェアを使用して、既存のServerヘッダーを自分の値で上書きしたいとします。外側のGoミドルウェアからのHTTPヘッダーを制御する

// Server attaches a Server header to the response. 
func Server(h http.Handler, serverName string) http.Handler { 
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
     w.Header().Set("Server", serverName) 
     h.ServeHTTP(w, r) 
    }) 
} 

authHandlerまたはDefaultServeMuxで扱うものは(のような、たとえば、httputil.ReverseProxy.ServeHTTP)、私は2台のサーバーで終わるw.Header().Add("Server", "foo")を呼び出した場合、私は、残念ながら、この

http.Handle("/", authHandler) 
http.ListenAndServe(":8000", Server(http.DefaultServeMux, "myapp")) 

のような応答チェーンに追加します応答のヘッダー。

// Server attaches a Server header to the response. 
func Server(h http.Handler, serverName string) http.Handler { 
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
     h.ServeHTTP(w, r) 
     w.Header().Set("Server", serverName) 
    }) 
} 

はしかし、これはdisallowed by the semantics of ServeHTTP次のとおりです:

ServeHTTPがResponseWriterにリプライヘッダとデータを書き込み、その後、返す必要があり、私が本当に欲しい

$ http localhost:5962/v1/hello_world 
HTTP/1.1 200 OK 
Content-Length: 11 
Content-Type: text/plain 
Date: Tue, 12 Jul 2016 04:54:04 GMT 
Server: inner-middleware 
Server: myapp 

はこのようなものです。要求が完了したという信号を返す。 ResponseWriterを使用したり、ServeHTTP呼び出しの完了後に、または同時にRequest.Bodyから読み取ることは無効です。

Iは、例えば、httputil.ReverseProxy.ServeHTTPのコード、コピーヘッダをこの周りにいくつかのかなり醜いハックを見て応答コードを書き換える、またはhttptest.ResponseRecorder、バイトバッファに体全体を読み取るを使用しました。

また、従来のミドルウェアの順序を逆にして、最後にサーバーミドルウェアを置くこともできます。

私は行方不明の簡単な方法はありますか?

答えて

1

。ここに例があります:

type serverWriter struct { 
    w   http.ResponseWriter 
    name  string 
    wroteHeader bool 
} 

func (s serverWriter) WriteHeader(code int) { 
    if s.wroteHeader == false { 
     s.w.Header().Set("Server", s.name) 
     s.wroteHeader = true 
    } 
    s.w.WriteHeader(code) 
} 

func (s serverWriter) Write(b []byte) (int, error) { 
    return s.w.Write(b) 
} 

func (s serverWriter) Header() http.Header { 
    return s.w.Header() 
} 

// Server attaches a Server header to the response. 
func Server(h http.Handler, serverName string) http.Handler { 
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
     sw := serverWriter{ 
      w:   w, 
      name:  serverName, 
      wroteHeader: false, 
     } 
     h.ServeHTTP(sw, r) 
    }) 
} 
+0

これはそれを強化する完璧な例です。 WriteHeader()を呼び出す前に、ヘッダーが書き込まれる場所を変更して書き込むだけです。 – dlsniper

+0

私はあなたのコメントで本当に混乱しています。外部ミドルウェアから内部ミドルウェアを無効にすることは不可能です。この場合、私はhttputil.ReverseProxy.ServeHTTPを呼び出して、制御しないコードにプロキシします。 ReverseProxy.ServeHTTPは、プロキシが返すものであればWriteHeaderを呼び出します。私はそれを制御することはできません。 –

+0

@dlsniperあなたは質問を再読みする必要があります私の友人 – Kugel

1

WriteHeader(ステータス)を使用した後、ヘッダーを変更(追加/削除/変更)することはできません。

仕事、に変更するには、このために

:あなたは間接の追加の層の費用で、ResponseWriterをラップし、すべてのヘッダーが書き込まれる直前にサーバヘッダを挿入するカスタムタイプを定義することができます

// Server attaches a Server header to the response. 
func Server(h http.Handler, serverName string) http.Handler { 
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
    w.Header().Set("Server", serverName) 
    h.ServeHTTP(w, r) 
    }) 
} 
+0

申し訳ありません - 私の最初のコードスニペットとの違いはどうですか? –

+0

書込みヘッダーとh.ServeHTTPの位置はdiffです。 – dlsniper

+0

Ah - 質問に2つのコードスニペットがあります。最初に書いたものと一致し、2番目は私がやりたいことの例です。 –

関連する問題