package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
)
type requestPayloadStruct struct {
ProxyCondition string `json:"proxy_condition"`
}
// Get env var or default
func getEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return fallback
}
// Get the port to listen on
func getListenAddress() string {
port := getEnv("PORT", "8072")
return ":" + port
}
// Serve a reverse proxy for a given url
func serveReverseProxy(target string, res http.ResponseWriter, req *http.Request) {
// parse the url
url, err := url.Parse(target)
if err != nil {
fmt.Printf("err: %+v\n", err)
}
// create the reverse proxy
proxy := httputil.NewSingleHostReverseProxy(url)
// Update the headers to allow for SSL redirection
req.URL.Host = url.Host
req.URL.Scheme = url.Scheme
req.Header.Set("X-Forwarded-Host", req.Header.Get("Host"))
req.Host = url.Host
//web端,通过代理调该接口产生跨域问题,多个头问题:
//Access-Control-Allow-Origin' header contains multiple values '*, *' 删除一个头
//res.Header().Del("Access-Control-Allow-Origin") //如果产生上述问题,就删除一个头
// Note that ServeHttp is non blocking and uses a go routine under the hood
proxy.ServeHTTP(res, req)
//出现上述多个头问题,删除头操作,放在此处不起作用,
//必须要放在proxy.ServeHTTP(res, req)操作前
// res.Header().Del("Access-Control-Allow-Origin")
}
// Get a json decoder for a given requests body
func requestBodyDecoder(request *http.Request) *json.Decoder {
// Read body to buffer
body, err := ioutil.ReadAll(request.Body)
if err != nil {
log.Printf("Error reading body: %v", err)
panic(err)
}
// Because go lang is a pain in the ass if you read the body then any susequent calls
// are unable to read the body again....
request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
return json.NewDecoder(ioutil.NopCloser(bytes.NewBuffer(body)))
}
// Parse the requests body
func parseRequestBody(request *http.Request) requestPayloadStruct {
decoder := requestBodyDecoder(request)
var requestPayload requestPayloadStruct
err := decoder.Decode(&requestPayload)
if err != nil {
panic(err)
}
return requestPayload
}
// Given a request send it to the appropriate url
func handleRequestAndRedirect(res http.ResponseWriter, req *http.Request) {
url := "http://50.73.65.35:8080"
url = "http://192.168.1.221:8280/v2/facesets/search?page_size=10&page_number=0" //错误,代理的url为代理的接口所在的服务的IP和端口,而不是具体的接口的URL
//url = "http://www.baidu.com"
url = "http://192.168.1.240:11032" //正确示例,代理的url为代理服务接口地址+端口
serveReverseProxy(url, res, req)
}
func main() {
// start server
http.HandleFunc("/", handleRequestAndRedirect)
http.HandleFunc("/api/v4/login", handleRequestAndRedirect)
err := http.ListenAndServe(getListenAddress(), nil)
if err != nil {
fmt.Println("err", err)
panic(err)
}
}
学艺不精,在做这个代理过程中遇到了问题,花了好久才解决问题,记录在此,以备不时之需。