@@ -19,6 +19,7 @@ package http
19
19
import (
20
20
"encoding/json"
21
21
"fmt"
22
+ "os"
22
23
23
24
"net/http"
24
25
"net/url"
@@ -27,29 +28,34 @@ import (
27
28
"k8s.io/klog/v2"
28
29
logf "sigs.k8s.io/controller-runtime/pkg/log"
29
30
31
+ "github.com/KusionStack/controller-mesh/pkg/apis/ctrlmesh/constants"
30
32
meshhttp "github.com/KusionStack/controller-mesh/pkg/apis/ctrlmesh/http"
33
+ "github.com/KusionStack/controller-mesh/pkg/proxy/circuitbreaker"
31
34
"github.com/KusionStack/controller-mesh/pkg/proxy/faultinjection"
32
35
"github.com/KusionStack/controller-mesh/pkg/utils"
33
36
utilshttp "github.com/KusionStack/controller-mesh/pkg/utils/http"
34
37
)
35
38
36
39
var (
37
- logger = logf .Log .WithName ("http-proxy" )
40
+ enableRestBreaker = os .Getenv (constants .EnvEnableRestCircuitBreaker ) == "true"
41
+ logger = logf .Log .WithName ("http-proxy" )
38
42
)
39
43
40
44
type ITProxy interface {
41
45
Start ()
42
46
}
43
47
44
48
type tproxy struct {
45
- port int
46
- FaultInjector faultinjection.ManagerInterface
49
+ port int
50
+ FaultInjector faultinjection.ManagerInterface
51
+ CircuitInjector circuitbreaker.ManagerInterface
47
52
}
48
53
49
- func NewTProxy (port int , faultInjector faultinjection.ManagerInterface ) ITProxy {
54
+ func NewTProxy (port int , faultInjector faultinjection.ManagerInterface , circuitInjector circuitbreaker. ManagerInterface ) ITProxy {
50
55
return & tproxy {
51
- port : port ,
52
- FaultInjector : faultInjector ,
56
+ port : port ,
57
+ FaultInjector : faultInjector ,
58
+ CircuitInjector : circuitInjector ,
53
59
}
54
60
}
55
61
@@ -59,7 +65,7 @@ func (t *tproxy) Start() {
59
65
Addr : fmt .Sprintf (":%d" , t .port ),
60
66
Handler : http .HandlerFunc (t .handleHTTP ),
61
67
}
62
- logger . Info ("%s" , server .ListenAndServe ())
68
+ klog . Infof ("%s" , server .ListenAndServe ())
63
69
}
64
70
65
71
func (t * tproxy ) handleHTTP (resp http.ResponseWriter , req * http.Request ) {
@@ -76,9 +82,10 @@ func (t *tproxy) handleHTTP(resp http.ResponseWriter, req *http.Request) {
76
82
return
77
83
}
78
84
realEndPointUrl = epUrl
79
- logger . Info ("receive" , " proxy-host" , realEndPointUrl . Host , " proxy-method" , req . Method , " Mesh-Real-Endpoint" , realEp )
85
+ klog . Infof ("receive, proxy-host: %s, proxy-method: %s, Mesh-Real-Endpoint: %s" , realEndPointUrl . Host , req . Method , realEp )
80
86
}
81
- logger .Info ("handel http request" , "url" , realEndPointUrl .String ())
87
+ klog .Infof ("handel http request, url: %s " , realEndPointUrl .String ())
88
+ // faultinjection
82
89
result := t .FaultInjector .FaultInjectionRest (req .Header .Get (meshhttp .HeaderMeshRealEndpoint ), req .Method )
83
90
if result .Abort {
84
91
apiErr := utils .HttpToAPIError (int (result .ErrCode ), req .Method , result .Message )
@@ -87,10 +94,35 @@ func (t *tproxy) handleHTTP(resp http.ResponseWriter, req *http.Request) {
87
94
if err := json .NewEncoder (resp ).Encode (apiErr ); err != nil {
88
95
http .Error (resp , fmt .Sprintf ("fail to inject fault %v" , err ), http .StatusInternalServerError )
89
96
}
90
- logger . Info ("faultInjection rule" , " rule" , fmt .Sprintf ("fault injection, %s, %s,%d" , result .Reason , result .Message , result .ErrCode ))
97
+ klog . Infof ("faultInjection rule, rule: %s " , fmt .Sprintf ("fault injection, %s, %s,%d" , result .Reason , result .Message , result .ErrCode ))
91
98
return
92
99
}
93
100
101
+ // circuitbreaker
102
+ if enableRestBreaker {
103
+ // check request is in the whitelist
104
+ klog .Infof ("start checktrafficrule %s" , realEndPointUrl .Host )
105
+ result := t .CircuitInjector .ValidateTrafficIntercept (realEndPointUrl .Host , req .Method )
106
+ if ! result .Allowed {
107
+ klog .Infof ("ErrorTProxy: %s %s ValidateTrafficIntercept NOPASSED ,checkresult:\t %s" , realEndPointUrl .Host , req .Method , result .Reason )
108
+ http .Error (resp , fmt .Sprintf ("Forbidden by ValidateTrafficIntercept breaker, %s, %s" , result .Message , result .Reason ), http .StatusForbidden )
109
+ return
110
+ }
111
+ }
112
+
113
+ // ValidateTrafficIntercept check pass or enableRestBreaker is false run http proxy
114
+ klog .Infof ("TProxy: %s %s ValidateTrafficIntercept check PASSED or enableRestBreaker is false" , realEndPointUrl .Host , req .Method )
115
+
116
+ // ValidateRest check
117
+ klog .Infof ("start ValidateRest checkrule %s %s" , realEndPointUrl .Host , req .Method )
118
+ validateresult := t .CircuitInjector .ValidateRest (req .Header .Get ("Mesh-Real-Endpoint" ), req .Method )
119
+ if ! validateresult .Allowed {
120
+ klog .Infof ("ErrorTProxy: %s %s ValidateRest NOPASSED ,checkresult:%t, validateresultReason:%s" , req .Header .Get ("Mesh-Real-Endpoint" ), req .Method , validateresult .Allowed , validateresult .Reason )
121
+ http .Error (resp , fmt .Sprintf ("Forbidden by circuit ValidateRest breaker, %s, %s" , validateresult .Message , validateresult .Reason ), http .StatusForbidden )
122
+ return
123
+ }
124
+ klog .Infof ("TProxy: %s %s ValidateRest check PASSED" , realEndPointUrl .Host , req .Method )
125
+
94
126
// modify request
95
127
director := func (target * http.Request ) {
96
128
target .Header .Set ("Pass-Via-Go-TProxy" , "1" )
0 commit comments