mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-05 00:34:01 +08:00
反向代理支持RequestPath、RequestURI等
This commit is contained in:
@@ -727,7 +727,6 @@ func (this *HTTPRequest) setForwardHeaders(header http.Header) {
|
||||
}
|
||||
|
||||
// 处理自定义Request Header
|
||||
// TODO 处理一些被Golang转换了的Header,比如Websocket
|
||||
func (this *HTTPRequest) processRequestHeaders(reqHeader http.Header) {
|
||||
if this.web.RequestHeaderPolicy != nil && this.web.RequestHeaderPolicy.IsOn {
|
||||
// 删除某些Header
|
||||
@@ -768,6 +767,18 @@ func (this *HTTPRequest) processRequestHeaders(reqHeader http.Header) {
|
||||
}
|
||||
}
|
||||
|
||||
// 处理一些被Golang转换了的Header
|
||||
// TODO 可以自定义要转换的Header
|
||||
func (this *HTTPRequest) fixRequestHeader(header http.Header) {
|
||||
for k, v := range header {
|
||||
if strings.Contains(k, "-Websocket-") {
|
||||
header.Del(k)
|
||||
k = strings.ReplaceAll(k, "-Websocket-", "-WebSocket-")
|
||||
header[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理自定义Response Header
|
||||
func (this *HTTPRequest) processResponseHeaders(statusCode int) {
|
||||
responseHeader := this.writer.Header()
|
||||
|
||||
@@ -1,7 +1,72 @@
|
||||
package nodes
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 处理反向代理
|
||||
func (this *HTTPRequest) doReverseProxy() {
|
||||
if this.reverseProxy == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// StripPrefix
|
||||
if len(this.reverseProxy.StripPrefix) > 0 {
|
||||
stripPrefix := this.reverseProxy.StripPrefix
|
||||
if stripPrefix[0] != '/' {
|
||||
stripPrefix = "/" + stripPrefix
|
||||
}
|
||||
this.uri = strings.TrimPrefix(this.uri, stripPrefix)
|
||||
if len(this.uri) == 0 || this.uri[0] != '/' {
|
||||
this.uri = "/" + this.uri
|
||||
}
|
||||
}
|
||||
|
||||
// RequestURI
|
||||
if len(this.reverseProxy.RequestURI) > 0 {
|
||||
if this.reverseProxy.RequestURIHasVariables() {
|
||||
this.uri = this.Format(this.reverseProxy.RequestURI)
|
||||
} else {
|
||||
this.uri = this.reverseProxy.RequestURI
|
||||
}
|
||||
if len(this.uri) == 0 || this.uri[0] != '/' {
|
||||
this.uri = "/" + this.uri
|
||||
}
|
||||
|
||||
// 处理RequestURI中的问号
|
||||
questionMark := strings.LastIndex(this.uri, "?")
|
||||
if questionMark > 0 {
|
||||
path := this.uri[:questionMark]
|
||||
if strings.Contains(path, "?") {
|
||||
this.uri = path + "&" + this.uri[questionMark+1:]
|
||||
}
|
||||
}
|
||||
|
||||
// 去除多个/
|
||||
this.uri = utils.CleanPath(this.uri)
|
||||
}
|
||||
|
||||
// 重组请求URL
|
||||
questionMark := strings.Index(this.uri, "?")
|
||||
if questionMark > -1 {
|
||||
this.RawReq.URL.Path = this.uri[:questionMark]
|
||||
this.RawReq.URL.RawQuery = this.uri[questionMark+1:]
|
||||
} else {
|
||||
this.RawReq.URL.Path = this.uri
|
||||
this.RawReq.URL.RawQuery = ""
|
||||
}
|
||||
|
||||
// RequestHost
|
||||
if len(this.reverseProxy.RequestHost) > 0 {
|
||||
if this.reverseProxy.RequestHostHasVariables() {
|
||||
this.RawReq.Host = this.Format(this.reverseProxy.RequestHost)
|
||||
} else {
|
||||
this.RawReq.Host = this.reverseProxy.RequestHost
|
||||
}
|
||||
this.RawReq.URL.Host = this.RawReq.Host
|
||||
}
|
||||
|
||||
// 判断是否为Websocket请求
|
||||
if this.RawReq.Header.Get("Upgrade") == "websocket" {
|
||||
this.doWebsocket()
|
||||
@@ -11,4 +76,3 @@ func (this *HTTPRequest) doReverseProxy() {
|
||||
// 普通HTTP请求
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ func (this *HTTPRequest) doWebsocket() {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO 实现handshakeTimeout
|
||||
|
||||
// 校验来源
|
||||
requestOrigin := this.RawReq.Header.Get("Origin")
|
||||
if len(requestOrigin) > 0 {
|
||||
@@ -38,7 +40,9 @@ func (this *HTTPRequest) doWebsocket() {
|
||||
return
|
||||
}
|
||||
|
||||
// 处理Header
|
||||
this.processRequestHeaders(this.RawReq.Header)
|
||||
this.fixRequestHeader(this.RawReq.Header) // 处理 Websocket -> WebSocket
|
||||
|
||||
// 设置指定的来源域
|
||||
if !this.web.Websocket.RequestSameOrigin && len(this.web.Websocket.RequestOrigin) > 0 {
|
||||
@@ -49,11 +53,7 @@ func (this *HTTPRequest) doWebsocket() {
|
||||
this.RawReq.Header.Set("Origin", newRequestOrigin)
|
||||
}
|
||||
|
||||
// TODO 修改RequestURI
|
||||
// TODO 实现handshakeTimeout
|
||||
// TODO 修改 Websocket- 为 WebSocket-
|
||||
|
||||
// TODO 增加N次错误重试
|
||||
// TODO 增加N次错误重试,重试的时候需要尝试不同的源站
|
||||
originConn, err := OriginConnect(origin)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
|
||||
24
internal/utils/path.go
Normal file
24
internal/utils/path.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package utils
|
||||
|
||||
// 清理Path中的多余的字符
|
||||
func CleanPath(path string) string {
|
||||
l := len(path)
|
||||
if l == 0 {
|
||||
return "/"
|
||||
}
|
||||
result := []byte{'/'}
|
||||
isSlash := true
|
||||
for i := 0; i < l; i++ {
|
||||
if path[i] == '\\' || path[i] == '/' {
|
||||
if !isSlash {
|
||||
isSlash = true
|
||||
result = append(result, '/')
|
||||
}
|
||||
} else {
|
||||
isSlash = false
|
||||
result = append(result, path[i])
|
||||
}
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
|
||||
23
internal/utils/path_test.go
Normal file
23
internal/utils/path_test.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCleanPath(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
a.IsTrue(CleanPath("") == "/")
|
||||
a.IsTrue(CleanPath("/hello/world") == "/hello/world")
|
||||
a.IsTrue(CleanPath("\\hello\\world") == "/hello/world")
|
||||
a.IsTrue(CleanPath("/\\hello\\//world") == "/hello/world")
|
||||
a.IsTrue(CleanPath("hello/world") == "/hello/world")
|
||||
a.IsTrue(CleanPath("/hello////world") == "/hello/world")
|
||||
}
|
||||
|
||||
func BenchmarkCleanPath(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = CleanPath("/hello///world/very/long/very//long")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user