go.ligato.io/vpp-agent/v3@v3.5.0/plugins/govppmux/rest.go (about) 1 // Copyright (c) 2019 Cisco and/or its affiliates. 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 govppmux 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "io" 21 "net/http" 22 "net/rpc" 23 24 "github.com/unrolled/render" 25 "go.ligato.io/cn-infra/v2/rpc/rest" 26 ) 27 28 // registerHandlers registers all supported REST APIs. 29 func (p *Plugin) registerHandlers(http rest.HTTPHandlers) { 30 if http == nil { 31 p.Log.Debug("No http handler provided, skipping registration of REST handlers") 32 return 33 } 34 http.RegisterHTTPHandler("/govppmux/stats", p.statsHandler, "GET") 35 http.RegisterHTTPHandler(rpc.DefaultRPCPath, p.proxyHandler, "CONNECT") 36 http.RegisterHTTPHandler("/vpp/command", p.cliCommandHandler, "POST") 37 } 38 39 func (p *Plugin) statsHandler(formatter *render.Render) http.HandlerFunc { 40 return func(w http.ResponseWriter, req *http.Request) { 41 if err := formatter.JSON(w, http.StatusOK, GetStats()); err != nil { 42 p.Log.Warnf("stats handler errored: %v", err) 43 } 44 } 45 } 46 47 func (p *Plugin) proxyHandler(_ *render.Render) http.HandlerFunc { 48 if !p.config.ProxyEnabled { 49 return func(w http.ResponseWriter, req *http.Request) { 50 http.Error(w, "VPP proxy not enabled", http.StatusServiceUnavailable) 51 } 52 } 53 return func(w http.ResponseWriter, req *http.Request) { 54 p.proxy.ServeHTTP(w, req) 55 } 56 } 57 58 func (p *Plugin) cliCommandHandler(formatter *render.Render) http.HandlerFunc { 59 return func(w http.ResponseWriter, req *http.Request) { 60 body, err := io.ReadAll(req.Body) 61 if err != nil { 62 errMsg := fmt.Sprintf("400 Bad request: failed to parse request body: %v", err) 63 _ = formatter.JSON(w, http.StatusBadRequest, errMsg) 64 return 65 } 66 var reqParam map[string]string 67 68 if err = json.Unmarshal(body, &reqParam); err != nil { 69 errMsg := fmt.Sprintf("400 Bad request: failed to unmarshall request body: %v\n", err) 70 _ = formatter.JSON(w, http.StatusBadRequest, errMsg) 71 return 72 } 73 command, ok := reqParam["vppclicommand"] 74 if !ok || command == "" { 75 errMsg := "400 Bad request: vppclicommand parameter missing or empty\n" 76 _ = formatter.JSON(w, http.StatusBadRequest, errMsg) 77 return 78 } 79 80 p.Log.Debugf("VPPCLI command: %v", command) 81 reply, err := p.vpeHandler.RunCli(req.Context(), command) 82 if err != nil { 83 errMsg := fmt.Sprintf("500 Internal server error: sending request failed: %v\n", err) 84 _ = formatter.JSON(w, http.StatusInternalServerError, errMsg) 85 return 86 } 87 88 p.Log.Debugf("VPPCLI response: %s", reply) 89 _ = formatter.JSON(w, http.StatusOK, reply) 90 } 91 }