1package api 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "sort" 8 "strconv" 9 "strings" 10 11 "github.com/gorilla/mux" 12 "github.com/traefik/traefik/v2/pkg/config/runtime" 13 "github.com/traefik/traefik/v2/pkg/log" 14) 15 16type tcpRouterRepresentation struct { 17 *runtime.TCPRouterInfo 18 Name string `json:"name,omitempty"` 19 Provider string `json:"provider,omitempty"` 20} 21 22func newTCPRouterRepresentation(name string, rt *runtime.TCPRouterInfo) tcpRouterRepresentation { 23 return tcpRouterRepresentation{ 24 TCPRouterInfo: rt, 25 Name: name, 26 Provider: getProviderName(name), 27 } 28} 29 30type tcpServiceRepresentation struct { 31 *runtime.TCPServiceInfo 32 Name string `json:"name,omitempty"` 33 Provider string `json:"provider,omitempty"` 34 Type string `json:"type,omitempty"` 35} 36 37func newTCPServiceRepresentation(name string, si *runtime.TCPServiceInfo) tcpServiceRepresentation { 38 return tcpServiceRepresentation{ 39 TCPServiceInfo: si, 40 Name: name, 41 Provider: getProviderName(name), 42 Type: strings.ToLower(extractType(si.TCPService)), 43 } 44} 45 46type tcpMiddlewareRepresentation struct { 47 *runtime.TCPMiddlewareInfo 48 Name string `json:"name,omitempty"` 49 Provider string `json:"provider,omitempty"` 50 Type string `json:"type,omitempty"` 51} 52 53func newTCPMiddlewareRepresentation(name string, mi *runtime.TCPMiddlewareInfo) tcpMiddlewareRepresentation { 54 return tcpMiddlewareRepresentation{ 55 TCPMiddlewareInfo: mi, 56 Name: name, 57 Provider: getProviderName(name), 58 Type: strings.ToLower(extractType(mi.TCPMiddleware)), 59 } 60} 61 62func (h Handler) getTCPRouters(rw http.ResponseWriter, request *http.Request) { 63 results := make([]tcpRouterRepresentation, 0, len(h.runtimeConfiguration.TCPRouters)) 64 65 criterion := newSearchCriterion(request.URL.Query()) 66 67 for name, rt := range h.runtimeConfiguration.TCPRouters { 68 if keepTCPRouter(name, rt, criterion) { 69 results = append(results, newTCPRouterRepresentation(name, rt)) 70 } 71 } 72 73 sort.Slice(results, func(i, j int) bool { 74 return results[i].Name < results[j].Name 75 }) 76 77 rw.Header().Set("Content-Type", "application/json") 78 79 pageInfo, err := pagination(request, len(results)) 80 if err != nil { 81 writeError(rw, err.Error(), http.StatusBadRequest) 82 return 83 } 84 85 rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage)) 86 87 err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) 88 if err != nil { 89 log.FromContext(request.Context()).Error(err) 90 writeError(rw, err.Error(), http.StatusInternalServerError) 91 } 92} 93 94func (h Handler) getTCPRouter(rw http.ResponseWriter, request *http.Request) { 95 routerID := mux.Vars(request)["routerID"] 96 97 rw.Header().Set("Content-Type", "application/json") 98 99 router, ok := h.runtimeConfiguration.TCPRouters[routerID] 100 if !ok { 101 writeError(rw, fmt.Sprintf("router not found: %s", routerID), http.StatusNotFound) 102 return 103 } 104 105 result := newTCPRouterRepresentation(routerID, router) 106 107 err := json.NewEncoder(rw).Encode(result) 108 if err != nil { 109 log.FromContext(request.Context()).Error(err) 110 writeError(rw, err.Error(), http.StatusInternalServerError) 111 } 112} 113 114func (h Handler) getTCPServices(rw http.ResponseWriter, request *http.Request) { 115 results := make([]tcpServiceRepresentation, 0, len(h.runtimeConfiguration.TCPServices)) 116 117 criterion := newSearchCriterion(request.URL.Query()) 118 119 for name, si := range h.runtimeConfiguration.TCPServices { 120 if keepTCPService(name, si, criterion) { 121 results = append(results, newTCPServiceRepresentation(name, si)) 122 } 123 } 124 125 sort.Slice(results, func(i, j int) bool { 126 return results[i].Name < results[j].Name 127 }) 128 129 rw.Header().Set("Content-Type", "application/json") 130 131 pageInfo, err := pagination(request, len(results)) 132 if err != nil { 133 writeError(rw, err.Error(), http.StatusBadRequest) 134 return 135 } 136 137 rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage)) 138 139 err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) 140 if err != nil { 141 log.FromContext(request.Context()).Error(err) 142 writeError(rw, err.Error(), http.StatusInternalServerError) 143 } 144} 145 146func (h Handler) getTCPService(rw http.ResponseWriter, request *http.Request) { 147 serviceID := mux.Vars(request)["serviceID"] 148 149 rw.Header().Set("Content-Type", "application/json") 150 151 service, ok := h.runtimeConfiguration.TCPServices[serviceID] 152 if !ok { 153 writeError(rw, fmt.Sprintf("service not found: %s", serviceID), http.StatusNotFound) 154 return 155 } 156 157 result := newTCPServiceRepresentation(serviceID, service) 158 159 err := json.NewEncoder(rw).Encode(result) 160 if err != nil { 161 log.FromContext(request.Context()).Error(err) 162 writeError(rw, err.Error(), http.StatusInternalServerError) 163 } 164} 165 166func (h Handler) getTCPMiddlewares(rw http.ResponseWriter, request *http.Request) { 167 results := make([]tcpMiddlewareRepresentation, 0, len(h.runtimeConfiguration.Middlewares)) 168 169 criterion := newSearchCriterion(request.URL.Query()) 170 171 for name, mi := range h.runtimeConfiguration.TCPMiddlewares { 172 if keepTCPMiddleware(name, mi, criterion) { 173 results = append(results, newTCPMiddlewareRepresentation(name, mi)) 174 } 175 } 176 177 sort.Slice(results, func(i, j int) bool { 178 return results[i].Name < results[j].Name 179 }) 180 181 rw.Header().Set("Content-Type", "application/json") 182 183 pageInfo, err := pagination(request, len(results)) 184 if err != nil { 185 writeError(rw, err.Error(), http.StatusBadRequest) 186 return 187 } 188 189 rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage)) 190 191 err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) 192 if err != nil { 193 log.FromContext(request.Context()).Error(err) 194 writeError(rw, err.Error(), http.StatusInternalServerError) 195 } 196} 197 198func (h Handler) getTCPMiddleware(rw http.ResponseWriter, request *http.Request) { 199 middlewareID := mux.Vars(request)["middlewareID"] 200 201 rw.Header().Set("Content-Type", "application/json") 202 203 middleware, ok := h.runtimeConfiguration.TCPMiddlewares[middlewareID] 204 if !ok { 205 writeError(rw, fmt.Sprintf("middleware not found: %s", middlewareID), http.StatusNotFound) 206 return 207 } 208 209 result := newTCPMiddlewareRepresentation(middlewareID, middleware) 210 211 err := json.NewEncoder(rw).Encode(result) 212 if err != nil { 213 log.FromContext(request.Context()).Error(err) 214 writeError(rw, err.Error(), http.StatusInternalServerError) 215 } 216} 217 218func keepTCPRouter(name string, item *runtime.TCPRouterInfo, criterion *searchCriterion) bool { 219 if criterion == nil { 220 return true 221 } 222 223 return criterion.withStatus(item.Status) && criterion.searchIn(item.Rule, name) 224} 225 226func keepTCPService(name string, item *runtime.TCPServiceInfo, criterion *searchCriterion) bool { 227 if criterion == nil { 228 return true 229 } 230 231 return criterion.withStatus(item.Status) && criterion.searchIn(name) 232} 233 234func keepTCPMiddleware(name string, item *runtime.TCPMiddlewareInfo, criterion *searchCriterion) bool { 235 if criterion == nil { 236 return true 237 } 238 239 return criterion.withStatus(item.Status) && criterion.searchIn(name) 240} 241