Подтвердить что ты не робот

Как перенаправить URL-адреса с завершающим косой чертой на соответствующие без него?

Spring MVC (3.0) рассматривает URL-адреса с и без конечных косых черт как один и тот же URL-адрес.

Например:

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

Мне нужно перенаправить URL с завершающими косой чертой

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

к URL без него:

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

Мне нужно сделать это внутри приложения (так что не переписывайте правила через Apache и т.д.).

Способ сделать это:

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

но у этого обычно есть 2 проблемы:

  • слишком много контроллеров
  • проблема с параметрами: как неправильное кодирование

Вопрос

Есть ли способ перехватить все URL-адреса и в случае, если они имеют завершающую косую черту, перенаправить их на относительный без косой черты?

4b9b3361

Ответ 1

Вы можете перечислить все правила перезаписи, которые вам нужны в вашей веб-конфигурации

Если их не так много, вы можете настроить такие виды переадресации, как это.

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

Или вы можете создать пользовательский HandlerInterceptor

Но перехватчики возникают до того, как запросы сопоставлены с конкретным Controller.action, и вы не можете знать контроллеры и действия в этом контексте.

Все, что у вас есть, это API HTTPServlet и запрос + ответ; поэтому вы можете:

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

Ответ, который вы не хотите читать

Это поведение (URL с конечным слэш = URL без него) отлично "допустимо" при рассмотрении HTTP. По крайней мере, это поведение по умолчанию с Spring, которое можно отключить с помощью useTrailingSlashMatch (см. Javadoc).

Таким образом, использование правил перезаписи/переадресации на интерфейсном сервере может быть решением; но опять же, я не знаю ваших ограничений (может быть, вы могли бы разобраться в этом, и мы могли бы найти другие решения?).

Ответ 2

Я думаю, что вам лучше всего сделать это, прежде чем войти в веб-сервлет Spring, используя UrlRewriteFilter. Это гарантирует, что ваши правила перенаправления не повлияют на ваши контроллеры.

Обратите внимание, что вы пишете правила в своем проекте .war, а не в apache с mod_rewrite.

Перейдите сюда для проекта библиотеки на googlecode.

в urlrewrite.xml напишите:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.1//EN" "http://www.tuckey.org/res/dtds/urlrewrite3.1.dtd">
<urlrewrite>
    <rule match-type="regex">  
      <note>Remove trailing slash</note>
      <from>^(.*)/$</from>
      <to type="redirect">$1</to>
    </rule>  
</urlrewrite>

В web.xml вашего приложения добавьте:

<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
       <init-param>
            <param-name>confPath</param-name>
            <param-value>/WEB-INF/urlrewrite.xml</param-value>
        </init-param>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

Опасайтесь, порядок объявлений фильтров в web.xml важен, поэтому попробуйте объявить это перед чем-либо из spring.

Конечно, это лишь часть того, что может сделать UrlRewriteFilter.

С уважением.

Ответ 3

Это обычно работает для меня с URLRewriteFilter в Spring.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN" 
 "http://www.tuckey.org/res/dtds/urlrewrite3.2.dtd">
<urlrewrite>
    <rule>
         <note>Remove trailing slash for SEO purposes</note>
         <from>/**/</from>
         <to type="permanent-redirect">%{context-path}/$1</to>
    </rule>
</urlrewrite>

Ответ 4

Не уверен, что это было spring 3.0, но spring 3.1 RequestMappingHandlerMapping позволяет установить свойство useTrailingSlashMatch. По умолчанию это верно.

Я думаю, что переключение на false приведет к решению вашей проблемы, однако это повлияет на ВСЕ-сопоставления, обрабатываемые RequestMappingHandlerMapping в вашем приложении... поэтому у вас может быть справедливое количество регрессий.

Ответ 5

Я согласен с @Brian Clozel: я не думаю, что это хорошая идея делать то, что вы хотите. Итак, зачем вам это нужно?

В любом случае, я думаю, что самым простым решением является создание пользовательского javax.servlet.Filter. Таким образом, никакая зависимость Spring. Если URL-адрес запроса заканчивается косой чертой, вам просто нужно перенаправить на тот же URL без него. Но предостережение:

  • Все параметры (GET и POST) должны быть добавлены как параметры GET. Вы уверены, что ваше приложение является агностическим?

  • У вас могут быть проблемы с кодировкой. В фильтре вы можете кодировать POST-параметры требуемой кодировке. Но кодировка по умолчанию для параметров GET не настроена в вашем приложении. Конфигурируется в server.xml(если Tomcat), а значение по умолчанию - ISO-8859-1.

Удачи!

Ответ 6

Основываясь на SEO, я думаю, что важно сделать различие.

Если URL-адрес, который заканчивается в концевой косой черты, существует, индексируется в поисковых системах и есть ссылки в Интернете, требуется постоянное перенаправление (301), как говорит Уддхав Камбли. Стандартное перенаправление (302) будет лучше, чем дублированный URL-адрес, но недостаточно.

Однако, если URL-адрес никогда не существовал, он не индексируется в Интернете и внешних ссылок нет, URL-адрес не существует. Поэтому 404, страница не найдена, лучше подходит.

WEB-INF/urlrewrite.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.1//EN"  "http://www.tuckey.org/res/dtds/urlrewrite3.1.dtd">
<urlrewrite>
    <rule match-type="regex">
        <note>Remove trailing slash</note>
        <from>^(.+)/$</from>
        <set type="status">404</set>
        <to>null</to>
    </rule>
</urlrewrite>

И чтобы завершить настройку...

добавить в WEB-INF/web.xml

<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    <init-param>
        <param-name>confPath</param-name>
        <param-value>/WEB-INF/urlrewrite.xml</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

Maven

<dependency>
    <groupId>org.tuckey</groupId>
    <artifactId>urlrewritefilter</artifactId>
    <version>4.0.3</version>
</dependency>