@@ -30,6 +30,7 @@ import (
30
30
"sync"
31
31
"time"
32
32
33
+ "github.com/v3io/scaler/pkg/ingresscache"
33
34
"github.com/v3io/scaler/pkg/scalertypes"
34
35
35
36
"github.com/nuclio/errors"
@@ -49,6 +50,7 @@ type Handler struct {
49
50
targetURLCache * cache.LRUExpireCache
50
51
proxyLock sync.Locker
51
52
lastProxyErrorTime time.Time
53
+ ingressCache ingresscache.IngressHostCacheReader
52
54
}
53
55
54
56
func NewHandler (parentLogger logger.Logger ,
@@ -57,7 +59,8 @@ func NewHandler(parentLogger logger.Logger,
57
59
targetNameHeader string ,
58
60
targetPathHeader string ,
59
61
targetPort int ,
60
- multiTargetStrategy scalertypes.MultiTargetStrategy ) (Handler , error ) {
62
+ multiTargetStrategy scalertypes.MultiTargetStrategy ,
63
+ ingressCache ingresscache.IngressHostCacheReader ) (Handler , error ) {
61
64
h := Handler {
62
65
logger : parentLogger .GetChild ("handler" ),
63
66
resourceStarter : resourceStarter ,
@@ -69,17 +72,17 @@ func NewHandler(parentLogger logger.Logger,
69
72
targetURLCache : cache .NewLRUExpireCache (100 ),
70
73
proxyLock : & sync.Mutex {},
71
74
lastProxyErrorTime : time .Now (),
75
+ ingressCache : ingressCache ,
72
76
}
73
77
h .HandleFunc = h .handleRequest
74
78
return h , nil
75
79
}
76
80
77
81
func (h * Handler ) handleRequest (res http.ResponseWriter , req * http.Request ) {
82
+ var path string
83
+ var err error
78
84
var resourceNames []string
79
85
80
- responseChannel := make (chan ResourceStatusResult , 1 )
81
- defer close (responseChannel )
82
-
83
86
// first try to see if our request came from ingress controller
84
87
forwardedHost := req .Header .Get ("X-Forwarded-Host" )
85
88
forwardedPort := req .Header .Get ("X-Forwarded-Port" )
@@ -97,15 +100,15 @@ func (h *Handler) handleRequest(res http.ResponseWriter, req *http.Request) {
97
100
resourceNames = append (resourceNames , resourceName )
98
101
resourceTargetURLMap [resourceName ] = targetURL
99
102
} else {
100
- targetNameHeaderValue := req .Header .Get (h .targetNameHeader )
101
- path := req .Header .Get (h .targetPathHeader )
102
- if targetNameHeaderValue == "" {
103
- h .logger .WarnWith ("When ingress not set, must pass header value" ,
104
- "missingHeader" , h .targetNameHeader )
103
+ path , resourceNames , err = h .getPathAndResourceNames (req )
104
+ if err != nil {
105
+ h .logger .WarnWith ("Failed to get resource names and path from request" ,
106
+ "error" , err .Error (),
107
+ "host" , req .Host ,
108
+ "path" , h .getRequestURLPath (req ))
105
109
res .WriteHeader (http .StatusBadRequest )
106
110
return
107
111
}
108
- resourceNames = strings .Split (targetNameHeaderValue , "," )
109
112
for _ , resourceName := range resourceNames {
110
113
targetURL , status := h .parseTargetURL (resourceName , path )
111
114
if targetURL == nil {
@@ -163,6 +166,43 @@ func (h *Handler) handleRequest(res http.ResponseWriter, req *http.Request) {
163
166
proxy .ServeHTTP (res , req )
164
167
}
165
168
169
+ func (h * Handler ) getPathAndResourceNames (req * http.Request ) (string , []string , error ) {
170
+ // first try to get the resource names and path from the ingress cache
171
+ path , resourceNames , err := h .getValuesFromCache (req )
172
+ if err == nil {
173
+ return path , resourceNames , nil
174
+ }
175
+
176
+ h .logger .DebugWith ("Failed to get resource names from ingress cache, trying to extract from the request headers" ,
177
+ "host" , req .Host ,
178
+ "path" , h .getRequestURLPath (req ),
179
+ "error" , err .Error ())
180
+
181
+ // old implementation for backward compatibility
182
+ targetNameHeaderValue := req .Header .Get (h .targetNameHeader )
183
+ path = req .Header .Get (h .targetPathHeader )
184
+ if targetNameHeaderValue == "" {
185
+ return "" , nil , errors .New ("No target name header found" )
186
+ }
187
+ resourceNames = strings .Split (targetNameHeaderValue , "," )
188
+ return path , resourceNames , nil
189
+ }
190
+
191
+ func (h * Handler ) getValuesFromCache (req * http.Request ) (string , []string , error ) {
192
+ host := req .Host
193
+ path := h .getRequestURLPath (req )
194
+ resourceNames , err := h .ingressCache .Get (host , path )
195
+ if err != nil {
196
+ return "" , nil , errors .New ("Failed to get resource names from ingress cache" )
197
+ }
198
+
199
+ if len (resourceNames ) == 0 {
200
+ return "" , nil , errors .New ("No resources found in ingress cache" )
201
+ }
202
+
203
+ return path , resourceNames , nil
204
+ }
205
+
166
206
func (h * Handler ) parseTargetURL (resourceName , path string ) (* url.URL , int ) {
167
207
serviceName , err := h .resourceScaler .ResolveServiceName (scalertypes.Resource {Name : resourceName })
168
208
if err != nil {
@@ -178,17 +218,17 @@ func (h *Handler) parseTargetURL(resourceName, path string) (*url.URL, int) {
178
218
}
179
219
180
220
func (h * Handler ) startResources (resourceNames []string ) * ResourceStatusResult {
181
- responseChannel := make (chan ResourceStatusResult , len (resourceNames ))
182
- defer close (responseChannel )
221
+ responseChan := make (chan ResourceStatusResult , len (resourceNames ))
222
+ defer close (responseChan )
183
223
184
224
// Start all resources in separate go routines
185
225
for _ , resourceName := range resourceNames {
186
- go h .resourceStarter .handleResourceStart (resourceName , responseChannel )
226
+ go h .resourceStarter .handleResourceStart (resourceName , responseChan )
187
227
}
188
228
189
229
// Wait for all resources to finish starting
190
230
for range resourceNames {
191
- statusResult := <- responseChannel
231
+ statusResult := <- responseChan
192
232
193
233
if statusResult .Error != nil {
194
234
h .logger .WarnWith ("Failed to start resource" ,
@@ -230,3 +270,10 @@ func (h *Handler) URLBadParse(resourceName string, err error) int {
230
270
"err" , errors .GetErrorStackString (err , 10 ))
231
271
return http .StatusBadRequest
232
272
}
273
+
274
+ func (h * Handler ) getRequestURLPath (req * http.Request ) string {
275
+ if req .URL != nil {
276
+ return req .URL .Path
277
+ }
278
+ return ""
279
+ }
0 commit comments