Adapt HTML5 history mode of console in non-proxy mode (#4018)

#### What type of PR is this?

/kind bug
/area core

#### What this PR does / why we need it:

This PR adapts HTML5 history mode of console in non-proxy mode. In PR <https://github.com/halo-dev/halo/pull/4005>, history mode of console has changed from hash mode into HTML5 mode, so that we cannot access console project when refreshing pages.

#### Special notes for your reviewer:

1. Build console project by executing command `make -C console build`
1. Change value of property `halo.console.proxy.enabled` into `false`.
2. Start Halo and check console pages.

#### Does this PR introduce a user-facing change?

```release-note
None
```
pull/4020/head
John Niang 2023-05-31 22:09:03 +08:00 committed by GitHub
parent b37ec04c87
commit ede8ea4827
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 27 deletions

View File

@ -1,12 +1,13 @@
package run.halo.app.config;
import static org.springframework.util.ResourceUtils.FILE_URL_PREFIX;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RequestPredicates.method;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static run.halo.app.infra.utils.FileUtils.checkDirectoryTraversal;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.util.List;
import java.util.Objects;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -15,6 +16,8 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.codec.CodecConfigurer;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ServerCodecConfigurer;
@ -96,13 +99,10 @@ public class WebFluxConfig implements WebFluxConfigurer {
@Bean
RouterFunction<ServerResponse> consoleIndexRedirection() {
return route(GET("/console")
.or(GET("/console/index"))
.or(GET("/console/index.html")),
this::redirectConsole)
.and(route(GET("/console/"),
this::serveConsoleIndex
));
var consolePredicate = method(HttpMethod.GET)
.and(path("/console/**").and(path("/console/assets/**").negate()))
.and(accept(MediaType.TEXT_HTML));
return route(consolePredicate, this::serveConsoleIndex);
}
private Mono<ServerResponse> serveConsoleIndex(ServerRequest request) {
@ -117,10 +117,6 @@ public class WebFluxConfig implements WebFluxConfigurer {
}
}
private Mono<ServerResponse> redirectConsole(ServerRequest request) {
return ServerResponse.permanentRedirect(URI.create("/console/")).build();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
var attachmentsRoot = haloProp.getWorkDir().resolve("attachments");
@ -135,9 +131,9 @@ public class WebFluxConfig implements WebFluxConfigurer {
.setUseLastModified(useLastModified)
.setCacheControl(cacheControl);
// For console project
registry.addResourceHandler("/console/**")
.addResourceLocations(haloProp.getConsole().getLocation())
// For console assets
registry.addResourceHandler("/console/assets/**")
.addResourceLocations(haloProp.getConsole().getLocation() + "assets/")
.setCacheControl(cacheControl)
.setUseLastModified(useLastModified)
.resourceChain(true)

View File

@ -19,22 +19,33 @@ class WebFluxConfigTest {
class ConsoleRequest {
@Test
void shouldRedirect() {
List.of("/console", "/console/index", "/console/index.html")
.forEach(index -> {
webClient.get().uri(index)
.exchange()
.expectStatus().isPermanentRedirect()
.expectHeader().location("/console/");
});
void shouldRequestConsoleIndex() {
List.of(
"/console",
"/console/index",
"/console/index.html",
"/console/dashboard",
"/console/fake"
)
.forEach(uri -> webClient.get().uri(uri)
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("console index\n"));
}
@Test
void shouldRequestConsoleIndex() {
webClient.get().uri("/console/")
void shouldRequestConsoleAssetsCorrectly() {
webClient.get().uri("/console/assets/fake.txt")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("console index\n");
.expectBody(String.class).isEqualTo("fake.\n");
}
@Test
void shouldResponseNotFoundWhenAssetsNotExist() {
webClient.get().uri("/console/assets/not-found.txt")
.exchange()
.expectStatus().isNotFound();
}
}

View File

@ -0,0 +1 @@
fake.