mirror of https://github.com/halo-dev/halo
Support configuring console location to access console (#2453)
#### What type of PR is this? /kind feature /area core /milestone 2.0 #### What this PR does / why we need it: Support configuring console location to access console. By default, `classpath:/console/` location will be used. If anyone want to debug locally, you can configure the console properties as following: ```yaml halo: console: location: file:/home/xxx/path/to/halo-admin/dist/ # The trailing slash is required or it will be treated with a file instead of a folder. ``` #### Does this PR introduce a user-facing change? ```release-note None ```pull/2460/head
parent
95b7a273f8
commit
d40626b07b
|
@ -1,8 +1,12 @@
|
|||
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.RouterFunctions.route;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.net.URI;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -15,10 +19,15 @@ import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
|||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.web.reactive.config.ResourceHandlerRegistry;
|
||||
import org.springframework.web.reactive.config.WebFluxConfigurer;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import org.springframework.web.reactive.resource.EncodedResourceResolver;
|
||||
import org.springframework.web.reactive.resource.PathResourceResolver;
|
||||
import org.springframework.web.reactive.result.view.ViewResolutionResultHandler;
|
||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.core.extension.endpoint.CustomEndpoint;
|
||||
import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder;
|
||||
import run.halo.app.infra.properties.HaloProperties;
|
||||
|
@ -30,9 +39,13 @@ public class WebFluxConfig implements WebFluxConfigurer {
|
|||
|
||||
private final HaloProperties haloProp;
|
||||
|
||||
public WebFluxConfig(ObjectMapper objectMapper, HaloProperties haloProp) {
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
public WebFluxConfig(ObjectMapper objectMapper, HaloProperties haloProp,
|
||||
ApplicationContext applicationContext) {
|
||||
this.objectMapper = objectMapper;
|
||||
this.haloProp = haloProp;
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -69,10 +82,45 @@ public class WebFluxConfig implements WebFluxConfigurer {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
@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
|
||||
));
|
||||
}
|
||||
|
||||
private Mono<ServerResponse> serveConsoleIndex(ServerRequest request) {
|
||||
var indexLocation = haloProp.getConsole().getLocation() + "index.html";
|
||||
var indexResource = applicationContext.getResource(indexLocation);
|
||||
try {
|
||||
return ServerResponse.ok()
|
||||
.lastModified(Instant.ofEpochMilli(indexResource.lastModified()))
|
||||
.body(BodyInserters.fromResource(indexResource));
|
||||
} catch (Throwable e) {
|
||||
return Mono.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
registry.addResourceHandler("/upload/**")
|
||||
.addResourceLocations(FILE_URL_PREFIX + attachmentsRoot + "/");
|
||||
|
||||
// For console project
|
||||
registry.addResourceHandler("/console/**")
|
||||
.addResourceLocations(haloProp.getConsole().getLocation())
|
||||
.resourceChain(true)
|
||||
.addResolver(new EncodedResourceResolver())
|
||||
.addResolver(new PathResourceResolver());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package run.halo.app.infra.properties;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ConsoleProperties {
|
||||
|
||||
private String location = "classpath:/console/";
|
||||
|
||||
}
|
|
@ -39,4 +39,7 @@ public class HaloProperties {
|
|||
|
||||
@Valid
|
||||
private final SecurityProperties security = new SecurityProperties();
|
||||
|
||||
@Valid
|
||||
private final ConsoleProperties console = new ConsoleProperties();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
server:
|
||||
port: 8090
|
||||
compression:
|
||||
enabled: true
|
||||
spring:
|
||||
output:
|
||||
ansi:
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package run.halo.app.config;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
@SpringBootTest(properties = "halo.console.location=classpath:/console/")
|
||||
@AutoConfigureWebTestClient
|
||||
class WebFluxConfigTest {
|
||||
|
||||
@Autowired
|
||||
WebTestClient webClient;
|
||||
|
||||
@Nested
|
||||
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/");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRequestConsoleIndex() {
|
||||
webClient.get().uri("/console/")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo("console index\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
console index
|
Loading…
Reference in New Issue