summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2023-10-09 00:19:42 +0900
committernsfisis <nsfisis@gmail.com>2023-10-09 00:19:42 +0900
commitd137a764d050e3d5296da2830a32f6d83bdb364f (patch)
treebee59ab913cd7fc03c8f1209aaa12d012dafe161
parent6f97769e4fc893e7607652e3cbfcf5698e2256f4 (diff)
downloadmioproxy-d137a764d050e3d5296da2830a32f6d83bdb364f.tar.gz
mioproxy-d137a764d050e3d5296da2830a32f6d83bdb364f.tar.zst
mioproxy-d137a764d050e3d5296da2830a32f6d83bdb364f.zip
support path-based proxy
-rw-r--r--conf.example.hcl21
-rw-r--r--config.go17
-rw-r--r--server.go16
3 files changed, 52 insertions, 2 deletions
diff --git a/conf.example.hcl b/conf.example.hcl
index 8f1a56c..dfe18f8 100644
--- a/conf.example.hcl
+++ b/conf.example.hcl
@@ -11,4 +11,25 @@ server http {
port = 8001
}
}
+
+ proxy b {
+ from {
+ path = "/b/"
+ }
+ to {
+ host = "127.0.0.1"
+ port = 8002
+ }
+ }
+
+ proxy c {
+ from {
+ host = "c.localhost"
+ path = "/c/"
+ }
+ to {
+ host = "127.0.0.1"
+ port = 8003
+ }
+ }
}
diff --git a/config.go b/config.go
index ed4b3e0..6ad988f 100644
--- a/config.go
+++ b/config.go
@@ -4,6 +4,7 @@ import (
"fmt"
"net/netip"
"net/url"
+ "strings"
"github.com/hashicorp/hcl/v2/hclsimple"
)
@@ -36,6 +37,7 @@ type ProxyConfig struct {
type ProxyFromConfig struct {
Host string
+ Path string
}
type ProxyToConfig struct {
@@ -70,7 +72,8 @@ type InternalHCLProxyConfig struct {
}
type InternalHCLProxyFromConfig struct {
- Host string `hcl:"host"`
+ Host string `hcl:"host,optional"`
+ Path string `hcl:"path,optional"`
}
type InternalHCLProxyToConfig struct {
@@ -93,6 +96,7 @@ func fromHCLConfigToConfig(hclConfig *InternalHCLConfig) *Config {
Name: p.Name,
From: ProxyFromConfig{
Host: p.From.Host,
+ Path: p.From.Path,
},
To: ProxyToConfig{
Host: p.To.Host,
@@ -180,6 +184,17 @@ func LoadConfig(fileName string) (*Config, error) {
}
for _, p := range server.Proxies {
+ if p.From.Path != "" {
+ if !strings.HasPrefix(p.From.Path, "/") {
+ return nil, fmt.Errorf("Path must start with '/'")
+ }
+ if !strings.HasSuffix(p.From.Path, "/") {
+ return nil, fmt.Errorf("Path must end with '/'")
+ }
+ }
+ if p.From.Host == "" && p.From.Path == "" {
+ return nil, fmt.Errorf("Either host or path must be specified")
+ }
_, err := url.Parse(fmt.Sprintf("http://%s:%d", p.To.Host, p.To.Port))
if err != nil {
return nil, fmt.Errorf("Invalid host or port: %s:%d", p.To.Host, p.To.Port)
diff --git a/server.go b/server.go
index 47c52dd..830a6e4 100644
--- a/server.go
+++ b/server.go
@@ -8,6 +8,7 @@ import (
"net/http"
"net/http/httputil"
"net/url"
+ "strings"
)
type multipleReverseProxyServer struct {
@@ -16,10 +17,22 @@ type multipleReverseProxyServer struct {
type rewriteRule struct {
fromHost string
+ fromPath string
toUrl *url.URL
proxy *httputil.ReverseProxy
}
+func (r *rewriteRule) matches(host, path string) bool {
+ ret := true
+ if r.fromHost != "" {
+ ret = ret && r.fromHost == host
+ }
+ if r.fromPath != "" {
+ ret = ret && strings.HasPrefix(path+"/", r.fromPath)
+ }
+ return ret
+}
+
func newMultipleReverseProxyServer(ps []ProxyConfig) *multipleReverseProxyServer {
var rules []rewriteRule
for _, p := range ps {
@@ -30,6 +43,7 @@ func newMultipleReverseProxyServer(ps []ProxyConfig) *multipleReverseProxyServer
}
rules = append(rules, rewriteRule{
fromHost: p.From.Host,
+ fromPath: p.From.Path,
toUrl: targetUrl,
proxy: &httputil.ReverseProxy{
Rewrite: func(r *httputil.ProxyRequest) {
@@ -50,7 +64,7 @@ func (s *multipleReverseProxyServer) tryServeHTTP(
hostWithoutPort string,
) bool {
for _, rule := range s.rules {
- if rule.fromHost == hostWithoutPort {
+ if rule.matches(hostWithoutPort, r.URL.Path) {
rule.proxy.ServeHTTP(w, r)
return true
}