• [Go]基于Go语言的Web路由转发,多个网站共享一个端口(存在问题,已经抛弃,新解决方案请看新博客)


    服务器上跑了很多的Web服务,但都是基于Golang自己写的,不能像IIS或者Apache一样共享端口和绑定域名,很多端口号自己又记不住

    所以呢,我就利用端口转发技术,制作了这样一个Web路由

    其主要原理就是将所有流量集中在一个端口,然后再将其通过域名转发至真正WebServer工作的端口

    从而实现了域名指向一处服务器,而服务器又可以通过域名连接至与其对应的Web服务

    其实在我的测试中,这个Web路由也可以进行网站镜像之类的服务,或者说直接将流量转发至其他服务器

    下面是在我服务器上的测试,已经投入使用,暂时没用什么问题

    这里是代码,其实也不多,就一百来行

    package main
    
    import (
        "bytes"
        "fmt"
        "io"
        "os"
        "log"
        "net"
        "strings"
        "regexp"
        "io/ioutil"
        "encoding/json"
    )
    type Rule struct{
        Domain string `json:Domain`
        Address string `json:Address`
    }
    type Config struct{
        MainPort string `json:MainPort`
        Rules []Rule `json:Rules`
    }
    var myConfig Config
    func InitConfig(){
        var Data,err = ioutil.ReadFile("config.json")
        if err != nil{
            log.Println("Read Config File Error!")
            os.Exit(0)
            return
        }
        err = json.Unmarshal(Data,&myConfig)
        if err != nil{
            log.Println("Read Config JSON Error!Please Check!")
            os.Exit(0)
            return
        }
        fmt.Println("Main Port:"+myConfig.MainPort)
        for i:=0;i<len(myConfig.Rules);i++{
            fmt.Println("Domain: "+myConfig.Rules[i].Domain+" <----> "+myConfig.Rules[i].Address)
        }
    }
    func handleClientRequest(client net.Conn) {
        if client == nil {
            return
        }
        defer client.Close()
        var b [1024]byte
        n, err := client.Read(b[:])
        if err != nil {
            log.Println(err)
            return
        }
        var method, url, HTTPv, address string
        fmt.Sscanf(string(b[:bytes.IndexByte(b[:], '
    ')]), "%s%s%s", &method, &url, &HTTPv)
        address = GetAddress(string(b[:]))
        if address == "nil"{
            fmt.Println("Unknow Domain")
            return
        }
        server, err := net.Dial("tcp", address)
        if err != nil {
            log.Println(err)
            return
        }
        if method == "CONNECT" {
            fmt.Fprint(client, "HTTP/1.1 200 Connection established
    
    ")
        } else {
            server.Write(b[:n])
        }
        go io.Copy(server, client)
        io.Copy(client, server)
    }
    func GetAddress(HTTPData string) string{
        Lines := strings.Split(HTTPData,"
    ")
        for i:=0;i<len(Lines);i++{
            line := Lines[i]
            temp := strings.Split(line,": ")
            if strings.Compare(temp[0],"Host")==0{
                for i:=0;i<len(myConfig.Rules);i++{
                    if strings.Compare(myConfig.Rules[i].Domain,temp[1])==0{
                        return myConfig.Rules[i].Address
                    }
                }
            }
        }
        return "nil"
    }
    func compressStr(str string) string {
        if str == "" {
            return ""
        }
        reg := regexp.MustCompile("\s+")
        return reg.ReplaceAllString(str, "")
    }
    func main() {
        log.SetFlags(log.LstdFlags|log.Lshortfile)
        InitConfig()
        l, err := net.Listen("tcp", ":"+myConfig.MainPort)
        if err != nil {
            log.Panic(err)
        }
        for {
            client, err := l.Accept()
            if err != nil {
                log.Panic(err)
            }
            go handleClientRequest(client)
        }
    }

    下面是GitHub地址:https://github.com/leeli73/WebRouter

    Config规则和几个Release都在该项目中

  • 相关阅读:
    函数对象、名称空间与作用域
    函数
    leetcode语法练习(二)
    leetcode语法练习(一)
    字符编码与文件操作
    集合类型内置方法与总结
    列表,元组与字典类型
    数据类型内置方法之数据类型与字符串类型
    [SVG实战]饼图全面解析
    [JavaScript语法学习]重新认识JavaScript
  • 原文地址:https://www.cnblogs.com/lee-li/p/10340322.html
Copyright © 2020-2023  润新知