[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[:], '\n')]), "%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\r\n\r\n")
    } else {
        server.Write(b[:n])
    }
    go io.Copy(server, client)
    io.Copy(client, server)
}
func GetAddress(HTTPData string) string{
    Lines := strings.Split(HTTPData,"\r\n")
    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都在该项目中

posted @ 2019-01-31 00:33  leeli73  阅读(1647)  评论(0编辑  收藏  举报