程序基本實現了對http的完整轉發,目前暫不支持https
windows需要在設置中的網絡>代理設置為手動,並開啟代理服務器,填寫ip和端口
// httpForward
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"strconv"
"strings"
)
func HttpForward(pattern string, port int) {
http.HandleFunc(pattern, doGo)
strPort := strconv.Itoa(port)
fmt.Print("listenning on :", " ", pattern, " ", strPort, "\n")
err := http.ListenAndServe(":"+strPort, nil)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func doGo(w http.ResponseWriter, r *http.Request) {
//r.host不帶http,r.url是完整的url
//fmt.Println(r.Host, " ", r.URL, "\n")
fmt.Println("url: ", r.URL)
//查看url各個信息
// str := "hi ,it is working"
// b := []byte(str)
//w.Write(b)
//fmt.Print(r.Host, " ", r.Method, " \nr.URL.String ", r.URL.String(), " r.URL.Host ", r.URL.Host, " r.URL.Fragment ", r.URL.Fragment, " r.URL.Hostname ", r.URL.Hostname(), " r.URL.RequestURI ", r.URL.RequestURI(), " r.URL.Scheme ", r.URL.Scheme)
cli := &http.Client{}
//不建議用readfull,對於body大小難以判斷,容易出錯
// body := make([]byte, 2048000)
// n, err := io.ReadFull(r.Body, body)
body, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Print("io.ReadFull(r.Body, body) ", err.Error())
//return,沒有數據也是可以的,不需要直接結束
}
fmt.Print("req count :", len(body), "\n")
//fmt.Print(len(body))
//reqUrl := r.Host + r.URL.String()
reqUrl := r.URL.String()
//url里帶了協議類型,不需要用scheme
// if r.URL.Scheme != "" {
// reqUrl = r.URL.Scheme + reqUrl
// } else {
// reqUrl = "http://" + reqUrl
// }
req, err := http.NewRequest(r.Method, reqUrl, strings.NewReader(string(body)))
if err != nil {
fmt.Print("http.NewRequest ", err.Error())
return
}
//用遍歷header實現完整復制
//contentType := r.Header.Get("Content-Type")
//req.Header.Set("Content-Type", contentType)
for k, v := range r.Header {
req.Header.Set(k, v[0])
}
res, err := cli.Do(req)
if err != nil {
fmt.Print("cli.Do(req) ", err.Error())
return
}
defer res.Body.Close()
// n, err = io.ReadFull(res.Body, body)
// if err != nil {
// fmt.Print("io.ReadFull(res.Body, body) ", err.Error())
// return
// }
//fmt.Print("count body bytes: ", n, "\n")
for k, v := range res.Header {
w.Header().Set(k, v[0])
}
io.Copy(w, res.Body)
//這樣復制對大小控制較差,不建議。用copy即可
// io.WriteString(w, string(body[:n]))
// fmt.Print(string(body))
}
我發現使用https時,程序似乎接收不到請求,沒有反應,不知道是不是證書的問題