Skip to content

Commit 4248014

Browse files
authored
fix: httproute matching (#121)
Signed-off-by: ashing <[email protected]>
1 parent a42c43e commit 4248014

File tree

2 files changed

+67
-7
lines changed

2 files changed

+67
-7
lines changed

internal/provider/adc/translator/httproute.go

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package translator
33
import (
44
"encoding/json"
55
"fmt"
6+
"sort"
67
"strings"
78

89
"github.com/api7/gopkg/pkg/log"
@@ -341,6 +342,33 @@ func (t *Translator) translateBackendRef(tctx *provider.TranslateContext, ref ga
341342
return t.translateEndpointSlice(portName, weight, endpointSlices)
342343
}
343344

345+
// calculateMatchPriority calculate the priority of HTTPRouteMatch, according to the Gateway API specification
346+
// the higher the return value, the higher the priority
347+
func calculateMatchPriority(match *gatewayv1.HTTPRouteMatch) int64 {
348+
var score int64 = 0
349+
350+
// 1. Exact path matches have the highest priority
351+
if match.Path != nil && match.Path.Type != nil && *match.Path.Type == gatewayv1.PathMatchExact {
352+
score += 10000
353+
} else if match.Path != nil && match.Path.Type != nil && *match.Path.Type == gatewayv1.PathMatchPathPrefix && match.Path.Value != nil {
354+
// 2. Prefix path matches, the longer the string, the higher the priority
355+
score += 1000 + int64(len(*match.Path.Value))
356+
}
357+
358+
// 3. Method matching
359+
if match.Method != nil {
360+
score += 100
361+
}
362+
363+
// 4. Header matching, the more headers, the higher the priority
364+
score += int64(len(match.Headers) * 10)
365+
366+
// 5. Query parameter matching, the more query parameters, the higher the priority
367+
score += int64(len(match.QueryParams))
368+
369+
return score
370+
}
371+
344372
func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRoute *gatewayv1.HTTPRoute) (*TranslateResult, error) {
345373
result := &TranslateResult{}
346374

@@ -388,6 +416,11 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
388416
},
389417
},
390418
}
419+
} else {
420+
// Sort the matches by priority
421+
sort.Slice(matches, func(a, b int) bool {
422+
return calculateMatchPriority(&matches[a]) > calculateMatchPriority(&matches[b])
423+
})
391424
}
392425

393426
routes := []*adctypes.Route{}
@@ -402,6 +435,11 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
402435
route.ID = id.GenID(name)
403436
route.Labels = labels
404437
route.EnableWebsocket = ptr.To(true)
438+
439+
// Set the route priority
440+
priority := calculateMatchPriority(&match)
441+
route.Priority = &priority
442+
405443
routes = append(routes, route)
406444
}
407445
t.fillHTTPRoutePoliciesForHTTPRoute(tctx, routes, rule)
@@ -422,7 +460,14 @@ func (t *Translator) translateGatewayHTTPRouteMatch(match *gatewayv1.HTTPRouteMa
422460
case gatewayv1.PathMatchExact:
423461
route.Uris = []string{*match.Path.Value}
424462
case gatewayv1.PathMatchPathPrefix:
425-
route.Uris = []string{*match.Path.Value + "*"}
463+
pathValue := *match.Path.Value
464+
route.Uris = []string{pathValue}
465+
466+
if strings.HasSuffix(pathValue, "/") {
467+
route.Uris = append(route.Uris, pathValue+"*")
468+
} else {
469+
route.Uris = append(route.Uris, pathValue+"/*")
470+
}
426471
case gatewayv1.PathMatchRegularExpression:
427472
var this []adctypes.StringOrSlice
428473
this = append(this, adctypes.StringOrSlice{
@@ -439,6 +484,11 @@ func (t *Translator) translateGatewayHTTPRouteMatch(match *gatewayv1.HTTPRouteMa
439484
default:
440485
return nil, errors.New("unknown path match type " + string(*match.Path.Type))
441486
}
487+
} else {
488+
/* If no matches are specified, the default is a prefix
489+
path match on "/", which has the effect of matching every
490+
HTTP request. */
491+
route.Uris = []string{"/", "/*"}
442492
}
443493

444494
if len(match.Headers) > 0 {
@@ -451,7 +501,12 @@ func (t *Translator) translateGatewayHTTPRouteMatch(match *gatewayv1.HTTPRouteMa
451501
StrVal: "http_" + name,
452502
})
453503

454-
switch *header.Type {
504+
matchType := gatewayv1.HeaderMatchExact
505+
if header.Type != nil {
506+
matchType = *header.Type
507+
}
508+
509+
switch matchType {
455510
case gatewayv1.HeaderMatchExact:
456511
this = append(this, adctypes.StringOrSlice{
457512
StrVal: "==",
@@ -461,7 +516,7 @@ func (t *Translator) translateGatewayHTTPRouteMatch(match *gatewayv1.HTTPRouteMa
461516
StrVal: "~~",
462517
})
463518
default:
464-
return nil, errors.New("unknown header match type " + string(*header.Type))
519+
return nil, errors.New("unknown header match type " + string(matchType))
465520
}
466521

467522
this = append(this, adctypes.StringOrSlice{
@@ -479,7 +534,12 @@ func (t *Translator) translateGatewayHTTPRouteMatch(match *gatewayv1.HTTPRouteMa
479534
StrVal: "arg_" + strings.ToLower(fmt.Sprintf("%v", query.Name)),
480535
})
481536

482-
switch *query.Type {
537+
queryType := gatewayv1.QueryParamMatchExact
538+
if query.Type != nil {
539+
queryType = *query.Type
540+
}
541+
542+
switch queryType {
483543
case gatewayv1.QueryParamMatchExact:
484544
this = append(this, adctypes.StringOrSlice{
485545
StrVal: "==",
@@ -489,7 +549,7 @@ func (t *Translator) translateGatewayHTTPRouteMatch(match *gatewayv1.HTTPRouteMa
489549
StrVal: "~~",
490550
})
491551
default:
492-
return nil, errors.New("unknown query match type " + string(*query.Type))
552+
return nil, errors.New("unknown query match type " + string(queryType))
493553
}
494554

495555
this = append(this, adctypes.StringOrSlice{

test/conformance/conformance_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ var skippedTestsForTraditionalRoutes = []string{
3737
tests.HTTPRouteHostnameIntersection.ShortName,
3838
tests.HTTPRouteListenerHostnameMatching.ShortName,
3939

40-
tests.HTTPRouteMatching.ShortName,
41-
tests.HTTPRouteMatchingAcrossRoutes.ShortName,
40+
// tests.HTTPRouteMatching.ShortName,
41+
// tests.HTTPRouteMatchingAcrossRoutes.ShortName,
4242

4343
tests.GatewayInvalidTLSConfiguration.ShortName,
4444
tests.HTTPRouteInvalidBackendRefUnknownKind.ShortName,

0 commit comments

Comments
 (0)