1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > golang 超简单实现反向代理(nginx 端口转发 Proxy)

golang 超简单实现反向代理(nginx 端口转发 Proxy)

时间:2023-12-30 15:05:18

相关推荐

golang 超简单实现反向代理(nginx 端口转发 Proxy)

100行你就可以做到类似nginx带自动更新的端口转发功能

总共就2个文件,一个main(总行数128行),一个配置文件

main:

里面的json解析和log可以忽略

package mainimport ("/weimingjue/json"utils2 "goProxy/utils""goService/utils""io/ioutil""net""net/http""net/http/httputil""net/url""os""strings""sync""time")var (projectDir, _ = os.Getwd()fileName = projectDir + "/domain.config"readFileTime int64 = 0 //读取文件的时间fileChangedTime int64 = 0 //文件修改时间domainData[][]string //[{***.gq,8080,http://127.0.0.1:8080/}]duPeiZhiSuosync.Mutex //读配置锁)// 获取反向代理域名func getProxyUrl(reqDomain string) string {checkFile()for _, dms := range domainData {if strings.Index(reqDomain, dms[0]) >= 0 {return dms[2]}}return domainData[0][2]}//读取配置文件//域名:端口号,未知域名默认用第一个func checkFile() {nowTime := time.Now().Unix()if nowTime-readFileTime < 300 {return}//每5分钟判断文件是否修改domainFile, _ := os.OpenFile(fileName, os.O_WRONLY|os.O_APPEND, 0)info, _ := domainFile.Stat()if info.ModTime().Unix() == fileChangedTime {return}duPeiZhiSuo.Lock()defer duPeiZhiSuo.Unlock()domainFile, _ = os.OpenFile(fileName, os.O_WRONLY|os.O_APPEND, 0) //加锁再来一遍,防止重入info, _ = domainFile.Stat()changedTime := info.ModTime().Unix()if changedTime == fileChangedTime {return}//文件改变//重置数据readFileTime = nowTimefileChangedTime = changedTimedomainData = [][]string{}bytes, _ := ioutil.ReadFile(fileName)split := strings.Split(string(bytes), "\n")for _, domainInfo := range split {dLen := len(domainInfo)if dLen < 8 || dLen > 20 { //忽略错误信息continue}domainItems := strings.Split(domainInfo, ":")if len(domainItems) != 2 || len(domainItems[0]) < 3 || len(domainItems[1]) < 2 {continue}if utils.EndWidth(domainItems[1], "/") {domainItems = append(domainItems, "http://127.0.0.1:"+domainItems[1])} else {domainItems = append(domainItems, "http://127.0.0.1:"+domainItems[1]+"/")}domainData = append(domainData, domainItems)}domainSt, _ := json.Marshal(domainData)utils2.MyLogProxyI("配置已修改:" + string(domainSt))}//获取主机名func getHost(req *http.Request) string {if req.Host != "" {if hostPart, _, err := net.SplitHostPort(req.Host); err == nil {return hostPart}return req.Host}return "localhost"}func handleRequestAndRedirect(res http.ResponseWriter, req *http.Request) {host := getHost(req)proxyUrl := getProxyUrl(host)url2, _ := url.Parse(proxyUrl)utils2.MyLogProxyI("请求域名:" + host + ",转到:" + proxyUrl)// create the reverse proxyproxy := httputil.NewSingleHostReverseProxy(url2)// Update the headers to allow for SSL redirectionreq.URL.Host = url2.Hostreq.URL.Scheme = url2.Schemereq.Header.Set("X-Forwarded-Host", req.Header.Get("Host"))req.Host = url2.Host// Note that ServeHttp is non blocking and uses a go routine under the hoodproxy.ServeHTTP(res, req)}func main() {http.HandleFunc("/", handleRequestAndRedirect)if err := http.ListenAndServe(":80", nil); err != nil {utils.MyLogE("Proxy监听80端口错误:" + err.Error())panic(err)}}

domain.config:

***为自己的域名,":"后面是需要转发的端口,不用写http://,任何地方都不能有空格

wang.gq:8080***.aa:8081/

代码写的是相对目录请到当前目录执行"go run main.go",愉快的转发从现在开始

参考资料(抄的😂):/articles/14246

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。