refactor: ignore trailing separator for permalink router (#2632)

#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0
#### What this PR does / why we need it:
permalink 路由匹配时自动忽略末尾分隔符
例如
/archives  匹配到 /archives
/archives/ 匹配到 /archives

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
None
```
pull/2634/head v2.0.0-alpha.3
guqing 2022-10-26 15:24:10 +08:00 committed by GitHub
parent fa3e0c44f4
commit 84617c3e96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 3 deletions

View File

@ -125,7 +125,7 @@ public class RadixRouterTree extends RadixTree<HandlerFunction<ServerResponse>>
* TODO Optimize parameter route matching query. * TODO Optimize parameter route matching query.
* Router URL , /?p=post-name URL query URL * Router URL , /?p=post-name URL query URL
*/ */
private String pathToFind(ServerRequest request) { static String pathToFind(ServerRequest request) {
String requestPath = processRequestPath(request.path()); String requestPath = processRequestPath(request.path());
MultiValueMap<String, String> queryParams = request.queryParams(); MultiValueMap<String, String> queryParams = request.queryParams();
// 文章的 permalink 规则需要对 p 参数规则特殊处理 // 文章的 permalink 规则需要对 p 参数规则特殊处理
@ -141,6 +141,7 @@ public class RadixRouterTree extends RadixTree<HandlerFunction<ServerResponse>>
requestPath = requestPath.substring(0, i); requestPath = requestPath.substring(0, i);
} }
} }
requestPath = StringUtils.removeEnd(requestPath, "/");
return StringUtils.prependIfMissing(requestPath, "/"); return StringUtils.prependIfMissing(requestPath, "/");
} }
@ -177,7 +178,7 @@ public class RadixRouterTree extends RadixTree<HandlerFunction<ServerResponse>>
} }
} }
private String processRequestPath(String requestPath) { private static String processRequestPath(String requestPath) {
String path = StringUtils.prependIfMissing(requestPath, "/"); String path = StringUtils.prependIfMissing(requestPath, "/");
return UriUtils.decode(path, StandardCharsets.UTF_8); return UriUtils.decode(path, StandardCharsets.UTF_8);
} }

View File

@ -5,6 +5,7 @@ import static run.halo.app.theme.router.PageUrlUtils.totalPage;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.HandlerFunction; import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerRequest;
@ -64,7 +65,7 @@ public class ArchivesRouteStrategy implements ListPageRouteHandlerStrategy {
@Override @Override
public List<String> getRouterPaths(String prefix) { public List<String> getRouterPaths(String prefix) {
return List.of( return List.of(
prefix, StringUtils.prependIfMissing(prefix, "/"),
PathUtils.combinePath(prefix, "/page/{page:\\d+}"), PathUtils.combinePath(prefix, "/page/{page:\\d+}"),
PathUtils.combinePath(prefix, "/{year:\\d{4}}"), PathUtils.combinePath(prefix, "/{year:\\d{4}}"),
PathUtils.combinePath(prefix, "/{year:\\d{4}}/page/{page:\\d+}"), PathUtils.combinePath(prefix, "/{year:\\d{4}}/page/{page:\\d+}"),

View File

@ -0,0 +1,44 @@
package run.halo.app.theme.router;
import static org.assertj.core.api.Assertions.assertThat;
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpMethod;
import org.springframework.mock.web.reactive.function.server.MockServerRequest;
/**
* Tests for {@link RadixRouterTree}.
*
* @author guqing
* @since 2.0.0
*/
class RadixRouterTreeTest {
@Test
void pathToFind() throws URISyntaxException {
MockServerRequest request =
MockServerRequest.builder().uri(new URI("/archives"))
.method(HttpMethod.GET).build();
String path = RadixRouterTree.pathToFind(request);
assertThat(path).isEqualTo("/archives");
request = MockServerRequest.builder().uri(new URI("/archives/"))
.method(HttpMethod.GET).build();
assertThat(RadixRouterTree.pathToFind(request)).isEqualTo("/archives");
request = MockServerRequest.builder().uri(new URI("/archives/page/1"))
.method(HttpMethod.GET).build();
assertThat(RadixRouterTree.pathToFind(request)).isEqualTo("/archives");
request = MockServerRequest.builder().uri(new URI("/"))
.method(HttpMethod.GET).build();
assertThat(RadixRouterTree.pathToFind(request)).isEqualTo("/");
request = MockServerRequest.builder().uri(new URI("/"))
.queryParam("p", "fake-post")
.method(HttpMethod.GET).build();
assertThat(RadixRouterTree.pathToFind(request)).isEqualTo("/?p=fake-post");
}
}