MCPcopy
hub / github.com/kcp-dev/kcp / WithShardScope

Function WithShardScope

pkg/cache/server/handler.go:72–127  ·  view source on GitHub ↗

WithShardScope reads a shard name from the URL path and puts it into the context. It also trims "/shards/" prefix from the URL. If the path doesn't contain the shard name then a 404 error is returned. For example: shards/*/clusters/*/apis/apis.kcp.io/v1alpha1/apiexports shards/amber/clusters/*/ap

(handler http.Handler)

Source from the content-addressed store, hash-verified

70// so that prometheus-style scrapers can hit the cache server directly without
71// constructing a /shards/<sh>/ prefix.
72func WithShardScope(handler http.Handler) http.Handler {
73 return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
74 if path := req.URL.Path; path == "/livez" || path == "/readyz" || path == "/healthz" || shardpaths.Paths.Has(path) {
75 handler.ServeHTTP(w, req)
76 return
77 }
78 var shardName string
79 if path := req.URL.Path; strings.HasPrefix(path, "/shards/") {
80 path = strings.TrimPrefix(path, "/shards/")
81
82 i := strings.Index(path, "/")
83 if i == -1 {
84 responsewriters.ErrorNegotiated(
85 apierrors.NewBadRequest(fmt.Sprintf("unable to parse shard: no `/` found in path %s", path)),
86 errorCodecs, schema.GroupVersion{},
87 w, req)
88 return
89 }
90 shardName, path = path[:i], path[i:]
91 req.URL.Path = path
92 newURL, err := url.Parse(req.URL.String())
93 if err != nil {
94 responsewriters.ErrorNegotiated(
95 apierrors.NewInternalError(fmt.Errorf("unable to resolve %s, err %w", req.URL.Path, err)),
96 errorCodecs, schema.GroupVersion{},
97 w, req)
98 return
99 }
100 req.URL = newURL
101 }
102
103 var shard request.Shard
104 switch {
105 case shardName == "*":
106 shard = "*"
107 case len(shardName) == 0:
108 responsewriters.ErrorNegotiated(
109 apierrors.NewBadRequest("a shard name is required"),
110 errorCodecs, schema.GroupVersion{},
111 w, req)
112 return
113 default:
114 if !shardNameRegExp.MatchString(shardName) {
115 responsewriters.ErrorNegotiated(
116 apierrors.NewBadRequest(fmt.Sprintf("invalid shard: %q does not match the regex", shardName)),
117 errorCodecs, schema.GroupVersion{},
118 w, req)
119 return
120 }
121 shard = request.Shard(shardName)
122 }
123
124 ctx := request.WithShard(req.Context(), shard)
125 handler.ServeHTTP(w, req.WithContext(ctx))
126 })
127}
128
129// WithServiceScope an HTTP filter that trims "/services/cache" prefix from the URL.

Callers 2

NewConfigFunction · 0.85

Calls 5

HasMethod · 0.80
StringMethod · 0.65
ErrorfMethod · 0.65
ContextMethod · 0.65
ServeHTTPMethod · 0.45

Tested by 1