实现websocket基本功能

This commit is contained in:
GoEdgeLab
2020-09-26 19:54:20 +08:00
parent 37b5243eef
commit 423a7f5b24
16 changed files with 910 additions and 189 deletions

View File

@@ -1,11 +1,16 @@
package serverconfigs
// 字符集设置
type HTTPCharsetConfig struct {
IsPrior bool `yaml:"isPrior" json:"isPrior"` // 是否覆盖
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
Charset string `yaml:"charset" json:"charset"` // 字符集
IsUpper bool `yaml:"isUpper" json:"isUpper"` // 是否要大写
// TODO 支持自定义字符集
}
// 初始化
func (this *HTTPCharsetConfig) Init() error {
return nil
}

View File

@@ -44,8 +44,15 @@ func (this *HTTPLocationConfig) Init() error {
}
}
if this.ReverseProxyRef != nil {
err := this.ReverseProxyRef.Init()
if err != nil {
return err
}
}
if this.ReverseProxy != nil {
err := this.Web.Init()
err := this.ReverseProxy.Init()
if err != nil {
return err
}

View File

@@ -1,5 +1,7 @@
package serverconfigs
import "github.com/TeaOSLab/EdgeCommon/pkg/configutils"
// Web文档目录配置
type HTTPRootConfig struct {
IsPrior bool `yaml:"isPrior" json:"isPrior"` // 是否优先
@@ -9,9 +11,17 @@ type HTTPRootConfig struct {
StripPrefix string `yaml:"stripPrefix" json:"stripPrefix"` // 去除前缀
DecodePath bool `yaml:"decodePath" json:"decodePath"` // 是否对请求路径进行解码
IsBreak bool `yaml:"isBreak" json:"isBreak"` // 找不到文件的情况下是否终止
hasVariables bool
}
// 初始化
func (ths *HTTPRootConfig) Init() error {
func (this *HTTPRootConfig) Init() error {
this.hasVariables = configutils.HasVariables(this.Dir)
return nil
}
// 判断是否有变量
func (this *HTTPRootConfig) HasVariables() bool {
return this.hasVariables
}

View File

@@ -0,0 +1,43 @@
package serverconfigs
import (
"github.com/iwind/TeaGo/assert"
"testing"
)
func TestHTTPRootConfig_HasVariables(t *testing.T) {
a := assert.NewAssertion(t)
{
rootConfig := &HTTPRootConfig{
Dir: "",
}
err := rootConfig.Init()
if err != nil {
t.Fatal(err)
}
a.IsFalse(rootConfig.HasVariables())
}
{
rootConfig := &HTTPRootConfig{
Dir: "/home/www",
}
err := rootConfig.Init()
if err != nil {
t.Fatal(err)
}
a.IsFalse(rootConfig.HasVariables())
}
{
rootConfig := &HTTPRootConfig{
Dir: "/home/www/${prefix}/world",
}
err := rootConfig.Init()
if err != nil {
t.Fatal(err)
}
a.IsTrue(rootConfig.HasVariables())
}
}

View File

@@ -3,7 +3,6 @@ package serverconfigs
import (
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/maps"
"time"
)
@@ -15,21 +14,16 @@ type HTTPWebsocketConfig struct {
// 握手超时时间
HandshakeTimeout *shared.TimeDuration `yaml:"handshakeTimeout" json:"handshakeTimeout"`
// 允许的域名,支持 www.example.com, example.com, .example.com, *.example.com
// 允许的来源域名,支持 www.example.com, example.com, .example.com, *.example.com
AllowAllOrigins bool `yaml:"allowAllOrigins" json:"allowAllOrigins"`
Origins []string `yaml:"origins" json:"origins"`
AllowedOrigins []string `yaml:"allowedOrigins" json:"allowedOrigins"`
// 转发方式
ForwardMode HTTPWebsocketForwardMode `yaml:"forwardMode" json:"forwardMode"`
// 向后传递的来源
RequestSameOrigin bool `yaml:"requestSameOrigin" json:"requestSameOrigin"` // 和请求一致
RequestOrigin string `yaml:"requestOrigin" json:"requestOrigin"` // 自行指定Origin支持变量
handshakeTimeoutDuration time.Duration
}
// 获取新对象
func NewHTTPWebsocketConfig() *HTTPWebsocketConfig {
return &HTTPWebsocketConfig{
IsOn: true,
}
handshakeTimeoutDuration time.Duration
requestOriginHasVariables bool
}
// 校验
@@ -39,6 +33,9 @@ func (this *HTTPWebsocketConfig) Init() error {
this.handshakeTimeoutDuration = this.HandshakeTimeout.Duration()
}
// requestOrigin
this.requestOriginHasVariables = configutils.HasVariables(this.RequestOrigin)
return nil
}
@@ -47,20 +44,15 @@ func (this *HTTPWebsocketConfig) HandshakeTimeoutDuration() time.Duration {
return this.handshakeTimeoutDuration
}
// 转发模式名称
func (this *HTTPWebsocketConfig) ForwardModeSummary() maps.Map {
for _, mode := range AllWebsocketForwardModes() {
if mode["mode"] == this.ForwardMode {
return mode
}
}
return nil
}
// 匹配域名
func (this *HTTPWebsocketConfig) MatchOrigin(origin string) bool {
if this.AllowAllOrigins {
return true
}
return configutils.MatchDomains(this.Origins, origin)
return configutils.MatchDomains(this.AllowedOrigins, origin)
}
// 判断请求Origin是否有变量
func (this *HTTPWebsocketConfig) RequestOriginHasVariables() bool {
return this.requestOriginHasVariables
}

View File

@@ -1,27 +0,0 @@
package serverconfigs
import "github.com/iwind/TeaGo/maps"
// Websocket转发类型
type HTTPWebsocketForwardMode = string
const (
HTTPWebsocketForwardModeWebsocket = "websocket"
HTTPWebsocketForwardModeHttp = "http"
)
// 所有的转发方式
func AllWebsocketForwardModes() []maps.Map {
return []maps.Map{
{
"name": "Websocket连接",
"mode": HTTPWebsocketForwardModeWebsocket,
"description": "通过Websocket连接后端服务器并发送数据",
},
{
"name": "HTTP连接",
"mode": HTTPWebsocketForwardModeHttp,
"description": "通过HTTP PUT转发服务器到后端服务器",
},
}
}

View File

@@ -1,12 +1,9 @@
package serverconfigs
import (
"crypto/tls"
"errors"
"fmt"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
"net"
"strconv"
"strings"
"time"
@@ -96,12 +93,24 @@ func (this *OriginConfig) Init() error {
}
// Headers
if this.RequestHeaderPolicyRef != nil {
err := this.RequestHeaderPolicyRef.Init()
if err != nil {
return err
}
}
if this.RequestHeaderPolicy != nil {
err := this.RequestHeaderPolicy.Init()
if err != nil {
return err
}
}
if this.ResponseHeaderPolicyRef != nil {
err := this.ResponseHeaderPolicyRef.Init()
if err != nil {
return err
}
}
if this.ResponseHeaderPolicy != nil {
err := this.ResponseHeaderPolicy.Init()
if err != nil {
@@ -150,31 +159,6 @@ func (this *OriginConfig) CandidateWeight() uint {
return this.Weight
}
// 连接源站
func (this *OriginConfig) Connect() (net.Conn, error) {
if this.Addr == nil {
return nil, errors.New("origin server address should not be empty")
}
switch this.Addr.Protocol {
case "", ProtocolTCP:
// TODO 支持TCP4/TCP6
// TODO 支持指定特定网卡
// TODO Addr支持端口范围如果有多个端口时随机一个端口使用
return net.DialTimeout("tcp", this.Addr.Host+":"+this.Addr.PortRange, this.connTimeoutDuration)
case ProtocolTLS:
// TODO 支持TCP4/TCP6
// TODO 支持指定特定网卡
// TODO Addr支持端口范围如果有多个端口时随机一个端口使用
// TODO 支持使用证书
return tls.Dial("tcp", this.Addr.Host+":"+this.Addr.PortRange, &tls.Config{})
}
// TODO 支持从Unix、Pipe、HTTP、HTTPS中读取数据
return nil, errors.New("invalid scheme '" + this.Addr.Protocol.String() + "'")
}
// 获取最终请求的地址
func (this *OriginConfig) RealAddr() string {
return this.realAddr
@@ -184,3 +168,8 @@ func (this *OriginConfig) RealAddr() string {
func (this *OriginConfig) SetRealAddr(realAddr string) {
this.realAddr = realAddr
}
// 连接超时时间
func (this *OriginConfig) ConnTimeoutDuration() time.Duration {
return this.connTimeoutDuration
}

View File

@@ -16,6 +16,8 @@ type ReverseProxyConfig struct {
BackupOriginRefs []*OriginRef `yaml:"backupOriginRefs" json:"backupOriginRefs"` // 备用源站引用
Scheduling *SchedulingConfig `yaml:"scheduling" json:"scheduling"` // 调度算法选项
// TODO 可以设置同后端交互的主机名Host并支持变量
hasPrimaryOrigins bool
hasBackupOrigins bool
schedulingIsBackup bool

View File

@@ -6,3 +6,8 @@ type ReverseProxyRef struct {
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
ReverseProxyId int64 `yaml:"reverseProxyId" json:"reverseProxyId"` // 反向代理ID
}
// 初始化
func (this *ReverseProxyRef) Init() error {
return nil
}

View File

@@ -84,6 +84,13 @@ func (this *ServerConfig) Init() error {
}
}
if this.ReverseProxyRef != nil {
err := this.ReverseProxyRef.Init()
if err != nil {
return err
}
}
if this.ReverseProxy != nil {
err := this.ReverseProxy.Init()
if err != nil {

View File

@@ -1,11 +1,9 @@
package shared
import (
"regexp"
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
)
var regexpNamedVariable = regexp.MustCompile("\\${[\\w.-]+}")
// 头部信息定义
type HTTPHeaderConfig struct {
Id int64 `yaml:"id" json:"id"` // ID
@@ -26,7 +24,7 @@ func NewHeaderConfig() *HTTPHeaderConfig {
// 校验
func (this *HTTPHeaderConfig) Init() error {
this.hasVariables = regexpNamedVariable.MatchString(this.Value)
this.hasVariables = configutils.HasVariables(this.Value)
if this.Status != nil {
err := this.Status.Init()