Support user-center route (#4797)

#### What type of PR is this?

/kind feature
/area core
/area console

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

This PR add a route to support user-center.

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

```release-note
None
```
pull/4805/head^2
John Niang 2023-10-31 22:18:02 -05:00 committed by GitHub
parent dcf099691f
commit b9c0a1f1d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 79 additions and 28 deletions

1
.gitignore vendored
View File

@ -74,4 +74,5 @@ application-local.properties
!application/src/test/resources/themes/*.zip
!application/src/main/resources/themes/*.zip
application/src/main/resources/console/
application/src/main/resources/uc/
application/src/main/resources/presets/

View File

@ -29,14 +29,13 @@ 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.console.ConsoleProxyFilter;
import run.halo.app.console.ProxyFilter;
import run.halo.app.console.WebSocketRequestPredicate;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder;
@ -104,11 +103,21 @@ public class WebFluxConfig implements WebFluxConfigurer {
.and(path("/console/**").and(path("/console/assets/**").negate()))
.and(accept(MediaType.TEXT_HTML))
.and(new WebSocketRequestPredicate().negate());
return route(consolePredicate, this::serveConsoleIndex);
return route(consolePredicate,
request -> this.serveIndex(haloProp.getConsole().getLocation() + "index.html"));
}
private Mono<ServerResponse> serveConsoleIndex(ServerRequest request) {
var indexLocation = haloProp.getConsole().getLocation() + "index.html";
@Bean
RouterFunction<ServerResponse> ucIndexRedirect() {
var consolePredicate = method(HttpMethod.GET)
.and(path("/uc/**").and(path("/uc/assets/**").negate()))
.and(accept(MediaType.TEXT_HTML))
.and(new WebSocketRequestPredicate().negate());
return route(consolePredicate,
request -> this.serveIndex(haloProp.getUc().getLocation() + "index.html"));
}
private Mono<ServerResponse> serveIndex(String indexLocation) {
var indexResource = applicationContext.getResource(indexLocation);
try {
return ServerResponse.ok()
@ -142,6 +151,15 @@ public class WebFluxConfig implements WebFluxConfigurer {
.addResolver(new EncodedResourceResolver())
.addResolver(new PathResourceResolver());
// For uc assets
registry.addResourceHandler("/uc/assets/**")
.addResourceLocations(haloProp.getUc().getLocation() + "assets/")
.setCacheControl(cacheControl)
.setUseLastModified(useLastModified)
.resourceChain(true)
.addResolver(new EncodedResourceResolver())
.addResolver(new PathResourceResolver());
// Additional resource mappings
var staticResources = haloProp.getAttachment().getResourceMappings();
staticResources.forEach(staticResource -> {
@ -172,7 +190,14 @@ public class WebFluxConfig implements WebFluxConfigurer {
@ConditionalOnProperty(name = "halo.console.proxy.enabled", havingValue = "true")
@Bean
ConsoleProxyFilter consoleProxyFilter() {
return new ConsoleProxyFilter(haloProp);
ProxyFilter consoleProxyFilter() {
return new ProxyFilter("/console/**", haloProp.getConsole().getProxy());
}
@ConditionalOnProperty(name = "halo.uc.proxy.enabled", havingValue = "true")
@Bean
ProxyFilter ucProxyFilter() {
return new ProxyFilter("/uc/**", haloProp.getUc().getProxy());
}
}

View File

@ -13,11 +13,10 @@ import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import run.halo.app.infra.properties.ConsoleProperties.ProxyProperties;
import run.halo.app.infra.properties.HaloProperties;
import run.halo.app.infra.properties.ProxyProperties;
@Slf4j
public class ConsoleProxyFilter implements WebFilter {
public class ProxyFilter implements WebFilter {
private final ProxyProperties proxyProperties;
@ -25,14 +24,15 @@ public class ConsoleProxyFilter implements WebFilter {
private final WebClient webClient;
public ConsoleProxyFilter(HaloProperties haloProperties) {
this.proxyProperties = haloProperties.getConsole().getProxy();
var consoleMatcher = ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, "/console/**");
public ProxyFilter(String pattern, ProxyProperties proxyProperties) {
this.proxyProperties = proxyProperties;
var consoleMatcher = ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, pattern);
consoleMatcher = new AndServerWebExchangeMatcher(consoleMatcher,
new NegatedServerWebExchangeMatcher(new WebSocketServerWebExchangeMatcher()));
this.consoleMatcher = consoleMatcher;
this.webClient = WebClient.create(proxyProperties.getEndpoint().toString());
log.info("Initialized ConsoleProxyFilter to proxy console");
log.debug("Initialized ProxyFilter to proxy {} to endpoint {}", pattern,
proxyProperties.getEndpoint());
}
@Override

View File

@ -1,7 +1,6 @@
package run.halo.app.infra.properties;
import jakarta.validation.Valid;
import java.net.URI;
import lombok.Data;
@Data
@ -12,17 +11,4 @@ public class ConsoleProperties {
@Valid
private ProxyProperties proxy = new ProxyProperties();
@Data
public static class ProxyProperties {
/**
* Console endpoint in development environment to be proxied. e.g.: http://localhost:8090/
*/
private URI endpoint;
/**
* Indicates if the proxy behaviour is enabled. Default is false
*/
private boolean enabled = false;
}
}

View File

@ -54,6 +54,9 @@ public class HaloProperties implements Validator {
@Valid
private final ConsoleProperties console = new ConsoleProperties();
@Valid
private final UcProperties uc = new UcProperties();
@Valid
private final ThemeProperties theme = new ThemeProperties();

View File

@ -0,0 +1,18 @@
package run.halo.app.infra.properties;
import java.net.URI;
import lombok.Data;
@Data
public class ProxyProperties {
/**
* Console endpoint in development environment to be proxied. e.g.: http://localhost:8090/
*/
private URI endpoint;
/**
* Indicates if the proxy behaviour is enabled. Default is false
*/
private boolean enabled = false;
}

View File

@ -0,0 +1,14 @@
package run.halo.app.infra.properties;
import jakarta.validation.Valid;
import lombok.Data;
@Data
public class UcProperties {
private String location = "classpath:/uc/";
@Valid
private ProxyProperties proxy = new ProxyProperties();
}

View File

@ -19,6 +19,10 @@ halo:
proxy:
endpoint: http://localhost:3000/
enabled: true
uc:
proxy:
endpoint: http://localhost:4000/
enabled: true
plugin:
runtime-mode: development # development, deployment
work-dir: ${user.home}/halo2-dev