Cómo obtengo el HandlerMethod coincide con un HttpServletRequest en un filter

Estoy escribiendo una aplicación de proxy simple, y quiero que la URL asignada sea manejada por mi controller, pero otra url (incluye error) puede reenviarse a otra dirección diferente. Así que utilizo Filter vez de HandlerInterceptorAdapter que no se puede invocar si no se encuentra el resourece porque cierto "controller de ruta resourece" lo trata.

Expectativa

http://localhost:8090/upload.html > Filter > http://localhost:8092/upload.html
http://localhost:8090/files/upload > Controller > http://localhost:8092/files/upload

No

http://localhost:8090/upload.html > Filter > http://localhost:8092/upload.html
http://localhost:8090/files/upload > Controller > http://localhost:8092/files/upload

O

http://localhost:8090/upload.html > Interceptor > http://localhost:8090/error No se encontró http://localhost:8090/files/upload > Filter > http://localhost:8092/files/upload

Manifestación

Configuré un Filter en mi subclass de WebMvcConfigurerAdapter .

 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Bean private javax.servlet.Filter proxyFilter() { return new OncePerRequestFilter() { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { System.out.println("[doFilterInternal]isCommitted=" + response.isCommitted() + ", URI = " + request.getRequestURI()); // if(!isRequestMappedInController(request, "my.pakcage")) httpProxyForward(request, response); } }; } // @Bean // private FilterRegistrationBean loggingFilterRegistration() { // FilterRegistrationBean registration = new FilterRegistrationBean(proxyFilter()); // registration.addUrlPatterns("/**"); // return registration; // } Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HandlerInterceptorAdapter() { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // How I determine a controller has handled the request in my interceptor? if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = ((HandlerMethod) handler); if (handlerMethod.getMethod().getDeclaringClass().getName().startsWith("nxtcasb.casbproxy")) { System.out.println("[preHandle]dealt: request uri = " + request.getRequestURI() + ", HandlerMethod = " + ((HandlerMethod) handler).getMethod()); return true; } else { System.out.println("[preHandle]isCommitted=" + response.isCommitted() + ", HandlerMethod = " + ((HandlerMethod) handler).getMethod()); } } // act as an api-gateway System.out.println("[preHandle]undealt: request uri = " + request.getRequestURI() + ", handler = " + handler); //ModelAndView modelView = new ModelAndView("networkingirect: http://www.bing.com"); //throw new ModelAndViewDefiningException(modelView); httpProxyForward(request, response); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (handler instanceof HandlerMethod) { System.out.println("[postHandle]dealt: uri = " + request.getRequestURI() + ", handler = " + ((HandlerMethod) handler).getMethod()); } else { System.out.println("[postHandle]undealt uri = " + request.getRequestURI() + ", handler = " + handler); } } }).addPathPatterns("/**", "/error"); } /** * this is the same as <mvc:default-servlet-handler/> <!-- This tag allows for mapping the DispatcherServlet to "/" --> * * @param configurer */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //registry.addResourceHandler("/**").addResourceLocations("classpath:/public"); } protected void httpProxyForward(HttpServletRequest request, HttpServletResponse response) { HttpClient httpClient = CreateHttpClient(); HttpUriRequest targetRequest = null; HttpResponse targetResponse = null; try { targetRequest = createHttpUriRequest(request); targetResponse = httpClient.execute(targetRequest); } catch (IOException e) { e.printStackTrace(); } finally { // make sure the entire entity was consumed, so the connection is released if (targetResponse != null) { EntityUtils.consumeQuietly(targetResponse.getEntity()); // @since 4.2 //Note: Don't need to close servlet outputStream: // http://stackoverflow.com/questions/1159168/should-one-call-close-on-httpservletresponse-getoutputstream-getwriter } } } } 

La api url /files/upload :

 @RestController @RequestMapping(value = "/files") public class FileUploadProxyController { private static final Logger logger = LoggerFactory.getLogger(FileUploadProxyController.class); @RequestMapping(value = "/upload", method = RequestMethod.POST) public ResponseEntity upload(HttpServletResponse response, HttpServletRequest request) { try { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; Iterator<String> it = multipartRequest.getFileNames(); MultipartFile multipart = multipartRequest.getFile(it.next()); String fileName = multipart.getOriginalFilename(); File dir = new File("files", "proxy-uploaded"); dir.mkdirs(); logger.debug("current dir = {}, uploaded dir = {}", System.getProperty("user.dir"), dir.getAbsolutePath()); File file = new File(dir, fileName); Files.copy(multipart.getInputStream(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); //FileCopyUtils.copy(multipart.getInputStream()) // byte[] bytes = multipart.getBytes(); // BuffenetworkingOutputStream stream = new BuffenetworkingOutputStream(new FileOutputStream("upload" + fileName)); // stream.write(bytes); // stream.close(); RestTemplate restTemplate = new RestTemplate(); SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); //// if Spring version < 3.1, see https://jira.springsource.org/browse/SPR-7909 // requestFactory.setBufferRequestBody(false); restTemplate.setRequestFactory(requestFactory); String url = "http://localhost:8092/files/upload"; // [resttemplate multipart post](https://jira.spring.io/browse/SPR-13571) // [Spring RestTemplate - how to enable full debugging/logging of requests/responses?](https://stackoverflow.com/questions/7952154/spring-resttemplate-how-to-enable-full-debugging-logging-of-requests-responses?rq=1) MultiValueMap<String, Object> param = new LinkedMultiValueMap<>(); param.add("file", new FileSystemResource(file)); param.add("param1", fileName); param.add("param2", "Leo"); HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String,Object>>(param); ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class); //String string = restTemplate.postForObject(url, param, String.class); //ResponseEntity e = restTemplate.exchange(url, HttpMethod.POST, // new HttpEntity<Resource>(new FileSystemResource(file)), String.class); return responseEntity; } catch (Exception e) { e.printStackTrace(); return new ResponseEntity("Upload failed", HttpStatus.BAD_REQUEST); } } @RequestMapping("/hello") public String hello() { return "hello word"; } } 

Después de leer Spring mvc autowire RequestMappingHandlerMapping o Get destination controller desde un HttpServletRequest

El siguiente código funciona:

 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { // https://stackoverflow.com/questions/129207/getting-spring-application-context @Autowinetworking private org.springframework.context.ApplicationContext appContext; private static final String MY_CONTROLLER_PACKAGE_NAME = "nxtcasb.casbproxy"; @Bean protected javax.servlet.Filter proxyFilter() { return new OncePerRequestFilter() { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { HandlerMethod handlerMethod = null; try { RequestMappingHandlerMapping req2HandlerMapping = (RequestMappingHandlerMapping) appContext.getBean("requestMappingHandlerMapping"); // Map<RequestMappingInfo, HandlerMethod> handlerMethods = req2HandlerMapping.getHandlerMethods(); HandlerExecutionChain handlerExeChain = req2HandlerMapping.getHandler(request); if (Objects.nonNull(handlerExeChain)) { handlerMethod = (HandlerMethod) handlerExeChain.getHandler(); if (handlerMethod.getBeanType().getName().startsWith(MY_CONTROLLER_PACKAGE_NAME)) { filterChain.doFilter(request, response); return; } } } catch (Exception e) { logger.warn("Lookup the handler method", e); } finally { logger.debug("URI = " + request.getRequestURI() + ", handlerMethod = " + handlerMethod); } httpProxyForward(request, response); } }; } // @Bean // private FilterRegistrationBean loggingFilterRegistration() { // FilterRegistrationBean registration = new FilterRegistrationBean(proxyFilter()); // registration.addUrlPatterns("/**"); // return registration; // } /** * this is the same as <mvc:default-servlet-handler/> <!-- This tag allows for mapping the DispatcherServlet to "/" --> * * @param configurer */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //registry.addResourceHandler("/**").addResourceLocations("classpath:/public"); } protected void httpProxyForward(HttpServletRequest request, HttpServletResponse response) { HttpClient httpClient = CreateHttpClient(); HttpUriRequest targetRequest = null; HttpResponse targetResponse = null; try { targetRequest = createHttpUriRequest(request); targetResponse = httpClient.execute(targetRequest); } catch (IOException e) { e.printStackTrace(); } finally { // make sure the entire entity was consumed, so the connection is released if (targetResponse != null) { EntityUtils.consumeQuietly(targetResponse.getEntity()); // @since 4.2 //Note: Don't need to close servlet outputStream: // http://stackoverflow.com/questions/1159168/should-one-call-close-on-httpservletresponse-getoutputstream-getwriter } } } } 
  • Spring Boot no actualiza el html estático (con Kotlin / Intellij)
  • BeanDefinitionParsingException cuando se intenta usar JPA con Kotlin y Spring boot
  • Retrofit: get un cuerpo vacío en la actualización de respuesta