github.com/weaviate/weaviate@v1.24.6/adapters/handlers/rest/clusterapi/nodes.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package clusterapi 13 14 import ( 15 "context" 16 "encoding/json" 17 "fmt" 18 "net/http" 19 "regexp" 20 21 "github.com/weaviate/weaviate/entities/models" 22 entschema "github.com/weaviate/weaviate/entities/schema" 23 "github.com/weaviate/weaviate/entities/verbosity" 24 ) 25 26 type nodesManager interface { 27 GetNodeStatus(ctx context.Context, className, output string) (*models.NodeStatus, error) 28 } 29 30 type nodes struct { 31 nodesManager nodesManager 32 auth auth 33 } 34 35 func NewNodes(manager nodesManager, auth auth) *nodes { 36 return &nodes{nodesManager: manager, auth: auth} 37 } 38 39 var ( 40 regxNodes = regexp.MustCompile(`/status`) 41 regxNodesClass = regexp.MustCompile(`/status/(` + entschema.ClassNameRegexCore + `)`) 42 ) 43 44 func (s *nodes) Nodes() http.Handler { 45 return s.auth.handleFunc(s.nodesHandler()) 46 } 47 48 func (s *nodes) nodesHandler() http.HandlerFunc { 49 return func(w http.ResponseWriter, r *http.Request) { 50 path := r.URL.Path 51 switch { 52 case regxNodes.MatchString(path) || regxNodesClass.MatchString(path): 53 if r.Method != http.MethodGet { 54 msg := fmt.Sprintf("/nodes api path %q not found", path) 55 http.Error(w, msg, http.StatusMethodNotAllowed) 56 return 57 } 58 59 s.incomingNodeStatus().ServeHTTP(w, r) 60 return 61 default: 62 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 63 return 64 } 65 } 66 } 67 68 func (s *nodes) incomingNodeStatus() http.Handler { 69 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 70 defer r.Body.Close() 71 72 var className string 73 74 args := regxNodesClass.FindStringSubmatch(r.URL.Path) 75 if len(args) == 3 { 76 className = args[2] 77 } 78 79 output := verbosity.OutputMinimal 80 out, found := r.URL.Query()["output"] 81 if found && len(out) > 0 { 82 output = out[0] 83 } 84 85 nodeStatus, err := s.nodesManager.GetNodeStatus(r.Context(), className, output) 86 if err != nil { 87 http.Error(w, "/nodes fulfill request: "+err.Error(), 88 http.StatusBadRequest) 89 return 90 } 91 92 if nodeStatus == nil { 93 w.WriteHeader(http.StatusNotFound) 94 return 95 } 96 97 nodeStatusBytes, err := json.Marshal(nodeStatus) 98 if err != nil { 99 http.Error(w, "/nodes marshal response: "+err.Error(), 100 http.StatusInternalServerError) 101 } 102 103 w.Write(nodeStatusBytes) 104 }) 105 }