Skip to content

Instantly share code, notes, and snippets.

@leizongmin
Last active December 11, 2017 05:07
Show Gist options
  • Save leizongmin/9d8a1b9bd98438a667c8eedec677d271 to your computer and use it in GitHub Desktop.
Save leizongmin/9d8a1b9bd98438a667c8eedec677d271 to your computer and use it in GitHub Desktop.
Go语言写的简单HTTP反向代理
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/url"
"time"
)
func main() {
log.Fatal(http.ListenAndServe(":3000", proxy("http://www.rabbitpre.com", time.Second*10)))
}
func copyHeader(dest, src http.Header) {
for k, vv := range src {
for _, v := range vv {
dest.Add(k, v)
}
}
}
func responseError(w http.ResponseWriter, err error) {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(w, err)
}
func proxy(target string, timeout time.Duration) http.Handler {
urlInfo, err := url.Parse(target)
if err != nil {
panic(err)
}
client := &http.Client{
Timeout: timeout,
}
log.Printf("init: target=%s timeout=%d", target, timeout)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
log.Printf("%s %s %d\n", r.Method, r.RequestURI, r.ContentLength)
log.Printf(" - proxy: %s\n", target+r.RequestURI)
if err != nil {
responseError(w, err)
return
}
req, err := http.NewRequest(r.Method, target+r.RequestURI, r.Body)
if err != nil {
responseError(w, err)
return
}
copyHeader(req.Header, r.Header)
req.Header.Set("Host", urlInfo.Host)
resp, err := client.Do(req)
if err != nil {
responseError(w, err)
return
}
defer resp.Body.Close()
log.Printf(" - response: %d %s %d\n", resp.StatusCode, resp.Header.Get("Content-Type"), resp.ContentLength)
copyHeader(w.Header(), resp.Header)
w.WriteHeader(resp.StatusCode)
io.Copy(w, resp.Body)
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment