33
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Goのリバースプロキシーでレスポンスを書き換える

Last updated at Posted at 2017-12-06

フューチャーアーキテクトアドベントカレンダーの5日目の
サーバーサイドレンダリングの代替としてPrerenderを試してみた
の最後で、「Go実装について 長くなったので説明は省略します。だれかがGoアドベントカレンダーを落としたら書くかも?」と書いていたら、早速落とす人がいたらしいので、ハイジャックします。

リバースプロキシーはnet/http/httputilパッケージの ReverseProxyを使えば簡単につくれますよ、という説明はよく見かけるのですが、レスポンスを書き換える方法はまとまった情報がなかったので紹介します。

リクエストを書き換える

go言語でリバースプロキシというブログのエントリーにある通りです。

向き先を書き換える、Directorというフック関数を設定してあげることで、向き先を変えられます。なお、このエントリーにあるように、この関数の中でrequestを書き換えることでドメインごと入れ替えたりとかもできますし、試してはないですが、当然ヘッダーを足すとかもできるでしょう。

	director := func(request *http.Request) {
		request.URL.Scheme = "http"
		request.URL.Host = ":9001"
	}
	rp := &httputil.ReverseProxy{Director: director}
	server := http.Server{
		Addr:    ":9000",
		Handler: rp,
	}

レスポンスを書き換える

レスポンスを書き換えるフック関数も用意されています。ModifyResponseというフィールドにこの関数を設定します。

modifier := func(res *http.Response) error {
	// 別途用意したheadless chromeの出力を分析したDOMのソース
	// を元に、goqueryを使ってレスポンスを書き換えたstring型のhtmlという
	// 変数を用意しています
	document, err := goquery.NewDocumentFromReader(res.Body)
	if err != nil {
		return err
	}
	:
	document.Find("head").AppendHtml(result.OGP)
	body := document.Find(route.BodySelector)
	body.SetHtml("")
	body.AppendHtml(result.InnerHTML)
	html, err := document.Html()
	if err != nil {
		return err
	}
	// ここからが汎用的なところで、この文字列を``io.ReadCloser``にして
	// res.Bodyを差し替えます
	b := []byte(html)
	res.Body = ioutil.NopCloser(bytes.NewReader(b))
	res.Header.Set("Content-Length", strconv.Itoa(len(b)))
	return nil
}

rp := &httputil.ReverseProxy{
	Director: director,
	ModifyResponse: modifier,
}

[]byteにしてからbytes.NewReaderで初期化していたのは、strings.NewReaderで良かった予感。
なお、内容を書き換える場合、Content-Lengthをわざわざ書き換えて上げる必要はありません。Bodyだけ置き換えればあとはhttputilパッケージが勝手にやってくれます。

追記: やっぱりContent-Length書き換え必要っぽい


追記:github.com/elazarl/goproxyというのもあるらしい

33
29
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?