Ecwid / consul-api

Java client for Consul HTTP API
Apache License 2.0
416 stars 177 forks source link

CatalogConsulClient.getCatalogService exception when serviceName contains invalid characters #181

Open ghost opened 5 years ago

ghost commented 5 years ago

If a Consul server contains a service with a special character in the name, consul client will throw "Illegal character in path" error. The problem is in the CatalogConsulClient.getCatalogService where a call is made to rawClient by concatenating "/v1/catalog/service" with serviceName without escaping contents of serviceName. The easiest way to reproduce this issue is to register a service with $ in its name, create a basic spring-boot project with /actuator/consul endpoint exposed and then try navigating to that point. Here's a call stack of such application:

create:852, URI (java.net)

:66, HttpGet (org.apache.http.client.methods) makeGetRequest:33, AbstractHttpTransport (com.ecwid.consul.transport) makeGetRequest:128, ConsulRawClient (com.ecwid.consul.v1) getCatalogService:153, CatalogConsulClient (com.ecwid.consul.v1.catalog) getCatalogService:134, CatalogConsulClient (com.ecwid.consul.v1.catalog) getCatalogService:377, ConsulClient (com.ecwid.consul.v1) invoke:57, ConsulEndpoint (org.springframework.cloud.consul) invoke0:-1, NativeMethodAccessorImpl (sun.reflect) invoke:62, NativeMethodAccessorImpl (sun.reflect) invoke:43, DelegatingMethodAccessorImpl (sun.reflect) invoke:498, Method (java.lang.reflect) invokeMethod:246, ReflectionUtils (org.springframework.util) invoke:76, ReflectiveOperationInvoker (org.springframework.boot.actuate.endpoint.invoke.reflect) invoke:61, AbstractDiscoveredOperation (org.springframework.boot.actuate.endpoint.annotation) handle:294, AbstractWebMvcEndpointHandlerMapping$ServletWebOperationAdapter (org.springframework.boot.actuate.endpoint.web.servlet) handle:355, AbstractWebMvcEndpointHandlerMapping$OperationHandler (org.springframework.boot.actuate.endpoint.web.servlet) invoke:-1, GeneratedMethodAccessor55 (sun.reflect) invoke:43, DelegatingMethodAccessorImpl (sun.reflect) invoke:498, Method (java.lang.reflect) doInvoke:189, InvocableHandlerMethod (org.springframework.web.method.support) invokeForRequest:138, InvocableHandlerMethod (org.springframework.web.method.support) invokeAndHandle:102, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation) invokeHandlerMethod:895, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation) handleInternal:800, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation) handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method) doDispatch:1038, DispatcherServlet (org.springframework.web.servlet) doService:942, DispatcherServlet (org.springframework.web.servlet) processRequest:1005, FrameworkServlet (org.springframework.web.servlet) doGet:897, FrameworkServlet (org.springframework.web.servlet) service:634, HttpServlet (javax.servlet.http) service:882, FrameworkServlet (org.springframework.web.servlet) service:741, HttpServlet (javax.servlet.http) internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core) doFilter:166, ApplicationFilterChain (org.apache.catalina.core) doFilter:53, WsFilter (org.apache.tomcat.websocket.server) internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core) doFilter:166, ApplicationFilterChain (org.apache.catalina.core) doFilterInternal:90, HttpTraceFilter (org.springframework.boot.actuate.web.trace.servlet) doFilter:107, OncePerRequestFilter (org.springframework.web.filter) internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core) doFilter:166, ApplicationFilterChain (org.apache.catalina.core) doFilterInternal:99, RequestContextFilter (org.springframework.web.filter) doFilter:107, OncePerRequestFilter (org.springframework.web.filter) internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core) doFilter:166, ApplicationFilterChain (org.apache.catalina.core) doFilterInternal:92, FormContentFilter (org.springframework.web.filter) doFilter:107, OncePerRequestFilter (org.springframework.web.filter) internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core) doFilter:166, ApplicationFilterChain (org.apache.catalina.core) doFilterInternal:93, HiddenHttpMethodFilter (org.springframework.web.filter) doFilter:107, OncePerRequestFilter (org.springframework.web.filter) internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core) doFilter:166, ApplicationFilterChain (org.apache.catalina.core) doFilter:50, ExceptionLoggingFilter (org.springframework.cloud.sleuth.instrument.web) internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core) doFilter:166, ApplicationFilterChain (org.apache.catalina.core) doFilter:86, TracingFilter (brave.servlet) internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core) doFilter:166, ApplicationFilterChain (org.apache.catalina.core) filterAndRecordMetrics:117, WebMvcMetricsFilter (org.springframework.boot.actuate.metrics.web.servlet) doFilterInternal:106, WebMvcMetricsFilter (org.springframework.boot.actuate.metrics.web.servlet) doFilter:107, OncePerRequestFilter (org.springframework.web.filter) internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core) doFilter:166, ApplicationFilterChain (org.apache.catalina.core) doFilterInternal:200, CharacterEncodingFilter (org.springframework.web.filter) doFilter:107, OncePerRequestFilter (org.springframework.web.filter) internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core) doFilter:166, ApplicationFilterChain (org.apache.catalina.core) invoke:199, StandardWrapperValve (org.apache.catalina.core) invoke:96, StandardContextValve (org.apache.catalina.core) invoke:490, AuthenticatorBase (org.apache.catalina.authenticator) invoke:139, StandardHostValve (org.apache.catalina.core) invoke:92, ErrorReportValve (org.apache.catalina.valves) invoke:74, StandardEngineValve (org.apache.catalina.core) service:343, CoyoteAdapter (org.apache.catalina.connector) service:408, Http11Processor (org.apache.coyote.http11) process:66, AbstractProcessorLight (org.apache.coyote) process:834, AbstractProtocol$ConnectionHandler (org.apache.coyote) doRun:1417, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net) run:49, SocketProcessorBase (org.apache.tomcat.util.net) runWorker:1149, ThreadPoolExecutor (java.util.concurrent) run:624, ThreadPoolExecutor$Worker (java.util.concurrent) run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads) run:748, Thread (java.lang)
tommyk-gears commented 3 years ago

Looks like the fix for #117 more or less disabled url encoding of the constructed endpoint URLs (unless the URL happen to contain a space). As the problem is with the ConsulRawClient it affects many methods at the library api level. A simple workaround is to url encode the serviceName, configKey, etc that eventually get appended into a URL, but I do think it is "leaky" - the user of the library should not need to deal with url encoding.