2020-02-11 03:26:04 +03:00
package api
import (
"encoding/json"
"fmt"
"net/http"
2024-01-25 11:56:05 +03:00
"net/url"
2020-02-11 03:26:04 +03:00
"strconv"
"strings"
"github.com/gorilla/mux"
2022-11-21 20:36:05 +03:00
"github.com/rs/zerolog/log"
2023-02-03 17:24:05 +03:00
"github.com/traefik/traefik/v3/pkg/config/runtime"
2020-02-11 03:26:04 +03:00
)
type udpRouterRepresentation struct {
* runtime . UDPRouterInfo
Name string ` json:"name,omitempty" `
Provider string ` json:"provider,omitempty" `
}
func newUDPRouterRepresentation ( name string , rt * runtime . UDPRouterInfo ) udpRouterRepresentation {
return udpRouterRepresentation {
UDPRouterInfo : rt ,
Name : name ,
Provider : getProviderName ( name ) ,
}
}
type udpServiceRepresentation struct {
* runtime . UDPServiceInfo
Name string ` json:"name,omitempty" `
Provider string ` json:"provider,omitempty" `
Type string ` json:"type,omitempty" `
}
func newUDPServiceRepresentation ( name string , si * runtime . UDPServiceInfo ) udpServiceRepresentation {
return udpServiceRepresentation {
UDPServiceInfo : si ,
Name : name ,
Provider : getProviderName ( name ) ,
Type : strings . ToLower ( extractType ( si . UDPService ) ) ,
}
}
func ( h Handler ) getUDPRouters ( rw http . ResponseWriter , request * http . Request ) {
results := make ( [ ] udpRouterRepresentation , 0 , len ( h . runtimeConfiguration . UDPRouters ) )
2023-01-09 19:24:05 +03:00
query := request . URL . Query ( )
criterion := newSearchCriterion ( query )
2020-02-11 03:26:04 +03:00
for name , rt := range h . runtimeConfiguration . UDPRouters {
if keepUDPRouter ( name , rt , criterion ) {
results = append ( results , newUDPRouterRepresentation ( name , rt ) )
}
}
2023-01-09 19:24:05 +03:00
sortRouters ( query , results )
2020-02-11 03:26:04 +03:00
rw . Header ( ) . Set ( "Content-Type" , "application/json" )
pageInfo , err := pagination ( request , len ( results ) )
if err != nil {
writeError ( rw , err . Error ( ) , http . StatusBadRequest )
return
}
rw . Header ( ) . Set ( nextPageHeader , strconv . Itoa ( pageInfo . nextPage ) )
err = json . NewEncoder ( rw ) . Encode ( results [ pageInfo . startIndex : pageInfo . endIndex ] )
if err != nil {
2022-11-21 20:36:05 +03:00
log . Ctx ( request . Context ( ) ) . Error ( ) . Err ( err ) . Send ( )
2020-02-11 03:26:04 +03:00
writeError ( rw , err . Error ( ) , http . StatusInternalServerError )
}
}
func ( h Handler ) getUDPRouter ( rw http . ResponseWriter , request * http . Request ) {
2024-01-25 11:56:05 +03:00
scapedRouterID := mux . Vars ( request ) [ "routerID" ]
routerID , err := url . PathUnescape ( scapedRouterID )
if err != nil {
writeError ( rw , fmt . Sprintf ( "unable to decode routerID %q: %s" , scapedRouterID , err ) , http . StatusBadRequest )
return
}
2020-02-11 03:26:04 +03:00
rw . Header ( ) . Set ( "Content-Type" , "application/json" )
router , ok := h . runtimeConfiguration . UDPRouters [ routerID ]
if ! ok {
writeError ( rw , fmt . Sprintf ( "router not found: %s" , routerID ) , http . StatusNotFound )
return
}
result := newUDPRouterRepresentation ( routerID , router )
2024-01-25 11:56:05 +03:00
err = json . NewEncoder ( rw ) . Encode ( result )
2020-02-11 03:26:04 +03:00
if err != nil {
2022-11-21 20:36:05 +03:00
log . Ctx ( request . Context ( ) ) . Error ( ) . Err ( err ) . Send ( )
2020-02-11 03:26:04 +03:00
writeError ( rw , err . Error ( ) , http . StatusInternalServerError )
}
}
func ( h Handler ) getUDPServices ( rw http . ResponseWriter , request * http . Request ) {
results := make ( [ ] udpServiceRepresentation , 0 , len ( h . runtimeConfiguration . UDPServices ) )
2023-01-09 19:24:05 +03:00
query := request . URL . Query ( )
criterion := newSearchCriterion ( query )
2020-02-11 03:26:04 +03:00
for name , si := range h . runtimeConfiguration . UDPServices {
if keepUDPService ( name , si , criterion ) {
results = append ( results , newUDPServiceRepresentation ( name , si ) )
}
}
2023-01-09 19:24:05 +03:00
sortServices ( query , results )
2020-02-11 03:26:04 +03:00
rw . Header ( ) . Set ( "Content-Type" , "application/json" )
pageInfo , err := pagination ( request , len ( results ) )
if err != nil {
writeError ( rw , err . Error ( ) , http . StatusBadRequest )
return
}
rw . Header ( ) . Set ( nextPageHeader , strconv . Itoa ( pageInfo . nextPage ) )
err = json . NewEncoder ( rw ) . Encode ( results [ pageInfo . startIndex : pageInfo . endIndex ] )
if err != nil {
2022-11-21 20:36:05 +03:00
log . Ctx ( request . Context ( ) ) . Error ( ) . Err ( err ) . Send ( )
2020-02-11 03:26:04 +03:00
writeError ( rw , err . Error ( ) , http . StatusInternalServerError )
}
}
func ( h Handler ) getUDPService ( rw http . ResponseWriter , request * http . Request ) {
2024-01-25 11:56:05 +03:00
scapedServiceID := mux . Vars ( request ) [ "serviceID" ]
serviceID , err := url . PathUnescape ( scapedServiceID )
if err != nil {
writeError ( rw , fmt . Sprintf ( "unable to decode serviceID %q: %s" , scapedServiceID , err ) , http . StatusBadRequest )
return
}
2020-02-11 03:26:04 +03:00
rw . Header ( ) . Set ( "Content-Type" , "application/json" )
service , ok := h . runtimeConfiguration . UDPServices [ serviceID ]
if ! ok {
writeError ( rw , fmt . Sprintf ( "service not found: %s" , serviceID ) , http . StatusNotFound )
return
}
result := newUDPServiceRepresentation ( serviceID , service )
2024-01-25 11:56:05 +03:00
err = json . NewEncoder ( rw ) . Encode ( result )
2020-02-11 03:26:04 +03:00
if err != nil {
2022-11-21 20:36:05 +03:00
log . Ctx ( request . Context ( ) ) . Error ( ) . Err ( err ) . Send ( )
2020-02-11 03:26:04 +03:00
writeError ( rw , err . Error ( ) , http . StatusInternalServerError )
}
}
func keepUDPRouter ( name string , item * runtime . UDPRouterInfo , criterion * searchCriterion ) bool {
if criterion == nil {
return true
}
2023-01-09 19:24:05 +03:00
return criterion . withStatus ( item . Status ) &&
criterion . searchIn ( name ) &&
criterion . filterService ( item . Service )
2020-02-11 03:26:04 +03:00
}
func keepUDPService ( name string , item * runtime . UDPServiceInfo , criterion * searchCriterion ) bool {
if criterion == nil {
return true
}
return criterion . withStatus ( item . Status ) && criterion . searchIn ( name )
}