2 * Copyright 2020 Huawei Technologies Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 "github.com/apache/servicecomb-service-center/server/core"
25 "github.com/apache/servicecomb-service-center/server/core/proto"
27 "mepserver/mp1/arch/workspace"
28 "mepserver/mp1/models"
29 meputil "mepserver/mp1/util"
32 type DiscoverDecode struct {
34 R *http.Request `json:"r,in"`
35 Ctx context.Context `json:"ctx,out"`
36 QueryParam url.Values `json:"queryParam,out"`
37 CoreRequest interface{} `json:"coreRequest,out"`
40 func (t *DiscoverDecode) OnRequest(data string) workspace.TaskCode {
41 t.Ctx, t.CoreRequest, t.QueryParam = meputil.GetFindParam(t.R)
42 return workspace.TaskFinish
45 type DiscoverService struct {
47 Ctx context.Context `json:"ctx,in"`
48 QueryParam url.Values `json:"queryParam,in"`
49 CoreRequest interface{} `json:"coreRequest,in"`
50 CoreRsp interface{} `json:"coreRsp,out"`
53 func (t *DiscoverService) checkInstanceId(req *proto.FindInstancesRequest) bool {
54 instanceId := req.AppId
55 if instanceId != "default" {
56 instances := t.CoreRsp.(*proto.FindInstancesResponse).Instances
57 for _, val := range instances {
58 if val.ServiceId+val.InstanceId == instanceId {
67 func (t *DiscoverService) OnRequest(data string) workspace.TaskCode {
68 req, ok := t.CoreRequest.(*proto.FindInstancesRequest)
70 t.SetFirstErrorCode(SerErrServiceNotFound, "cast to request fail")
71 return workspace.TaskFinish
73 if req.ServiceName == "" {
74 var errFindByKey error
75 t.CoreRsp, errFindByKey = meputil.FindInstanceByKey(t.QueryParam)
76 if errFindByKey != nil || t.CoreRsp == nil {
77 t.SetFirstErrorCode(SerErrServiceNotFound, errFindByKey.Error())
78 return workspace.TaskFinish
80 if !t.checkInstanceId(req) {
81 t.SetFirstErrorCode(SerErrServiceNotFound, "instance id not found")
83 return workspace.TaskFinish
86 findInstance, err := core.InstanceAPI.Find(t.Ctx, req)
88 t.SetFirstErrorCode(SerErrServiceNotFound, err.Error())
89 return workspace.TaskFinish
91 if findInstance == nil || len(findInstance.Instances) == 0 {
92 t.SetFirstErrorCode(SerErrServiceNotFound, "service not found")
93 return workspace.TaskFinish
96 t.CoreRsp = findInstance
97 return workspace.TaskFinish
100 type ToStrDiscover struct {
101 HttpErrInf *proto.Response `json:"httpErrInf,out"`
103 CoreRsp interface{} `json:"coreRsp,in"`
104 HttpRsp interface{} `json:"httpRsp,out"`
107 func (t *ToStrDiscover) OnRequest(data string) workspace.TaskCode {
108 t.HttpErrInf, t.HttpRsp = mp1CvtSrvDiscover(t.CoreRsp.(*proto.FindInstancesResponse))
109 return workspace.TaskFinish
112 type RspHook struct {
113 R *http.Request `json:"r,in"`
115 Ctx context.Context `json:"ctx,in"`
116 HttpRsp interface{} `json:"httpRsp,in"`
117 HookRsp interface{} `json:"hookRsp,out"`
120 func (t *RspHook) OnRequest(data string) workspace.TaskCode {
121 t.HookRsp = instanceHook(t.Ctx, t.R, t.HttpRsp)
122 return workspace.TaskFinish
125 func instanceHook(ctx context.Context, r *http.Request, rspData interface{}) interface{} {
126 rspBody, ok := rspData.([]*models.ServiceInfo)
131 if len(rspBody) == 0 {
134 consumerName := r.Header.Get("X-ConsumerName")
135 if consumerName == "APIGW" {
139 for _, v := range rspBody {
140 if apihook.APIHook != nil {
141 info := apihook.APIHook()
142 if len(info.Addresses) == 0 && len(info.Uris) == 0 {
145 v.TransportInfo.Endpoint = info
151 type SendHttpRsp struct {
152 HttpErrInf *proto.Response `json:"httpErrInf,in"`
154 W http.ResponseWriter `json:"w,in"`
155 HttpRsp interface{} `json:"httpRsp,in"`
158 func (t *SendHttpRsp) OnRequest(data string) workspace.TaskCode {
159 errInfo := t.GetSerErrInfo()
160 if errInfo.ErrCode >= int(workspace.TaskFail) {
161 statusCode, httpBody := t.cvtHttpErrInfo(errInfo)
162 meputil.HttpErrResponse(t.W, statusCode, httpBody)
164 return workspace.TaskFinish
166 meputil.WriteResponse(t.W, t.HttpErrInf, t.HttpRsp)
167 return workspace.TaskFinish
170 func (t *SendHttpRsp) cvtHttpErrInfo(errInfo *workspace.SerErrInfo) (int, interface{}) {
171 statusCode := http.StatusBadRequest
172 var httpBody interface{}
173 switch workspace.ErrCode(errInfo.ErrCode) {
174 case SerErrServiceNotFound:
176 //status should return bad request
177 body := &models.ProblemDetails{
178 Title: "Can not found resource",
179 Status: uint32(errInfo.ErrCode),
180 Detail: errInfo.Message,
184 case SerInstanceNotFound:
186 statusCode = http.StatusNotFound
187 body := &models.ProblemDetails{
188 Title: "Can not found resource",
189 Status: uint32(errInfo.ErrCode),
190 Detail: errInfo.Message,
196 return statusCode, httpBody
199 func mp1CvtSrvDiscover(findInsResp *proto.FindInstancesResponse) (*proto.Response, []*models.ServiceInfo) {
200 resp := findInsResp.Response
201 if resp != nil && resp.GetCode() != proto.Response_SUCCESS {
204 serviceInfos := make([]*models.ServiceInfo, 0, len(findInsResp.Instances))
205 for _, ins := range findInsResp.Instances {
206 serviceInfo := &models.ServiceInfo{}
207 serviceInfo.FromServiceInstance(ins)
208 serviceInfos = append(serviceInfos, serviceInfo)
210 return resp, serviceInfos