gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/go-control-plane/pkg/server/v3/gateway.go (about) 1 // Copyright 2018 Envoyproxy Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package server 16 17 import ( 18 "bytes" 19 "fmt" 20 "gitee.com/ks-custle/core-gm/go-control-plane/pkg/resource/v3" 21 "io/ioutil" 22 "net/http" 23 "path" 24 25 "github.com/golang/protobuf/jsonpb" 26 27 discovery "gitee.com/ks-custle/core-gm/go-control-plane/envoy/service/discovery/v3" 28 "gitee.com/ks-custle/core-gm/go-control-plane/pkg/cache/types" 29 "gitee.com/ks-custle/core-gm/go-control-plane/pkg/log" 30 ) 31 32 // HTTPGateway is a custom implementation of [gRPC gateway](https://github.com/grpc-ecosystem/grpc-gateway) 33 // specialized to Envoy xDS API. 34 type HTTPGateway struct { 35 // Log is an optional log for errors in response write 36 Log log.Logger 37 38 // Server is the underlying gRPC server 39 Server Server 40 } 41 42 func (h *HTTPGateway) ServeHTTP(req *http.Request) ([]byte, int, error) { 43 p := path.Clean(req.URL.Path) 44 45 typeURL := "" 46 switch p { 47 case resource.FetchEndpoints: 48 typeURL = resource.EndpointType 49 case resource.FetchClusters: 50 typeURL = resource.ClusterType 51 case resource.FetchListeners: 52 typeURL = resource.ListenerType 53 case resource.FetchRoutes: 54 typeURL = resource.RouteType 55 case resource.FetchSecrets: 56 typeURL = resource.SecretType 57 case resource.FetchRuntimes: 58 typeURL = resource.RuntimeType 59 case resource.FetchExtensionConfigs: 60 typeURL = resource.ExtensionConfigType 61 default: 62 return nil, http.StatusNotFound, fmt.Errorf("no endpoint") 63 } 64 65 if req.Body == nil { 66 return nil, http.StatusBadRequest, fmt.Errorf("empty body") 67 } 68 69 body, err := ioutil.ReadAll(req.Body) 70 if err != nil { 71 return nil, http.StatusBadRequest, fmt.Errorf("cannot read body") 72 } 73 74 // parse as JSON 75 out := &discovery.DiscoveryRequest{} 76 err = jsonpb.UnmarshalString(string(body), out) 77 if err != nil { 78 return nil, http.StatusBadRequest, fmt.Errorf("cannot parse JSON body: " + err.Error()) 79 } 80 out.TypeUrl = typeURL 81 82 // fetch results 83 res, err := h.Server.Fetch(req.Context(), out) 84 if err != nil { 85 // SkipFetchErrors will return a 304 which will signify to the envoy client that 86 // it is already at the latest version; all other errors will 500 with a message. 87 if _, ok := err.(*types.SkipFetchError); ok { 88 return nil, http.StatusNotModified, nil 89 } 90 return nil, http.StatusInternalServerError, fmt.Errorf("fetch error: " + err.Error()) 91 } 92 93 buf := &bytes.Buffer{} 94 if err := (&jsonpb.Marshaler{OrigName: true}).Marshal(buf, res); err != nil { 95 return nil, http.StatusInternalServerError, fmt.Errorf("marshal error: " + err.Error()) 96 } 97 98 return buf.Bytes(), http.StatusOK, nil 99 }