You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2021/05/26 02:27:42 UTC
[servicecomb-service-center] branch master updated: SCB-2176 Add
response filter (#1005)
This is an automated email from the ASF dual-hosted git repository.
tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git
The following commit(s) were added to refs/heads/master by this push:
new 170a318 SCB-2176 Add response filter (#1005)
170a318 is described below
commit 170a3185652a3ab8a02b7959f9c06794b900a829
Author: little-cui <su...@qq.com>
AuthorDate: Wed May 26 10:27:36 2021 +0800
SCB-2176 Add response filter (#1005)
* SCB-2176 Add response filter
* SCB-2176 Resolve comments
* SCB-2176 Resolve comments
* SCB-2176 Resolve comments
---
server/handler/auth/auth.go | 25 +++-
server/resource/register.go | 2 +-
.../{resource/register.go => response/filter.go} | 24 ++--
server/response/response.go | 123 ++++++++++++++++++
server/response/response_test.go | 137 +++++++++++++++++++++
5 files changed, 290 insertions(+), 21 deletions(-)
diff --git a/server/handler/auth/auth.go b/server/handler/auth/auth.go
index bfbabce..32b5597 100644
--- a/server/handler/auth/auth.go
+++ b/server/handler/auth/auth.go
@@ -18,6 +18,9 @@
package auth
import (
+ "github.com/apache/servicecomb-service-center/pkg/util"
+ "github.com/apache/servicecomb-service-center/server/response"
+ "github.com/apache/servicecomb-service-center/server/rest/controller"
"net/http"
"github.com/apache/servicecomb-service-center/pkg/chain"
@@ -27,6 +30,8 @@ import (
"github.com/go-chassis/cari/discovery"
)
+const CtxResourceLabels util.CtxKey = "_resource_labels"
+
type Handler struct {
}
@@ -43,16 +48,24 @@ func (h *Handler) Handle(i *chain.Invocation) {
if !ret.OK {
return
}
-
- obj := i.Context().Value(rest.CtxResponseObject)
+ apiPath, obj := i.Context().Value(rest.CtxMatchPattern).(string),
+ i.Context().Value(rest.CtxResponseObject)
if obj == nil {
return
}
- // TODO filter and rewrite here!
- // data, _ := json.Marshal(obj)
- // w := i.Context().Value(rest.CtxResponse).(http.ResponseWriter)
- // w.Write(data)
+ labels, ok := i.Context().Value(CtxResourceLabels).([]map[string]string)
+ if !ok {
+ return
+ }
+ if len(labels) == 0 {
+ // all allowed
+ return
+ }
+ obj = response.Filter(apiPath, obj, labels)
+
+ w := i.Context().Value(rest.CtxResponse).(http.ResponseWriter)
+ controller.WriteResponse(w, r, nil, obj)
}))
}
diff --git a/server/resource/register.go b/server/resource/register.go
index be0ceea..026b770 100644
--- a/server/resource/register.go
+++ b/server/resource/register.go
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package v4
+package resource
import (
roa "github.com/apache/servicecomb-service-center/pkg/rest"
diff --git a/server/resource/register.go b/server/response/filter.go
similarity index 62%
copy from server/resource/register.go
copy to server/response/filter.go
index be0ceea..667c280 100644
--- a/server/resource/register.go
+++ b/server/response/filter.go
@@ -15,23 +15,19 @@
* limitations under the License.
*/
-package v4
+package response
-import (
- roa "github.com/apache/servicecomb-service-center/pkg/rest"
- v1 "github.com/apache/servicecomb-service-center/server/resource/v1"
- v4 "github.com/apache/servicecomb-service-center/server/resource/v4"
- "github.com/apache/servicecomb-service-center/server/service/rbac"
-)
+var filters = map[string]FilterFunc{}
-func init() {
- initRouter()
+type FilterFunc func(obj interface{}, filters []map[string]string) interface{}
+
+func RegisterFilter(apiPath string, f FilterFunc) {
+ filters[apiPath] = f
}
-func initRouter() {
- if rbac.Enabled() {
- roa.RegisterServant(&v4.AuthResource{})
- roa.RegisterServant(&v4.RoleResource{})
+func Filter(apiPath string, obj interface{}, labels []map[string]string) interface{} {
+ if f, ok := filters[apiPath]; ok {
+ return f(obj, labels)
}
- roa.RegisterServant(&v1.Governance{})
+ return obj
}
diff --git a/server/response/response.go b/server/response/response.go
new file mode 100644
index 0000000..3c01f10
--- /dev/null
+++ b/server/response/response.go
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package response
+
+import (
+ "github.com/go-chassis/cari/discovery"
+)
+
+func init() {
+ RegisterFilter("/v4/:project/registry/microservices", MicroserviceListFilter)
+ //response.RegisterFilter("/v4/:project/registry/instances", )
+ RegisterFilter("/v4/:project/registry/microservices/:providerId/consumers", ProvidersListFilter)
+ RegisterFilter("/v4/:project/registry/microservices/:consumerId/providers", ConsumersListFilter)
+ // control panel apis
+ RegisterFilter("/v4/:project/govern/microservices", MicroServiceInfoListFilter)
+ RegisterFilter("/v4/:project/govern/apps", AppIdListFilter)
+}
+
+func MicroserviceListFilter(obj interface{}, labels []map[string]string) interface{} {
+ servicesResponse, ok := obj.(*discovery.GetServicesResponse)
+ if !ok {
+ return obj
+ }
+ servicesResponse.Services = filterMicroservices(servicesResponse.Services, labels)
+ return servicesResponse
+}
+
+func filterMicroservices(sources []*discovery.MicroService, labelsList []map[string]string) []*discovery.MicroService {
+ var services []*discovery.MicroService
+ for _, service := range sources {
+ for _, labels := range labelsList {
+ if env, ok := labels["environment"]; ok && service.Environment != env {
+ continue
+ }
+ if app, ok := labels["appId"]; ok && service.AppId != app {
+ continue
+ }
+ if name, ok := labels["serviceName"]; ok && service.ServiceName != name {
+ continue
+ }
+ services = append(services, service)
+ break
+ }
+ }
+ return services
+}
+
+func ProvidersListFilter(obj interface{}, labels []map[string]string) interface{} {
+ servicesResponse, ok := obj.(*discovery.GetConDependenciesResponse)
+ if !ok {
+ return obj
+ }
+ servicesResponse.Providers = filterMicroservices(servicesResponse.Providers, labels)
+ return servicesResponse
+}
+
+func ConsumersListFilter(obj interface{}, labels []map[string]string) interface{} {
+ servicesResponse, ok := obj.(*discovery.GetProDependenciesResponse)
+ if !ok {
+ return obj
+ }
+ servicesResponse.Consumers = filterMicroservices(servicesResponse.Consumers, labels)
+ return servicesResponse
+}
+
+func MicroServiceInfoListFilter(obj interface{}, labelsList []map[string]string) interface{} {
+ servicesResponse, ok := obj.(*discovery.GetServicesInfoResponse)
+ if !ok {
+ return obj
+ }
+ var services []*discovery.ServiceDetail
+ for _, service := range servicesResponse.AllServicesDetail {
+ for _, labels := range labelsList {
+ if env, ok := labels["environment"]; ok && service.MicroService.Environment != env {
+ continue
+ }
+ if app, ok := labels["appId"]; ok && service.MicroService.AppId != app {
+ continue
+ }
+ if name, ok := labels["serviceName"]; ok && service.MicroService.ServiceName != name {
+ continue
+ }
+ services = append(services, service)
+ break
+ }
+ }
+ servicesResponse.AllServicesDetail = services
+ return servicesResponse
+}
+
+func AppIdListFilter(obj interface{}, labelsList []map[string]string) interface{} {
+ appsResponse, ok := obj.(*discovery.GetAppsResponse)
+ if !ok {
+ return obj
+ }
+ var apps []string
+ for _, appId := range appsResponse.AppIds {
+ for _, labels := range labelsList {
+ if app, ok := labels["appId"]; ok && appId != app {
+ continue
+ }
+ apps = append(apps, appId)
+ break
+ }
+ }
+ appsResponse.AppIds = apps
+ return appsResponse
+}
diff --git a/server/response/response_test.go b/server/response/response_test.go
new file mode 100644
index 0000000..233a764
--- /dev/null
+++ b/server/response/response_test.go
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package response_test
+
+import (
+ "github.com/apache/servicecomb-service-center/server/response"
+ "github.com/go-chassis/cari/discovery"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestMicroServiceInfoListFilter(t *testing.T) {
+ t.Run("obj is invalid, should do nothing", func(t *testing.T) {
+ other := &discovery.MicroService{}
+ assert.Equal(t, other, response.MicroServiceInfoListFilter(other, nil))
+ })
+
+ t.Run("labels is empty, should return empty resources", func(t *testing.T) {
+ rs := response.MicroServiceInfoListFilter(&discovery.GetServicesInfoResponse{
+ AllServicesDetail: []*discovery.ServiceDetail{
+ {MicroService: &discovery.MicroService{ServiceName: "A"}}, {MicroService: &discovery.MicroService{ServiceName: "B"}},
+ },
+ }, nil)
+ assert.Equal(t, 0, len(rs.(*discovery.GetServicesInfoResponse).AllServicesDetail))
+ })
+
+ t.Run("not match name, should return empty resources", func(t *testing.T) {
+ rs := response.MicroServiceInfoListFilter(&discovery.GetServicesInfoResponse{
+ AllServicesDetail: []*discovery.ServiceDetail{
+ {MicroService: &discovery.MicroService{ServiceName: "A"}}, {MicroService: &discovery.MicroService{ServiceName: "B"}},
+ },
+ }, []map[string]string{{"serviceName": "NONE"}})
+ assert.Equal(t, 0, len(rs.(*discovery.GetServicesInfoResponse).AllServicesDetail))
+ })
+
+ t.Run("match A, should return A resources", func(t *testing.T) {
+ rs := response.MicroServiceInfoListFilter(&discovery.GetServicesInfoResponse{
+ AllServicesDetail: []*discovery.ServiceDetail{
+ {MicroService: &discovery.MicroService{ServiceName: "A"}}, {MicroService: &discovery.MicroService{ServiceName: "B"}},
+ },
+ }, []map[string]string{{"serviceName": "A"}})
+ mss := rs.(*discovery.GetServicesInfoResponse).AllServicesDetail
+ assert.Equal(t, 1, len(mss))
+ assert.Equal(t, "A", mss[0].MicroService.ServiceName)
+ })
+
+ t.Run("not match name & appId, should return empty resources", func(t *testing.T) {
+ rs := response.MicroServiceInfoListFilter(&discovery.GetServicesInfoResponse{
+ AllServicesDetail: []*discovery.ServiceDetail{
+ {MicroService: &discovery.MicroService{ServiceName: "A"}}, {MicroService: &discovery.MicroService{ServiceName: "B"}},
+ },
+ }, []map[string]string{{"serviceName": "A", "appId": "A"}})
+ mss := rs.(*discovery.GetServicesInfoResponse).AllServicesDetail
+ assert.Equal(t, 0, len(mss))
+ })
+
+ t.Run("match name & appId, should return empty resources", func(t *testing.T) {
+ rs := response.MicroServiceInfoListFilter(&discovery.GetServicesInfoResponse{
+ AllServicesDetail: []*discovery.ServiceDetail{
+ {MicroService: &discovery.MicroService{AppId: "A", ServiceName: "A"}}, {MicroService: &discovery.MicroService{ServiceName: "B"}},
+ },
+ }, []map[string]string{{"serviceName": "A", "appId": "A"}})
+ mss := rs.(*discovery.GetServicesInfoResponse).AllServicesDetail
+ assert.Equal(t, 1, len(mss))
+ })
+}
+
+func TestMicroserviceListFilter(t *testing.T) {
+ t.Run("obj is invalid, should do nothing", func(t *testing.T) {
+ other := &discovery.MicroService{}
+ assert.Equal(t, other, response.MicroserviceListFilter(other, nil))
+ })
+
+ t.Run("labels is empty, should return empty resources", func(t *testing.T) {
+ rs := response.MicroserviceListFilter(&discovery.GetServicesResponse{
+ Services: []*discovery.MicroService{
+ {ServiceName: "A"}, {ServiceName: "B"},
+ },
+ }, nil)
+ assert.Equal(t, 0, len(rs.(*discovery.GetServicesResponse).Services))
+ })
+
+ t.Run("not match name, should return empty resources", func(t *testing.T) {
+ rs := response.MicroserviceListFilter(&discovery.GetServicesResponse{
+ Services: []*discovery.MicroService{
+ {ServiceName: "A"}, {ServiceName: "B"},
+ },
+ }, []map[string]string{{"serviceName": "NONE"}})
+ assert.Equal(t, 0, len(rs.(*discovery.GetServicesResponse).Services))
+ })
+
+ t.Run("match A, should return A resources", func(t *testing.T) {
+ rs := response.MicroserviceListFilter(&discovery.GetServicesResponse{
+ Services: []*discovery.MicroService{
+ {ServiceName: "A"}, {ServiceName: "B"},
+ },
+ }, []map[string]string{{"serviceName": "A"}})
+ mss := rs.(*discovery.GetServicesResponse).Services
+ assert.Equal(t, 1, len(mss))
+ assert.Equal(t, "A", mss[0].ServiceName)
+ })
+
+ t.Run("not match name & appId, should return empty resources", func(t *testing.T) {
+ rs := response.MicroserviceListFilter(&discovery.GetServicesResponse{
+ Services: []*discovery.MicroService{
+ {ServiceName: "A"}, {ServiceName: "B"},
+ },
+ }, []map[string]string{{"serviceName": "A", "appId": "A"}})
+ mss := rs.(*discovery.GetServicesResponse).Services
+ assert.Equal(t, 0, len(mss))
+ })
+
+ t.Run("match name & appId, should return empty resources", func(t *testing.T) {
+ rs := response.MicroserviceListFilter(&discovery.GetServicesResponse{
+ Services: []*discovery.MicroService{
+ {AppId: "A", ServiceName: "A"}, {ServiceName: "B"},
+ },
+ }, []map[string]string{{"serviceName": "A", "appId": "A"}})
+ mss := rs.(*discovery.GetServicesResponse).Services
+ assert.Equal(t, 1, len(mss))
+ })
+}