go言語でリバースプロキシ

httputilのReverseProxyを使う

go言語でリバースプロキシを立てるには、httputilパッケージにあるReverseProxyを使うと簡単。
ReverseProxyはhttp.Handlerインタフェースを実装していて、http.ServerのHandlerに渡せる。
以下はlocalhost:9000のリクエストをlocalhost:9001に移譲する処理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main
import (
"log"
"net/http"
"net/http/httputil"
)
func main() {
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,
}
if err := server.ListenAndServe(); err != nil {
log.Fatal(err.Error())
}
}

別ドメインへの移譲

あんまりないケースかもしれないが、localhost:9000のアクセスを別のドメインに移譲する場合は以下。
bodyやヘッダをそのままコピーして新しいhttpのリクエストを生成しなおす必要がある。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main
import (
"bytes"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
)
func main() {
director := func(request *http.Request) {
url := *request.URL
url.Scheme = "https"
url.Host = "kido0617.github.io"
buffer, err := ioutil.ReadAll(request.Body)
if err != nil {
log.Fatal(err.Error())
}
req, err := http.NewRequest(request.Method, url.String(), bytes.NewBuffer(buffer))
if err != nil {
log.Fatal(err.Error())
}
req.Header = request.Header
*request = *req
}
rp := &httputil.ReverseProxy{Director: director}
server := http.Server{
Addr: ":9000",
Handler: rp,
}
if err := server.ListenAndServe(); err != nil {
log.Fatal(err.Error())
}
}

参考

Golang Reverse Proxy
Reverse Proxy in Go
ichigo