Skip to content

Commit

Permalink
Support proxying console in server side (#2535)
Browse files Browse the repository at this point in the history
#### What type of PR is this?

/kind feature
/area core
/milestone 2.0

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

Support proxying console in server side. We just need to configure the properties as following:

```yaml
halo:
  console:
    proxy:
      endpoint: http://localhost:3000/
      enabled: true
```

Before starting Halo server, please start the console first at port 3000 by checkouting halo-dev/console#638.

Now we can have a try to access console via <http://localhost:8090/console/>.

Please note that this feature should be only for development environment instead of production environment.

#### Todos

- [ ] Proxy WebSocket for hmr of Vite

#### Which issue(s) this PR fixes:

Fixes #2530

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

```release-note
None
```
  • Loading branch information
JohnNiang authored Oct 11, 2022
1 parent af8860f commit dbaa087
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/main/java/run/halo/app/config/WebFluxConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.net.URI;
import java.time.Instant;
import java.util.List;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -28,6 +29,7 @@
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.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder;
import run.halo.app.infra.properties.HaloProperties;
Expand Down Expand Up @@ -123,4 +125,10 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) {
.addResolver(new PathResourceResolver());
}


@ConditionalOnProperty(name = "halo.console.proxy.enabled", havingValue = "true")
@Bean
ConsoleProxyFilter consoleProxyFilter() {
return new ConsoleProxyFilter(haloProp);
}
}
72 changes: 72 additions & 0 deletions src/main/java/run/halo/app/console/ConsoleProxyFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package run.halo.app.console;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.web.server.util.matcher.AndServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.MediaTypeServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
import org.springframework.web.reactive.function.BodyExtractors;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
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;

@Slf4j
public class ConsoleProxyFilter implements WebFilter {

private final ProxyProperties proxyProperties;

private final ServerWebExchangeMatcher consoleMatcher;

private final WebClient webClient;

public ConsoleProxyFilter(HaloProperties haloProperties) {
this.proxyProperties = haloProperties.getConsole().getProxy();
var consoleMatcher = ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, "/console/**");
consoleMatcher = new AndServerWebExchangeMatcher(consoleMatcher,
new MediaTypeServerWebExchangeMatcher(MediaType.TEXT_HTML));
this.consoleMatcher = consoleMatcher;
this.webClient = WebClient.create(proxyProperties.getEndpoint().toString());
log.info("Initialized ConsoleProxyFilter to proxy console");
}

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return consoleMatcher.matches(exchange)
.filter(ServerWebExchangeMatcher.MatchResult::isMatch)
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
.map(matchResult -> {
var request = exchange.getRequest();
return UriComponentsBuilder.fromUriString(
request.getPath().pathWithinApplication().value())
.queryParams(request.getQueryParams())
.build()
.toUriString();
})
.doOnNext(uri -> {
if (log.isDebugEnabled()) {
log.debug("Proxy {} to {}", uri, proxyProperties.getEndpoint());
}
})
.flatMap(uri -> webClient.get()
.uri(uri)
.headers(httpHeaders -> httpHeaders.addAll(exchange.getRequest().getHeaders()))
.exchangeToMono(clientResponse -> {
var response = exchange.getResponse();
// set headers
response.getHeaders().putAll(clientResponse.headers().asHttpHeaders());
// set cookies
response.getCookies().putAll(clientResponse.cookies());
// set status code
response.setStatusCode(clientResponse.statusCode());
var body = clientResponse.body(BodyExtractors.toDataBuffers());
return exchange.getResponse().writeAndFlushWith(Mono.just(body));
}));
}
}
18 changes: 18 additions & 0 deletions src/main/java/run/halo/app/infra/properties/ConsoleProperties.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
package run.halo.app.infra.properties;

import jakarta.validation.Valid;
import java.net.URI;
import lombok.Data;

@Data
public class ConsoleProperties {

private String location = "classpath:/console/";

@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;
}
}

0 comments on commit dbaa087

Please sign in to comment.