mirror of
https://github.com/fatedier/frp.git
synced 2024-12-13 10:11:04 +01:00
utils/vhost: update for vhost_https
This commit is contained in:
parent
0a50c3bd82
commit
b14441d5cd
@ -21,12 +21,14 @@ bind_addr = 0.0.0.0
|
|||||||
listen_port = 6000
|
listen_port = 6000
|
||||||
|
|
||||||
[web01]
|
[web01]
|
||||||
type = https
|
# if type equals http, vhost_http_port must be set
|
||||||
|
type = http
|
||||||
auth_token = 123
|
auth_token = 123
|
||||||
# if proxy type equals http, custom_domains must be set separated by commas
|
# if proxy type equals http, custom_domains must be set separated by commas
|
||||||
custom_domains = web01.yourdomain.com,web01.yourdomain2.com
|
custom_domains = web01.yourdomain.com,web01.yourdomain2.com
|
||||||
|
|
||||||
[web02]
|
[web02]
|
||||||
type = http
|
# if type equals https, vhost_https_port must be set
|
||||||
|
type = https
|
||||||
auth_token = 123
|
auth_token = 123
|
||||||
custom_domains = web02.yourdomain.com
|
custom_domains = web02.yourdomain.com
|
||||||
|
@ -225,11 +225,16 @@ func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if vhost_port is set
|
// check if vhost_port is set
|
||||||
if s.Type == "http" && server.VhostMuxer == nil {
|
if s.Type == "http" && server.VhostHttpMuxer == nil {
|
||||||
info = fmt.Sprintf("ProxyName [%s], type [http] not support when vhost_http_port is not set", req.ProxyName)
|
info = fmt.Sprintf("ProxyName [%s], type [http] not support when vhost_http_port is not set", req.ProxyName)
|
||||||
log.Warn(info)
|
log.Warn(info)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if s.Type == "https" && server.VhostHttpsMuxer == nil {
|
||||||
|
info = fmt.Sprintf("ProxyName [%s], type [https] not support when vhost_https_port is not set", req.ProxyName)
|
||||||
|
log.Warn(info)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// set infomations from frpc
|
// set infomations from frpc
|
||||||
s.UseEncryption = req.UseEncryption
|
s.UseEncryption = req.UseEncryption
|
||||||
|
@ -31,8 +31,8 @@ var (
|
|||||||
ConfigFile string = "./frps.ini"
|
ConfigFile string = "./frps.ini"
|
||||||
BindAddr string = "0.0.0.0"
|
BindAddr string = "0.0.0.0"
|
||||||
BindPort int64 = 7000
|
BindPort int64 = 7000
|
||||||
VhostHttpPort int64 = 0 // if VhostHttpPort equals 0, don't listen a public port for http
|
VhostHttpPort int64 = 0 // if VhostHttpPort equals 0, don't listen a public port for http protocol
|
||||||
VhostHttpsPort int64 = 0 // if VhostHttpsPort equals 0, don't listen a public port for http
|
VhostHttpsPort int64 = 0 // if VhostHttpsPort equals 0, don't listen a public port for https protocol
|
||||||
DashboardPort int64 = 0 // if DashboardPort equals 0, dashboard is not available
|
DashboardPort int64 = 0 // if DashboardPort equals 0, dashboard is not available
|
||||||
LogFile string = "console"
|
LogFile string = "console"
|
||||||
LogWay string = "console" // console or file
|
LogWay string = "console" // console or file
|
||||||
@ -102,7 +102,6 @@ func loadCommonConf(confFile string) error {
|
|||||||
} else {
|
} else {
|
||||||
VhostHttpsPort = 0
|
VhostHttpsPort = 0
|
||||||
}
|
}
|
||||||
vhost.VhostHttpsPort = VhostHttpsPort
|
|
||||||
|
|
||||||
tmpStr, ok = conf.Get("common", "dashboard_port")
|
tmpStr, ok = conf.Get("common", "dashboard_port")
|
||||||
if ok {
|
if ok {
|
||||||
@ -183,34 +182,25 @@ func loadProxyConf(confFile string) (proxyServers map[string]*ProxyServer, err e
|
|||||||
// for http
|
// for http
|
||||||
domainStr, ok := section["custom_domains"]
|
domainStr, ok := section["custom_domains"]
|
||||||
if ok {
|
if ok {
|
||||||
var suffix string
|
|
||||||
if VhostHttpPort != 80 {
|
|
||||||
suffix = fmt.Sprintf(":%d", VhostHttpPort)
|
|
||||||
}
|
|
||||||
proxyServer.CustomDomains = strings.Split(domainStr, ",")
|
proxyServer.CustomDomains = strings.Split(domainStr, ",")
|
||||||
if len(proxyServer.CustomDomains) == 0 {
|
if len(proxyServer.CustomDomains) == 0 {
|
||||||
return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals http", proxyServer.Name)
|
return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals http", proxyServer.Name)
|
||||||
}
|
}
|
||||||
for i, domain := range proxyServer.CustomDomains {
|
for i, domain := range proxyServer.CustomDomains {
|
||||||
proxyServer.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain)) + suffix
|
proxyServer.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if proxyServer.Type == "https" {
|
} else if proxyServer.Type == "https" {
|
||||||
// for https
|
// for https
|
||||||
domainStr, ok := section["custom_domains"]
|
domainStr, ok := section["custom_domains"]
|
||||||
if ok {
|
if ok {
|
||||||
var suffix string
|
|
||||||
if VhostHttpsPort != 443 {
|
|
||||||
suffix = fmt.Sprintf(":%d", VhostHttpsPort)
|
|
||||||
}
|
|
||||||
proxyServer.CustomDomains = strings.Split(domainStr, ",")
|
proxyServer.CustomDomains = strings.Split(domainStr, ",")
|
||||||
if len(proxyServer.CustomDomains) == 0 {
|
if len(proxyServer.CustomDomains) == 0 {
|
||||||
return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals http", proxyServer.Name)
|
return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals https", proxyServer.Name)
|
||||||
}
|
}
|
||||||
for i, domain := range proxyServer.CustomDomains {
|
for i, domain := range proxyServer.CustomDomains {
|
||||||
proxyServer.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain)) + suffix
|
proxyServer.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain))
|
||||||
}
|
}
|
||||||
log.Info("proxyServer: %+v", proxyServer.CustomDomains)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
proxyServers[proxyServer.Name] = proxyServer
|
proxyServers[proxyServer.Name] = proxyServer
|
||||||
|
47
src/frp/utils/vhost/http.go
Normal file
47
src/frp/utils/vhost/http.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package vhost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"frp/utils/conn"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HttpMuxer struct {
|
||||||
|
*VhostMuxer
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetHttpHostname(c *conn.Conn) (_ net.Conn, routerName string, err error) {
|
||||||
|
sc, rd := newShareConn(c.TcpConn)
|
||||||
|
|
||||||
|
request, err := http.ReadRequest(bufio.NewReader(rd))
|
||||||
|
if err != nil {
|
||||||
|
return sc, "", err
|
||||||
|
}
|
||||||
|
tmpArr := strings.Split(request.Host, ":")
|
||||||
|
routerName = tmpArr[0]
|
||||||
|
request.Body.Close()
|
||||||
|
return sc, routerName, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHttpMuxer(listener *conn.Listener, timeout time.Duration) (*HttpMuxer, error) {
|
||||||
|
mux, err := NewVhostMuxer(listener, GetHttpHostname, timeout)
|
||||||
|
return &HttpMuxer{mux}, err
|
||||||
|
}
|
@ -15,25 +15,13 @@
|
|||||||
package vhost
|
package vhost
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "bufio"
|
|
||||||
_ "bytes"
|
|
||||||
_ "crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"frp/utils/conn"
|
|
||||||
"frp/utils/log"
|
|
||||||
"io"
|
"io"
|
||||||
_ "io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
_ "net/http"
|
|
||||||
"strings"
|
"strings"
|
||||||
_ "sync"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
"frp/utils/conn"
|
||||||
maxHandshake int64 = 65536 // maximum handshake we support (protocol max is 16 MB)
|
|
||||||
VhostHttpsPort int64 = 443
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -58,160 +46,140 @@ type HttpsMuxer struct {
|
|||||||
*VhostMuxer
|
*VhostMuxer
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func NewHttpsMuxer(listener *conn.Listener, timeout time.Duration) (*HttpsMuxer, error) {
|
||||||
RFC document: http://tools.ietf.org/html/rfc5246
|
mux, err := NewVhostMuxer(listener, GetHttpsHostname, timeout)
|
||||||
*/
|
return &HttpsMuxer{mux}, err
|
||||||
|
|
||||||
func errMsgToLog(format string, a ...interface{}) error {
|
|
||||||
errMsg := fmt.Sprintf(format, a...)
|
|
||||||
log.Warn(errMsg)
|
|
||||||
return errors.New(errMsg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func readHandshake(rd io.Reader) (string, error) {
|
func readHandshake(rd io.Reader) (host string, err error) {
|
||||||
|
|
||||||
data := make([]byte, 1024)
|
data := make([]byte, 1024)
|
||||||
length, err := rd.Read(data)
|
length, err := rd.Read(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errMsgToLog("read err:%v", err)
|
return
|
||||||
} else {
|
} else {
|
||||||
if length < 47 {
|
if length < 47 {
|
||||||
return "", errMsgToLog("readHandshake: proto length[%d] is too short", length)
|
err = fmt.Errorf("readHandshake: proto length[%d] is too short", length)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data = data[:length]
|
data = data[:length]
|
||||||
//log.Warn("data: %+v", data)
|
|
||||||
if uint8(data[5]) != typeClientHello {
|
if uint8(data[5]) != typeClientHello {
|
||||||
return "", errMsgToLog("readHandshake: type[%d] is not clientHello", uint16(data[5]))
|
err = fmt.Errorf("readHandshake: type[%d] is not clientHello", uint16(data[5]))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//version and random
|
// session
|
||||||
//tlsVersion := uint16(data[9])<<8 | uint16(data[10])
|
|
||||||
//random := data[11:43]
|
|
||||||
|
|
||||||
//session
|
|
||||||
sessionIdLen := int(data[43])
|
sessionIdLen := int(data[43])
|
||||||
if sessionIdLen > 32 || len(data) < 44+sessionIdLen {
|
if sessionIdLen > 32 || len(data) < 44+sessionIdLen {
|
||||||
return "", errMsgToLog("readHandshake: sessionIdLen[%d] is long", sessionIdLen)
|
err = fmt.Errorf("readHandshake: sessionIdLen[%d] is long", sessionIdLen)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
data = data[44+sessionIdLen:]
|
data = data[44+sessionIdLen:]
|
||||||
if len(data) < 2 {
|
if len(data) < 2 {
|
||||||
return "", errMsgToLog("readHandshake: dataLen[%d] after session is short", len(data))
|
err = fmt.Errorf("readHandshake: dataLen[%d] after session is short", len(data))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// cipher suite numbers
|
// cipher suite numbers
|
||||||
cipherSuiteLen := int(data[0])<<8 | int(data[1])
|
cipherSuiteLen := int(data[0])<<8 | int(data[1])
|
||||||
if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
|
if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
|
||||||
//return "", errMsgToLog("readHandshake: cipherSuiteLen[%d] is long", sessionIdLen)
|
err = fmt.Errorf("readHandshake: dataLen[%d] after cipher suite is short", len(data))
|
||||||
return "", errMsgToLog("readHandshake: dataLen[%d] after cipher suite is short", len(data))
|
return
|
||||||
}
|
}
|
||||||
data = data[2+cipherSuiteLen:]
|
data = data[2+cipherSuiteLen:]
|
||||||
if len(data) < 1 {
|
if len(data) < 1 {
|
||||||
return "", errMsgToLog("readHandshake: cipherSuiteLen[%d] is long", cipherSuiteLen)
|
err = fmt.Errorf("readHandshake: cipherSuiteLen[%d] is long", cipherSuiteLen)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//compression method
|
// compression method
|
||||||
compressionMethodsLen := int(data[0])
|
compressionMethodsLen := int(data[0])
|
||||||
if len(data) < 1+compressionMethodsLen {
|
if len(data) < 1+compressionMethodsLen {
|
||||||
return "", errMsgToLog("readHandshake: compressionMethodsLen[%d] is long", compressionMethodsLen)
|
err = fmt.Errorf("readHandshake: compressionMethodsLen[%d] is long", compressionMethodsLen)
|
||||||
//return false
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data = data[1+compressionMethodsLen:]
|
data = data[1+compressionMethodsLen:]
|
||||||
|
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
// ClientHello is optionally followed by extension data
|
// ClientHello is optionally followed by extension data
|
||||||
//return true
|
err = fmt.Errorf("readHandshake: there is no extension data to get servername")
|
||||||
return "", errMsgToLog("readHandshake: there is no extension data to get servername")
|
return
|
||||||
}
|
}
|
||||||
if len(data) < 2 {
|
if len(data) < 2 {
|
||||||
return "", errMsgToLog("readHandshake: extension dataLen[%d] is too short")
|
err = fmt.Errorf("readHandshake: extension dataLen[%d] is too short")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
extensionsLength := int(data[0])<<8 | int(data[1])
|
extensionsLength := int(data[0])<<8 | int(data[1])
|
||||||
data = data[2:]
|
data = data[2:]
|
||||||
if extensionsLength != len(data) {
|
if extensionsLength != len(data) {
|
||||||
return "", errMsgToLog("readHandshake: extensionsLen[%d] is not equal to dataLen[%d]", extensionsLength, len(data))
|
err = fmt.Errorf("readHandshake: extensionsLen[%d] is not equal to dataLen[%d]", extensionsLength, len(data))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
for len(data) != 0 {
|
for len(data) != 0 {
|
||||||
if len(data) < 4 {
|
if len(data) < 4 {
|
||||||
return "", errMsgToLog("readHandshake: extensionsDataLen[%d] is too short", len(data))
|
err = fmt.Errorf("readHandshake: extensionsDataLen[%d] is too short", len(data))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
extension := uint16(data[0])<<8 | uint16(data[1])
|
extension := uint16(data[0])<<8 | uint16(data[1])
|
||||||
length := int(data[2])<<8 | int(data[3])
|
length := int(data[2])<<8 | int(data[3])
|
||||||
data = data[4:]
|
data = data[4:]
|
||||||
if len(data) < length {
|
if len(data) < length {
|
||||||
return "", errMsgToLog("readHandshake: extensionLen[%d] is long", length)
|
err = fmt.Errorf("readHandshake: extensionLen[%d] is long", length)
|
||||||
//return false
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch extension {
|
switch extension {
|
||||||
case extensionRenegotiationInfo:
|
case extensionRenegotiationInfo:
|
||||||
if length != 1 || data[0] != 0 {
|
if length != 1 || data[0] != 0 {
|
||||||
return "", errMsgToLog("readHandshake: extension reNegotiationInfoLen[%d] is short", length)
|
err = fmt.Errorf("readHandshake: extension reNegotiationInfoLen[%d] is short", length)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
case extensionNextProtoNeg:
|
case extensionNextProtoNeg:
|
||||||
case extensionStatusRequest:
|
case extensionStatusRequest:
|
||||||
case extensionServerName:
|
case extensionServerName:
|
||||||
d := data[:length]
|
d := data[:length]
|
||||||
if len(d) < 2 {
|
if len(d) < 2 {
|
||||||
return "", errMsgToLog("readHandshake: remiaining dataLen[%d] is short", len(d))
|
err = fmt.Errorf("readHandshake: remiaining dataLen[%d] is short", len(d))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
namesLen := int(d[0])<<8 | int(d[1])
|
namesLen := int(d[0])<<8 | int(d[1])
|
||||||
d = d[2:]
|
d = d[2:]
|
||||||
if len(d) != namesLen {
|
if len(d) != namesLen {
|
||||||
return "", errMsgToLog("readHandshake: nameListLen[%d] is not equal to dataLen[%d]", namesLen, len(d))
|
err = fmt.Errorf("readHandshake: nameListLen[%d] is not equal to dataLen[%d]", namesLen, len(d))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
for len(d) > 0 {
|
for len(d) > 0 {
|
||||||
if len(d) < 3 {
|
if len(d) < 3 {
|
||||||
return "", errMsgToLog("readHandshake: extension serverNameLen[%d] is short", len(d))
|
err = fmt.Errorf("readHandshake: extension serverNameLen[%d] is short", len(d))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
nameType := d[0]
|
nameType := d[0]
|
||||||
nameLen := int(d[1])<<8 | int(d[2])
|
nameLen := int(d[1])<<8 | int(d[2])
|
||||||
d = d[3:]
|
d = d[3:]
|
||||||
if len(d) < nameLen {
|
if len(d) < nameLen {
|
||||||
return "", errMsgToLog("readHandshake: nameLen[%d] is not equal to dataLen[%d]", nameLen, len(d))
|
err = fmt.Errorf("readHandshake: nameLen[%d] is not equal to dataLen[%d]", nameLen, len(d))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if nameType == 0 {
|
if nameType == 0 {
|
||||||
suffix := ""
|
|
||||||
if VhostHttpsPort != 443 {
|
|
||||||
suffix = fmt.Sprintf(":%d", VhostHttpsPort)
|
|
||||||
}
|
|
||||||
serverName := string(d[:nameLen])
|
serverName := string(d[:nameLen])
|
||||||
domain := strings.ToLower(strings.TrimSpace(serverName)) + suffix
|
host = strings.TrimSpace(serverName)
|
||||||
return domain, nil
|
return host, nil
|
||||||
break
|
|
||||||
}
|
}
|
||||||
d = d[nameLen:]
|
d = d[nameLen:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data = data[length:]
|
data = data[length:]
|
||||||
}
|
}
|
||||||
//return "test.codermao.com:8082", nil
|
err = fmt.Errorf("Unknow error")
|
||||||
return "", errMsgToLog("Unknow error")
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHttpsHostname(c *conn.Conn) (sc net.Conn, routerName string, err error) {
|
func GetHttpsHostname(c *conn.Conn) (sc net.Conn, routerName string, err error) {
|
||||||
log.Info("GetHttpsHostname")
|
|
||||||
sc, rd := newShareConn(c.TcpConn)
|
sc, rd := newShareConn(c.TcpConn)
|
||||||
|
|
||||||
host, err := readHandshake(rd)
|
host, err := readHandshake(rd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sc, "", err
|
return sc, "", err
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if _, ok := c.TcpConn.(*tls.Conn); ok {
|
|
||||||
log.Warn("convert to tlsConn success")
|
|
||||||
} else {
|
|
||||||
log.Warn("convert to tlsConn error")
|
|
||||||
}*/
|
|
||||||
//tcpConn.
|
|
||||||
log.Debug("GetHttpsHostname: %s", host)
|
|
||||||
|
|
||||||
return sc, host, nil
|
return sc, host, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHttpsMuxer(listener *conn.Listener, timeout time.Duration) (*HttpsMuxer, error) {
|
|
||||||
mux, err := NewVhostMuxer(listener, GetHttpsHostname, timeout)
|
|
||||||
return &HttpsMuxer{mux}, err
|
|
||||||
}
|
|
@ -15,12 +15,10 @@
|
|||||||
package vhost
|
package vhost
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -99,7 +97,6 @@ func (v *VhostMuxer) handle(c *conn.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
name = strings.ToLower(name)
|
name = strings.ToLower(name)
|
||||||
|
|
||||||
l, ok := v.getListener(name)
|
l, ok := v.getListener(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
@ -113,28 +110,6 @@ func (v *VhostMuxer) handle(c *conn.Conn) {
|
|||||||
l.accept <- c
|
l.accept <- c
|
||||||
}
|
}
|
||||||
|
|
||||||
type HttpMuxer struct {
|
|
||||||
*VhostMuxer
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetHttpHostname(c *conn.Conn) (_ net.Conn, routerName string, err error) {
|
|
||||||
sc, rd := newShareConn(c.TcpConn)
|
|
||||||
|
|
||||||
request, err := http.ReadRequest(bufio.NewReader(rd))
|
|
||||||
if err != nil {
|
|
||||||
return sc, "", err
|
|
||||||
}
|
|
||||||
routerName = request.Host
|
|
||||||
request.Body.Close()
|
|
||||||
|
|
||||||
return sc, routerName, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHttpMuxer(listener *conn.Listener, timeout time.Duration) (*HttpMuxer, error) {
|
|
||||||
mux, err := NewVhostMuxer(listener, GetHttpHostname, timeout)
|
|
||||||
return &HttpMuxer{mux}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
name string
|
name string
|
||||||
mux *VhostMuxer // for closing VhostMuxer
|
mux *VhostMuxer // for closing VhostMuxer
|
||||||
|
Loading…
Reference in New Issue
Block a user