服务器
package mainimport ( "bytes" "encoding/base64" "encoding/json" "fmt" "io/ioutil" "log" "math/rand" "net/http" "golang.org/x/net/websocket")var cp = make(chan []byte)var res = make(chan []byte, 1)//var uri_chan_map = make(map[string]chan *Return_content)var uri_chan_map = make(map[string]chan map[string]interface{})type Req_Group struct { Method string Header http.Header Body []byte Uri string Host string Id string}type Return_content struct { Uri string `json:"uri"` Id string `json:"id"` Header http.Header `json:"header"` Body []byte `json:"body"`}func Soket(ws *websocket.Conn) { //设置连接超时, 如果websocket客户端连接后, 客户端响应时间超过设置的等待时间, 则websocket服务端主动断开连接 //ws.SetReadDeadline(time.Now().Add(30 * time.Second)) //ws.RemoteAddr()远程地址(客户端地址), ws.LocalAddr()本地地址(服务器地址) fmt.Printf("websocket %s->%s 通信连接已建立:\n", ws.RemoteAddr().String(), ws.LocalAddr().String()) //标记出错, false表示没出错, true表示出错 var err_message = false //外层for循环一次发送一次请求信息 for true { data := <-cp ws.Write(data) //从缓存中一次只读取1024字节, 如果接收数据过多, 可以将读取内容存在一个可变的数组中,循环读取到缓存无数据即可 //将每次读取的1024字节存放在msg中, 然后append到result_msg中 msg := make([]byte, 1024) //将所有的读取信息存放在result_msg中 var result_msg []byte //内层for循环用来读取response信息 for true { n, err := ws.Read(msg) //这里的问题是websocket客户端的问题 if err != nil { fmt.Println("websocket客户端出现错误或断开") res_msg := make(map[string]string) res_msg["err"] = err.Error() new_msg, _ := json.Marshal(res_msg) new_msg = []byte(new_msg) result_msg = append(result_msg, new_msg...) //出错就把标记表量设置为true err_message = true break } if n != 0 && string(msg[:n]) != "OVER" { //msg的元素被打散一个个append进result_msg, 如果不加... 直接写会报错 new_msg := msg[:n] result_msg = append(result_msg, new_msg...) //fmt.Printf("读取了%d字节\n", n) msg = make([]byte, 1024) } else if string(msg[:n]) == "OVER" { fmt.Println("websocket传输完毕!") break } } //err_message为true就代表websocket客户端出错, 需要退出发送信息的外循环, 并断开websocket连接 if err_message { //将出错信息返回给http客户端 res <- result_msg //每次把response信息返回给客户端之后, 要将msg, result_msg清空, 否则会出之前的信息和现在的信息黏连的错误 msg = make([]byte, 1024) result_msg = []byte{} break } res <- result_msg //每次把response信息返回给客户端之后, 要将msg, result_msg清空, 否则会出之前的信息和现在的信息黏连的错误 msg = make([]byte, 1024) result_msg = []byte{} } ws.Close()}func Handler(w http.ResponseWriter, r *http.Request) { //处理请求 fmt.Printf("http客户端: %s 请求uri: %s 已连接...\n", r.RemoteAddr, r.URL.Path) //允许访问所有的域 w.Header().Set("Access-Control-Allow-Origin", "*") //reflect.TypeOf(r).String(): *http.Request var req Req_Group req.Method = string(r.Method) req.Header = r.Header //使用随机字符串作为标识 req.Id = randomString(10) defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) req.Body = body req.Uri = r.URL.Path req.Host = "https://192.168.18.97" var uri_chan = make(chan map[string]interface{}) json_req, _ := json.Marshal(req) //设置随机字符串Id对应的通道 uri_chan_map[req.Id] = uri_chan cp <- json_req new_content := <-uri_chan_map[req.Id] send_message(new_content, w, r)}func send_message(new_content map[string]interface{}, w http.ResponseWriter, r *http.Request) { delete(new_content, "Id") if _, ok := new_content["header"]; ok { //返回response头信息 for k, v := range new_content["header"].(map[string]interface{}) { switch tp := v.(type) { case []interface{}: for _, u := range tp { w.Header().Set(k, u.(string)) } case string: w.Header().Set(k, v.(string)) } } 对body进行base64解码 decodeBytes, err := base64.StdEncoding.DecodeString(new_content["body"].(string)) if err != nil { log.Fatalln(err) } w.Write(decodeBytes) fmt.Printf("http 客户端: %s: 响应uri: %s 请求的uri: %s 已完成\n", r.RemoteAddr, new_content["uri"].(string), r.URL.Path) return } else { w.Write([]byte(new_content["err"].(string))) fmt.Printf("出现错误, http 客户端: %s: 请求uri: %s 已完成\n", r.RemoteAddr, new_content["uri"].(string)) return }}//生成随机数函数func randomString(l int) string { var result bytes.Buffer var temp string for i := 0; i < l; { temp = string(randInt(65, 90)) result.WriteString(temp) i++ } return result.String()}func randInt(min int, max int) int { return min + rand.Intn(max-min)}func main() { go func() { for { content := <-res var new_content map[string]interface{} err := json.Unmarshal(content[:len(content)], &new_content) if err != nil { log.Fatal("err-->Handler json反解析 ", err) } uri_chan_map[new_content["id"].(string)] <- new_content } }() fmt.Println("服务器已开启, 等待客户端连接...") http.HandleFunc("/", Handler) http.Handle("/echo", websocket.Handler(Soket)) err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatal("err -> main", err) }}
反向代理客户端
package mainimport ( "bytes" "crypto/tls" "encoding/base64" "encoding/json" "fmt" "io" "io/ioutil" "log" "net/http" "golang.org/x/net/websocket")type Return_content struct { Uri string `json:"uri"` Id string `json:"id"` Header http.Header `json:"header"` Body []byte `json:"body"`}//客户端地址,自己设置, 但是端口要和服务器监听的端口一致var origin = "http://127.0.0.1:8080/"//服务器地址(在服务器设置端口/后的参数)var url = "ws://127.0.0.1:8080/echo"var ch = make(chan []byte)var res_str = make(chan string)func Forward(ws *websocket.Conn, receive_con map[string]interface{}) { for true { result := <-ch _, err := ws.Write(result) if err != nil { log.Fatal("err -> Forward: ", err) } var over = "OVER" _, err = ws.Write([]byte(over)) fmt.Println("转发成功!") start() }}func http_DO(receive_con map[string]interface{}) { //go实现的Client端默认也是要对服务端传过来的数字证书进行校验的,访问https需要让client端略过对证书的校验: tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{Transport: tr} request_url := "https://192.168.18.97" if _, ok := receive_con["Uri"]; ok { request_url = request_url + receive_con["Uri"].(string) } //根据是否有请求体区分 if len(receive_con["Body"].(string)) > 0 { decodeBytes, err := base64.StdEncoding.DecodeString(receive_con["Body"].(string)) if err != nil { log.Fatalln(err) } send_message(client, receive_con, request_url, bytes.NewReader(decodeBytes)) } else { form_data := bytes.NewReader(nil) send_message(client, receive_con, request_url, form_data) }}func send_message(client *http.Client, receive_con map[string]interface{}, request_url string, form_data io.Reader) { rep, err := http.NewRequest(receive_con["Method"].(string), request_url, form_data) //设置请求头 rep.Header.Set("Host", receive_con["Host"].(string)) for k1, v1 := range receive_con["Header"].(map[string]interface{}) { if k1 != "Accept-Encoding" && k1 != "Accept-Language" && k1 != "Id" { for _, v2 := range v1.([]interface{}) { rep.Header.Set(k1, v2.(string)) } } } resp, err := client.Do(rep) fmt.Println("status: ", resp.StatusCode) if err != nil { fmt.Println("请求出错", err) } Return_response_message(receive_con["Uri"].(string), resp, receive_con["Id"].(string))}func Return_response_message(uri string, resp *http.Response, Id string) { fmt.Println("请求uri: ", uri) defer resp.Body.Close() var return_content Return_content return_content.Id = Id return_content.Uri = uri return_content.Header = resp.Header body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) } //将body进行base64编码之后和json.Marshal的body结果一样 //encodeString := base64.StdEncoding.EncodeToString(body) //fmt.Println("encodeString: ", encodeString) return_content.Body = body json_return_content, _ := json.Marshal(return_content) // body是base64编码 ch <- json_return_content}func start() { ws, err := websocket.Dial(url, "", origin) for true { if err != nil { log.Fatal("err1 -> start: ", err) } var msg = make([]byte, 2048) m, err := ws.Read(msg) if err != nil { log.Fatal("err2 -> start: ", err) } web_message := msg[:m] //解析websocket发送的message var jx_web_message map[string]interface{} err = json.Unmarshal(web_message, &jx_web_message) if err != nil { log.Fatal("err3 -> start: ", err) } defer func() { ws.Close() }() go Forward(ws, jx_web_message) http_DO(jx_web_message) }}func main() { start()}