diff --git a/pkg/api/handler.go b/pkg/api/handler.go index f0623d4cc..df4db9f98 100644 --- a/pkg/api/handler.go +++ b/pkg/api/handler.go @@ -76,7 +76,7 @@ func New(staticConfig static.Configuration, runtimeConfig *runtime.Configuration // createRouter creates API routes and router. func (h Handler) createRouter() *mux.Router { - router := mux.NewRouter() + router := mux.NewRouter().UseEncodedPath() if h.staticConfig.API.Debug { DebugHandler{}.Append(router) diff --git a/pkg/api/handler_entrypoint.go b/pkg/api/handler_entrypoint.go index 38801e8c7..2a7aee691 100644 --- a/pkg/api/handler_entrypoint.go +++ b/pkg/api/handler_entrypoint.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" "sort" "strconv" @@ -49,7 +50,13 @@ func (h Handler) getEntryPoints(rw http.ResponseWriter, request *http.Request) { } func (h Handler) getEntryPoint(rw http.ResponseWriter, request *http.Request) { - entryPointID := mux.Vars(request)["entryPointID"] + scapedEntryPointID := mux.Vars(request)["entryPointID"] + + entryPointID, err := url.PathUnescape(scapedEntryPointID) + if err != nil { + writeError(rw, fmt.Sprintf("unable to decode entryPointID %q: %s", scapedEntryPointID, err), http.StatusBadRequest) + return + } rw.Header().Set("Content-Type", "application/json") @@ -64,7 +71,7 @@ func (h Handler) getEntryPoint(rw http.ResponseWriter, request *http.Request) { Name: entryPointID, } - err := json.NewEncoder(rw).Encode(result) + err = json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) writeError(rw, err.Error(), http.StatusInternalServerError) diff --git a/pkg/api/handler_entrypoint_test.go b/pkg/api/handler_entrypoint_test.go index 114724b40..5172e4689 100644 --- a/pkg/api/handler_entrypoint_test.go +++ b/pkg/api/handler_entrypoint_test.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "net/http/httptest" + "net/url" "os" "strconv" "testing" @@ -169,6 +170,21 @@ func TestHandler_EntryPoints(t *testing.T) { jsonFile: "testdata/entrypoint-bar.json", }, }, + { + desc: "one entry point by id containing slash", + path: "/api/entrypoints/" + url.PathEscape("foo / bar"), + conf: static.Configuration{ + Global: &static.Global{}, + API: &static.API{}, + EntryPoints: map[string]*static.EntryPoint{ + "foo / bar": {Address: ":81"}, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + jsonFile: "testdata/entrypoint-foo-slash-bar.json", + }, + }, { desc: "one entry point by id, that does not exist", path: "/api/entrypoints/foo", diff --git a/pkg/api/handler_http.go b/pkg/api/handler_http.go index b2643cdfa..7afbc7f43 100644 --- a/pkg/api/handler_http.go +++ b/pkg/api/handler_http.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" "sort" "strconv" "strings" @@ -99,7 +100,13 @@ func (h Handler) getRouters(rw http.ResponseWriter, request *http.Request) { } func (h Handler) getRouter(rw http.ResponseWriter, request *http.Request) { - routerID := mux.Vars(request)["routerID"] + 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 + } rw.Header().Set("Content-Type", "application/json") @@ -111,7 +118,7 @@ func (h Handler) getRouter(rw http.ResponseWriter, request *http.Request) { result := newRouterRepresentation(routerID, router) - err := json.NewEncoder(rw).Encode(result) + err = json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) writeError(rw, err.Error(), http.StatusInternalServerError) @@ -151,7 +158,13 @@ func (h Handler) getServices(rw http.ResponseWriter, request *http.Request) { } func (h Handler) getService(rw http.ResponseWriter, request *http.Request) { - serviceID := mux.Vars(request)["serviceID"] + 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 + } rw.Header().Add("Content-Type", "application/json") @@ -163,7 +176,7 @@ func (h Handler) getService(rw http.ResponseWriter, request *http.Request) { result := newServiceRepresentation(serviceID, service) - err := json.NewEncoder(rw).Encode(result) + err = json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) writeError(rw, err.Error(), http.StatusInternalServerError) @@ -203,7 +216,13 @@ func (h Handler) getMiddlewares(rw http.ResponseWriter, request *http.Request) { } func (h Handler) getMiddleware(rw http.ResponseWriter, request *http.Request) { - middlewareID := mux.Vars(request)["middlewareID"] + scapedMiddlewareID := mux.Vars(request)["middlewareID"] + + middlewareID, err := url.PathUnescape(scapedMiddlewareID) + if err != nil { + writeError(rw, fmt.Sprintf("unable to decode middlewareID %q: %s", scapedMiddlewareID, err), http.StatusBadRequest) + return + } rw.Header().Set("Content-Type", "application/json") @@ -215,7 +234,7 @@ func (h Handler) getMiddleware(rw http.ResponseWriter, request *http.Request) { result := newMiddlewareRepresentation(middlewareID, middleware) - err := json.NewEncoder(rw).Encode(result) + err = json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) writeError(rw, err.Error(), http.StatusInternalServerError) diff --git a/pkg/api/handler_http_test.go b/pkg/api/handler_http_test.go index b186a2d15..d7f905c5d 100644 --- a/pkg/api/handler_http_test.go +++ b/pkg/api/handler_http_test.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "net/http/httptest" + "net/url" "os" "strconv" "testing" @@ -223,6 +224,27 @@ func TestHandler_HTTP(t *testing.T) { jsonFile: "testdata/router-bar.json", }, }, + { + desc: "one router by id containing slash", + path: "/api/http/routers/" + url.PathEscape("foo / bar@myprovider"), + conf: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ + "foo / bar@myprovider": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`foo.bar`)", + Middlewares: []string{"auth", "addPrefixTest@anotherprovider"}, + }, + Status: "enabled", + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + jsonFile: "testdata/router-foo-slash-bar.json", + }, + }, { desc: "one router by id, implicitly using default TLS options", path: "/api/http/routers/baz@myprovider", @@ -583,6 +605,35 @@ func TestHandler_HTTP(t *testing.T) { jsonFile: "testdata/service-bar.json", }, }, + { + desc: "one service by id containing slash", + path: "/api/http/services/" + url.PathEscape("foo / bar@myprovider"), + conf: runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ + "foo / bar@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + PassHostHeader: Bool(true), + Servers: []dynamic.Server{ + { + URL: "http://127.0.0.1", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider", "test@myprovider"}, + } + si.UpdateServerStatus("http://127.0.0.1", "UP") + return si + }(), + }, + }, + expected: expected{ + statusCode: http.StatusOK, + jsonFile: "testdata/service-foo-slash-bar.json", + }, + }, { desc: "one service by id, that does not exist", path: "/api/http/services/nono@myprovider", @@ -819,6 +870,26 @@ func TestHandler_HTTP(t *testing.T) { jsonFile: "testdata/middleware-auth.json", }, }, + { + desc: "one middleware by id containing slash", + path: "/api/http/middlewares/" + url.PathEscape("foo / bar@myprovider"), + conf: runtime.Configuration{ + Middlewares: map[string]*runtime.MiddlewareInfo{ + "foo / bar@myprovider": { + Middleware: &dynamic.Middleware{ + AddPrefix: &dynamic.AddPrefix{ + Prefix: "/titi", + }, + }, + UsedBy: []string{"test@myprovider"}, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + jsonFile: "testdata/middleware-foo-slash-bar.json", + }, + }, { desc: "one middleware by id, that does not exist", path: "/api/http/middlewares/foo@myprovider", diff --git a/pkg/api/handler_tcp.go b/pkg/api/handler_tcp.go index 390e1179c..b738bf953 100644 --- a/pkg/api/handler_tcp.go +++ b/pkg/api/handler_tcp.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" "sort" "strconv" "strings" @@ -92,7 +93,13 @@ func (h Handler) getTCPRouters(rw http.ResponseWriter, request *http.Request) { } func (h Handler) getTCPRouter(rw http.ResponseWriter, request *http.Request) { - routerID := mux.Vars(request)["routerID"] + 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 + } rw.Header().Set("Content-Type", "application/json") @@ -104,7 +111,7 @@ func (h Handler) getTCPRouter(rw http.ResponseWriter, request *http.Request) { result := newTCPRouterRepresentation(routerID, router) - err := json.NewEncoder(rw).Encode(result) + err = json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) writeError(rw, err.Error(), http.StatusInternalServerError) @@ -144,7 +151,13 @@ func (h Handler) getTCPServices(rw http.ResponseWriter, request *http.Request) { } func (h Handler) getTCPService(rw http.ResponseWriter, request *http.Request) { - serviceID := mux.Vars(request)["serviceID"] + 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 + } rw.Header().Set("Content-Type", "application/json") @@ -156,7 +169,7 @@ func (h Handler) getTCPService(rw http.ResponseWriter, request *http.Request) { result := newTCPServiceRepresentation(serviceID, service) - err := json.NewEncoder(rw).Encode(result) + err = json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) writeError(rw, err.Error(), http.StatusInternalServerError) @@ -196,7 +209,13 @@ func (h Handler) getTCPMiddlewares(rw http.ResponseWriter, request *http.Request } func (h Handler) getTCPMiddleware(rw http.ResponseWriter, request *http.Request) { - middlewareID := mux.Vars(request)["middlewareID"] + scapedMiddlewareID := mux.Vars(request)["middlewareID"] + + middlewareID, err := url.PathUnescape(scapedMiddlewareID) + if err != nil { + writeError(rw, fmt.Sprintf("unable to decode middlewareID %q: %s", scapedMiddlewareID, err), http.StatusBadRequest) + return + } rw.Header().Set("Content-Type", "application/json") @@ -208,7 +227,7 @@ func (h Handler) getTCPMiddleware(rw http.ResponseWriter, request *http.Request) result := newTCPMiddlewareRepresentation(middlewareID, middleware) - err := json.NewEncoder(rw).Encode(result) + err = json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) writeError(rw, err.Error(), http.StatusInternalServerError) diff --git a/pkg/api/handler_tcp_test.go b/pkg/api/handler_tcp_test.go index d15ec1cdf..85e5fdc19 100644 --- a/pkg/api/handler_tcp_test.go +++ b/pkg/api/handler_tcp_test.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "net/http/httptest" + "net/url" "os" "testing" @@ -212,6 +213,25 @@ func TestHandler_TCP(t *testing.T) { jsonFile: "testdata/tcprouter-bar.json", }, }, + { + desc: "one TCP router by id containing slash", + path: "/api/tcp/routers/" + url.PathEscape("foo / bar@myprovider"), + conf: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ + "foo / bar@myprovider": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`foo.bar`)", + }, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + jsonFile: "testdata/tcprouter-foo-slash-bar.json", + }, + }, { desc: "one TCP router by id, that does not exist", path: "/api/tcp/routers/foo@myprovider", @@ -476,6 +496,30 @@ func TestHandler_TCP(t *testing.T) { jsonFile: "testdata/tcpservice-bar.json", }, }, + { + desc: "one tcp service by id containing slash", + path: "/api/tcp/services/" + url.PathEscape("foo / bar@myprovider"), + conf: runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ + "foo / bar@myprovider": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.1:2345", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider", "test@myprovider"}, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + jsonFile: "testdata/tcpservice-foo-slash-bar.json", + }, + }, { desc: "one tcp service by id, that does not exist", path: "/api/tcp/services/nono@myprovider", @@ -697,6 +741,26 @@ func TestHandler_TCP(t *testing.T) { jsonFile: "testdata/tcpmiddleware-ipwhitelist.json", }, }, + { + desc: "one middleware by id containing slash", + path: "/api/tcp/middlewares/" + url.PathEscape("foo / bar@myprovider"), + conf: runtime.Configuration{ + TCPMiddlewares: map[string]*runtime.TCPMiddlewareInfo{ + "foo / bar@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider", "test@myprovider"}, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + jsonFile: "testdata/tcpmiddleware-foo-slash-bar.json", + }, + }, { desc: "one middleware by id, that does not exist", path: "/api/tcp/middlewares/foo@myprovider", diff --git a/pkg/api/handler_udp.go b/pkg/api/handler_udp.go index 4cfe465d9..c3fe44a8a 100644 --- a/pkg/api/handler_udp.go +++ b/pkg/api/handler_udp.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" "sort" "strconv" "strings" @@ -76,7 +77,13 @@ func (h Handler) getUDPRouters(rw http.ResponseWriter, request *http.Request) { } func (h Handler) getUDPRouter(rw http.ResponseWriter, request *http.Request) { - routerID := mux.Vars(request)["routerID"] + 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 + } rw.Header().Set("Content-Type", "application/json") @@ -88,7 +95,7 @@ func (h Handler) getUDPRouter(rw http.ResponseWriter, request *http.Request) { result := newUDPRouterRepresentation(routerID, router) - err := json.NewEncoder(rw).Encode(result) + err = json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) writeError(rw, err.Error(), http.StatusInternalServerError) @@ -128,7 +135,13 @@ func (h Handler) getUDPServices(rw http.ResponseWriter, request *http.Request) { } func (h Handler) getUDPService(rw http.ResponseWriter, request *http.Request) { - serviceID := mux.Vars(request)["serviceID"] + 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 + } rw.Header().Set("Content-Type", "application/json") @@ -140,7 +153,7 @@ func (h Handler) getUDPService(rw http.ResponseWriter, request *http.Request) { result := newUDPServiceRepresentation(serviceID, service) - err := json.NewEncoder(rw).Encode(result) + err = json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) writeError(rw, err.Error(), http.StatusInternalServerError) diff --git a/pkg/api/handler_udp_test.go b/pkg/api/handler_udp_test.go index b091f8e1d..56c9b3a6f 100644 --- a/pkg/api/handler_udp_test.go +++ b/pkg/api/handler_udp_test.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "net/http/httptest" + "net/url" "os" "testing" @@ -190,6 +191,24 @@ func TestHandler_UDP(t *testing.T) { jsonFile: "testdata/udprouter-bar.json", }, }, + { + desc: "one UDP router by id containing slash", + path: "/api/udp/routers/" + url.PathEscape("foo / bar@myprovider"), + conf: runtime.Configuration{ + UDPRouters: map[string]*runtime.UDPRouterInfo{ + "foo / bar@myprovider": { + UDPRouter: &dynamic.UDPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + }, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + jsonFile: "testdata/udprouter-foo-slash-bar.json", + }, + }, { desc: "one UDP router by id, that does not exist", path: "/api/udp/routers/foo@myprovider", @@ -453,6 +472,30 @@ func TestHandler_UDP(t *testing.T) { jsonFile: "testdata/udpservice-bar.json", }, }, + { + desc: "one udp service by id containing slash", + path: "/api/udp/services/" + url.PathEscape("foo / bar@myprovider"), + conf: runtime.Configuration{ + UDPServices: map[string]*runtime.UDPServiceInfo{ + "foo / bar@myprovider": { + UDPService: &dynamic.UDPService{ + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "127.0.0.1:2345", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider", "test@myprovider"}, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + jsonFile: "testdata/udpservice-foo-slash-bar.json", + }, + }, { desc: "one udp service by id, that does not exist", path: "/api/udp/services/nono@myprovider", diff --git a/pkg/api/testdata/entrypoint-foo-slash-bar.json b/pkg/api/testdata/entrypoint-foo-slash-bar.json new file mode 100644 index 000000000..5f0bcbafc --- /dev/null +++ b/pkg/api/testdata/entrypoint-foo-slash-bar.json @@ -0,0 +1,5 @@ +{ + "address": ":81", + "http": {}, + "name": "foo / bar" +} diff --git a/pkg/api/testdata/middleware-foo-slash-bar.json b/pkg/api/testdata/middleware-foo-slash-bar.json new file mode 100644 index 000000000..5e68c7e3d --- /dev/null +++ b/pkg/api/testdata/middleware-foo-slash-bar.json @@ -0,0 +1,12 @@ +{ + "addPrefix": { + "prefix": "/titi" + }, + "name": "foo / bar@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "addprefix", + "usedBy": [ + "test@myprovider" + ] +} diff --git a/pkg/api/testdata/router-foo-slash-bar.json b/pkg/api/testdata/router-foo-slash-bar.json new file mode 100644 index 000000000..f9e30c240 --- /dev/null +++ b/pkg/api/testdata/router-foo-slash-bar.json @@ -0,0 +1,17 @@ +{ + "entryPoints": [ + "web" + ], + "middlewares": [ + "auth", + "addPrefixTest@anotherprovider" + ], + "name": "foo / bar@myprovider", + "provider": "myprovider", + "rule": "Host(`foo.bar`)", + "service": "foo-service@myprovider", + "status": "enabled", + "using": [ + "web" + ] +} diff --git a/pkg/api/testdata/service-foo-slash-bar.json b/pkg/api/testdata/service-foo-slash-bar.json new file mode 100644 index 000000000..58cde8530 --- /dev/null +++ b/pkg/api/testdata/service-foo-slash-bar.json @@ -0,0 +1,21 @@ +{ + "loadBalancer": { + "passHostHeader": true, + "servers": [ + { + "url": "http://127.0.0.1" + } + ] + }, + "name": "foo / bar@myprovider", + "provider": "myprovider", + "serverStatus": { + "http://127.0.0.1": "UP" + }, + "status": "enabled", + "type": "loadbalancer", + "usedBy": [ + "foo@myprovider", + "test@myprovider" + ] +} diff --git a/pkg/api/testdata/tcpmiddleware-foo-slash-bar.json b/pkg/api/testdata/tcpmiddleware-foo-slash-bar.json new file mode 100644 index 000000000..985e0380a --- /dev/null +++ b/pkg/api/testdata/tcpmiddleware-foo-slash-bar.json @@ -0,0 +1,13 @@ +{ + "ipWhiteList": { + "sourceRange": ["127.0.0.1/32"] + }, + "name": "foo / bar@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "ipwhitelist", + "usedBy": [ + "bar@myprovider", + "test@myprovider" + ] +} diff --git a/pkg/api/testdata/tcprouter-foo-slash-bar.json b/pkg/api/testdata/tcprouter-foo-slash-bar.json new file mode 100644 index 000000000..4656ea9f9 --- /dev/null +++ b/pkg/api/testdata/tcprouter-foo-slash-bar.json @@ -0,0 +1,13 @@ +{ + "entryPoints": [ + "web" + ], + "name": "foo / bar@myprovider", + "provider": "myprovider", + "rule": "Host(`foo.bar`)", + "service": "foo-service@myprovider", + "status": "enabled", + "using": [ + "web" + ] +} diff --git a/pkg/api/testdata/tcpservice-foo-slash-bar.json b/pkg/api/testdata/tcpservice-foo-slash-bar.json new file mode 100644 index 000000000..b250966d5 --- /dev/null +++ b/pkg/api/testdata/tcpservice-foo-slash-bar.json @@ -0,0 +1,17 @@ +{ + "loadBalancer": { + "servers": [ + { + "address": "127.0.0.1:2345" + } + ] + }, + "name": "foo / bar@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "loadbalancer", + "usedBy": [ + "foo@myprovider", + "test@myprovider" + ] +} diff --git a/pkg/api/testdata/udprouter-foo-slash-bar.json b/pkg/api/testdata/udprouter-foo-slash-bar.json new file mode 100644 index 000000000..276c1a907 --- /dev/null +++ b/pkg/api/testdata/udprouter-foo-slash-bar.json @@ -0,0 +1,12 @@ +{ + "entryPoints": [ + "web" + ], + "name": "foo / bar@myprovider", + "provider": "myprovider", + "service": "foo-service@myprovider", + "status": "enabled", + "using": [ + "web" + ] +} diff --git a/pkg/api/testdata/udpservice-foo-slash-bar.json b/pkg/api/testdata/udpservice-foo-slash-bar.json new file mode 100644 index 000000000..b250966d5 --- /dev/null +++ b/pkg/api/testdata/udpservice-foo-slash-bar.json @@ -0,0 +1,17 @@ +{ + "loadBalancer": { + "servers": [ + { + "address": "127.0.0.1:2345" + } + ] + }, + "name": "foo / bar@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "loadbalancer", + "usedBy": [ + "foo@myprovider", + "test@myprovider" + ] +} diff --git a/webui/src/_mixins/GetTableProps.js b/webui/src/_mixins/GetTableProps.js index 014a397bb..020b54657 100644 --- a/webui/src/_mixins/GetTableProps.js +++ b/webui/src/_mixins/GetTableProps.js @@ -138,7 +138,7 @@ const GetTablePropsMixin = { return { onRowClick: row => this.$router.push({ - path: `/${type.replace('-', '/', 'gi')}/${row.name}` + path: `/${type.replace('-', '/', 'gi')}/${encodeURIComponent(row.name)}` }), columns: allColumns.filter(c => get(propsByType, `${type}.columns`, []).includes(c.name) diff --git a/webui/src/_services/HttpService.js b/webui/src/_services/HttpService.js index 0e206b24d..c239f20ed 100644 --- a/webui/src/_services/HttpService.js +++ b/webui/src/_services/HttpService.js @@ -14,7 +14,7 @@ function getAllRouters (params) { } function getRouterByName (name) { - return APP.api.get(`${apiBase}/routers/${name}`) + return APP.api.get(`${apiBase}/routers/${encodeURIComponent(name)}`) .then(body => { console.log('Success -> HttpService -> getRouterByName', body.data) return body.data @@ -32,7 +32,7 @@ function getAllServices (params) { } function getServiceByName (name) { - return APP.api.get(`${apiBase}/services/${name}`) + return APP.api.get(`${apiBase}/services/${encodeURIComponent(name)}`) .then(body => { console.log('Success -> HttpService -> getServiceByName', body.data) return body.data @@ -50,7 +50,7 @@ function getAllMiddlewares (params) { } function getMiddlewareByName (name) { - return APP.api.get(`${apiBase}/middlewares/${name}`) + return APP.api.get(`${apiBase}/middlewares/${encodeURIComponent(name)}`) .then(body => { console.log('Success -> HttpService -> getMiddlewareByName', body.data) return body.data diff --git a/webui/src/_services/TcpService.js b/webui/src/_services/TcpService.js index e5645e9b1..9132c8c19 100644 --- a/webui/src/_services/TcpService.js +++ b/webui/src/_services/TcpService.js @@ -14,7 +14,7 @@ function getAllRouters (params) { } function getRouterByName (name) { - return APP.api.get(`${apiBase}/routers/${name}`) + return APP.api.get(`${apiBase}/routers/${encodeURIComponent(name)}`) .then(body => { console.log('Success -> TcpService -> getRouterByName', body.data) return body.data @@ -32,7 +32,7 @@ function getAllServices (params) { } function getServiceByName (name) { - return APP.api.get(`${apiBase}/services/${name}`) + return APP.api.get(`${apiBase}/services/${encodeURIComponent(name)}`) .then(body => { console.log('Success -> TcpService -> getServiceByName', body.data) return body.data @@ -50,7 +50,7 @@ function getAllMiddlewares (params) { } function getMiddlewareByName (name) { - return APP.api.get(`${apiBase}/middlewares/${name}`) + return APP.api.get(`${apiBase}/middlewares/${encodeURIComponent(name)}`) .then(body => { console.log('Success -> TcpService -> getMiddlewareByName', body.data) return body.data diff --git a/webui/src/_services/UdpService.js b/webui/src/_services/UdpService.js index fd641d357..d0f8551da 100644 --- a/webui/src/_services/UdpService.js +++ b/webui/src/_services/UdpService.js @@ -14,7 +14,7 @@ function getAllRouters (params) { } function getRouterByName (name) { - return APP.api.get(`${apiBase}/routers/${name}`) + return APP.api.get(`${apiBase}/routers/${encodeURIComponent(name)}`) .then(body => { console.log('Success -> UdpService -> getRouterByName', body.data) return body.data @@ -32,7 +32,7 @@ function getAllServices (params) { } function getServiceByName (name) { - return APP.api.get(`${apiBase}/services/${name}`) + return APP.api.get(`${apiBase}/services/${encodeURIComponent(name)}`) .then(body => { console.log('Success -> UdpService -> getServiceByName', body.data) return body.data diff --git a/webui/src/pages/_commons/RouterDetail.vue b/webui/src/pages/_commons/RouterDetail.vue index 1fec28292..c93a5ccfe 100644 --- a/webui/src/pages/_commons/RouterDetail.vue +++ b/webui/src/pages/_commons/RouterDetail.vue @@ -279,7 +279,7 @@ export default { return data.service } - return `${data.service}@${data.provider}` + return `${encodeURIComponent(data.service)}@${data.provider}` } }, created () {