¿Cómo redirigir las URL con barra diagonal a las correspondientes sin ella?

Spring MVC (3.0) considera las URL con y sin barras diagonales como la misma URL.

Por ejemplo:

http://www.example.org/data/something = http://www.example.org/data/something/

Necesito redirigir la URL con barras diagonales

http://www.example.org/data/something/

a la URL sin él:

http://www.example.org/data/algo

Necesito hacer esto internamente la aplicación (para no reescribir las reglas a través de Apache, etc.).

Una forma de hacerlo es:

@ResponseStatus(value=HttpStatus.MOVED_PERMANENTLY) @RequestMapping(value = "/data/something/") public String dataSomethingRedirect(...) { return "redirect:/data/something"; } 

pero esto generalmente tiene 2 problemas:

  1. demasiados controladores
  2. problema con los parámetros: como la encoding incorrecta

Pregunta

¿Hay alguna forma de interceptar todas las URL y, en caso de que tengan una barra diagonal final, redirigirlas a la relativa sin barra diagonal?

Puede enumerar todas las reglas de reescritura que necesita en su configuración web

Si no hay muchos de estos, puede configurar vistas de redireccionamiento como esta

 @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addRedirectViewController("/my/path/", "/my/path") .setKeepQueryParams(true) .setStatusCode(HttpStatus.PERMANENT_REDIRECT); } 

O podría crear un HandlerInterceptor personalizado

Pero los interceptores se producen antes de que las solicitudes se asignen a un Controller.action específico y no hay forma de conocer los controladores y las acciones en ese contexto.

Todo lo que tienes es HTTPServlet API y request + response; así que puedes:

 response.sendRedirect("http://example.org/whitout-trailing-slash"); 

La respuesta que no quieres leer.

Este comportamiento (URL con barra diagonal = URL sin él) es perfectamente “válido” cuando se considera HTTP. Al menos este es el comportamiento predeterminado con Spring, que puede deshabilitar con useTrailingSlashMatch ( vea javadoc ).

Así que usar reglas de reescritura / redirección en el servidor de aplicaciones para el usuario podría ser una solución; pero una vez más, no conozco tus limitaciones (¿tal vez podrías explicar esto y podríamos encontrar otras soluciones?).

Creo que la mejor opción sería hacer esto antes de ingresar al servlet de Spring web, usando UrlRewriteFilter. Esto asegurará que sus reglas de redirección no afecten a sus controladores.

Tenga en cuenta que escribe las reglas en su proyecto .war, no en un apache con mod_rewrite.

Vaya aquí para el proyecto de la biblioteca en googlecode.

en el urlrewrite.xml escribe:

     Remove trailing slash ^(.*)/$ $1   

En el web.xml de su aplicación, agregue:

  UrlRewriteFilter org.tuckey.web.filters.urlrewrite.UrlRewriteFilter  confPath /WEB-INF/urlrewrite.xml    UrlRewriteFilter /* REQUEST  

Cuidado, el orden de statement de los filtros en el web.xml es importante, así que trata de declararlo antes de la spring.

Por supuesto, esto es solo una fracción de lo que puede hacer UrlRewriteFilter.

Saludos.

Esto generalmente me funciona con URLRewriteFilter en Spring.

     Remove trailing slash for SEO purposes /**/ %{context-path}/$1   

No estoy seguro si Spring 3.0 tenía esto, pero Spring 3.1 RequestMappingHandlerMapping te permite establecer una propiedad “useTrailingSlashMatch”. Por defecto es cierto.

Creo que cambiarlo a falso resolvería su problema, sin embargo, afectaría TODAS las asignaciones manejadas por RequestMappingHandlerMapping en su aplicación … por lo que es posible que tenga que hacer una gran cantidad de regresión.

Estoy de acuerdo con @Brian Clozel: no creo que sea una buena idea hacer lo que quieras. Entonces, ¿por qué lo necesitas?

De todos modos, creo que la solución más simple es escribir un javax.servlet.Filter personalizado. Por lo tanto, no hay dependencia de spring. Si la URL de la solicitud termina con una barra, solo tiene que redirigir a la misma URL sin ella. Pero cuidado:

  • Todos los parámetros (GET y POST) deben agregarse como parámetros GET. ¿Está seguro de que su aplicación es un método independiente ?

  • Puede tener algunos problemas con la encoding. En el filtro puede codificar los parámetros POST a la encoding requerida. Pero la encoding predeterminada para los parámetros GET no está configurada en su aplicación. Se configura en server.xml (si Tomcat) y el valor predeterminado es ISO-8859-1.

¡Buena suerte!

Basado en SEO, creo que es importante hacer una distinción.

Si la URL que terminó en la barra diagonal final está indexada en los motores de búsqueda y hay enlaces en Internet, se requiere una redirección permanente (301), como indica Uddhav Kambli. La redirección estándar (302) será mejor que tener una URL duplicada, pero no es lo suficientemente buena.

Sin embargo, si la URL nunca existió, no está indexada en Internet y no hay enlaces externos, la URL no existe. Por lo tanto, un 404, página no encontrada, es un mejor ajuste.

WEB-INF / urlrewrite.xml

     Remove trailing slash ^(.+)/$ 404 null   

Y para completar la configuración …

agregar a WEB-INF / web.xml

  UrlRewriteFilter org.tuckey.web.filters.urlrewrite.UrlRewriteFilter  confPath /WEB-INF/urlrewrite.xml    UrlRewriteFilter /* REQUEST  

Maven

  org.tuckey urlrewritefilter 4.0.3  

Descubrí que esto también se puede manejar mucho más simplemente usando un bean ErrorViewResolver en algún lugar de su @Configuration:

 @Autowired private DefaultErrorViewResolver defaultErrorViewResolver; @Bean ErrorViewResolver errorViewResolver() { return new ErrorViewResolver() { @Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map model) { if(model.containsKey("path") && !model.get("path").toString().endsWith("/")) { return new ModelAndView("redirect:"+model.get("path") + "/"); } return defaultErrorViewResolver.resolveErrorView(request, status, model); } }; } 

No estoy seguro si esto es una buena o mala práctica, pero es efectivo en mi circunstancia y hace exactamente lo que necesito que haga para una ruta arbitraria ‘foo’: responda con un redireccionamiento 302 a / foo / cuando usted solicite / foo y responde como debería cuando solicitas / foo.