simple configurable routes
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
package org.springframework.cloud.gateway;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.gateway.filters.FindRouteFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.client.reactive.WebClient;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public class GatewayConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public WebClient webClient() {
|
||||
return WebClient.builder(new ReactorClientHttpConnector()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FindRouteFilter findRouteFilter(GatewayProperties properties) {
|
||||
return new FindRouteFilter(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GatewayProperties gatewayProperties() {
|
||||
return new GatewayProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GatewayWebHandler gatewayController(GatewayProperties properties, WebClient webClient) {
|
||||
return new GatewayWebHandler(properties, webClient);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GatewayHandlerMapping gatewayHandlerMapping(GatewayProperties properties, GatewayWebHandler gatewayWebHandler) {
|
||||
return new GatewayHandlerMapping(properties, gatewayWebHandler);
|
||||
}
|
||||
|
||||
/*@Bean
|
||||
public GatewayWebReactiveConfigurer gatewayWebReactiveConfiguration() {
|
||||
return new GatewayWebReactiveConfigurer();
|
||||
}
|
||||
|
||||
public static class GatewayWebReactiveConfigurer implements WebReactiveConfigurer {
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
}
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.springframework.cloud.gateway;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.cloud.gateway.GatewayProperties.Route;
|
||||
import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class GatewayHandlerMapping extends AbstractUrlHandlerMapping {
|
||||
|
||||
private GatewayProperties properties;
|
||||
private GatewayWebHandler gatewayWebHandler;
|
||||
|
||||
public GatewayHandlerMapping(GatewayProperties properties, GatewayWebHandler gatewayWebHandler) {
|
||||
this.properties = properties;
|
||||
this.gatewayWebHandler = gatewayWebHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initApplicationContext() throws BeansException {
|
||||
super.initApplicationContext();
|
||||
registerHandlers(this.properties.getRoutes());
|
||||
}
|
||||
|
||||
protected void registerHandlers(Map<String, Route> routes) {
|
||||
for (Route route : routes.values()) {
|
||||
registerHandler(route.getPath(), this.gatewayWebHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object lookupHandler(String urlPath, ServerWebExchange exchange) throws Exception {
|
||||
return super.lookupHandler(urlPath, exchange);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.springframework.cloud.gateway;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.gateway")
|
||||
public class GatewayProperties {
|
||||
|
||||
|
||||
/**
|
||||
* Map of route names to properties.
|
||||
*/
|
||||
private Map<String, Route> routes = new LinkedHashMap<>();
|
||||
|
||||
public Map<String, Route> getRoutes() {
|
||||
return routes;
|
||||
}
|
||||
|
||||
public void setRoutes(Map<String, Route> routes) {
|
||||
this.routes = routes;
|
||||
}
|
||||
|
||||
public static class Route {
|
||||
private String id;
|
||||
private String path;
|
||||
private String url;
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,32 @@
|
||||
package org.springframework.cloud.gateway;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.reactive.ClientRequest;
|
||||
import org.springframework.web.client.reactive.WebClient;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@RestController
|
||||
@SuppressWarnings("unused")
|
||||
public class GatewayController {
|
||||
public class GatewayWebHandler implements WebHandler {
|
||||
|
||||
private final GatewayProperties properties;
|
||||
private final WebClient webClient;
|
||||
|
||||
public GatewayController(WebClient webClient) {
|
||||
public GatewayWebHandler(GatewayProperties properties, WebClient webClient) {
|
||||
this.properties = properties;
|
||||
this.webClient = webClient;
|
||||
}
|
||||
|
||||
//TODO: plugin to request mappings
|
||||
@GetMapping(path = "/")
|
||||
public Flux<Void> home(ServerWebExchange exchange) {
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange) {
|
||||
Optional<String> requestUrl = exchange.getAttribute("requestUrl");
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
ClientRequest<Void> clientRequest = ClientRequest
|
||||
@@ -42,6 +40,6 @@ public class GatewayController {
|
||||
response.setStatusCode(clientResponse.statusCode());
|
||||
Flux<DataBuffer> body = clientResponse.body((inputMessage, context) -> inputMessage.getBody());
|
||||
return response.writeWith(body);
|
||||
});
|
||||
}).next(); // TODO: is this correct?
|
||||
}
|
||||
}
|
||||
@@ -2,38 +2,25 @@ package org.springframework.cloud.gateway;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.client.reactive.WebClient;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@SpringBootApplication
|
||||
//TODO: move to autoconfig
|
||||
@Import(GatewayConfiguration.class)
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
public class SpringCloudGatewayApplication {
|
||||
|
||||
private static final Log log = LogFactory.getLog(SpringCloudGatewayApplication.class);
|
||||
|
||||
@Bean
|
||||
public WebClient webClient() {
|
||||
return WebClient.builder(new ReactorClientHttpConnector()).build();
|
||||
}
|
||||
|
||||
// TODO: request only, how to filter response?
|
||||
@Bean
|
||||
@Order(500)
|
||||
public WebFilter findRouteFilter() {
|
||||
return (exchange, chain) -> {
|
||||
log.info("findRoutFilter start");
|
||||
exchange.getAttributes().put("requestUrl", "http://httpbin.org/get");
|
||||
return chain.filter(exchange);
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: only apply filters to zuul?
|
||||
@Bean
|
||||
@Order(501)
|
||||
public WebFilter modifyResponseFilter() {
|
||||
@@ -60,6 +47,9 @@ public class SpringCloudGatewayApplication {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringCloudGatewayApplication.class, args);
|
||||
new SpringApplicationBuilder()
|
||||
.sources(SpringCloudGatewayApplication.class)
|
||||
//TODO: howto do programatically
|
||||
.run(args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.springframework.cloud.gateway.filters;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.gateway.GatewayProperties;
|
||||
import org.springframework.cloud.gateway.GatewayProperties.Route;
|
||||
import org.springframework.cloud.gateway.SpringCloudGatewayApplication;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class FindRouteFilter implements WebFilter {
|
||||
|
||||
private static final Log log = LogFactory.getLog(SpringCloudGatewayApplication.class);
|
||||
|
||||
private final GatewayProperties properties;
|
||||
private final AntPathMatcher matcher;
|
||||
|
||||
public FindRouteFilter(GatewayProperties properties) {
|
||||
this.properties = properties;
|
||||
this.matcher = new AntPathMatcher();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
log.info("FindRouteFilter start");
|
||||
//TODO:
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
URI uri = request.getURI();
|
||||
String path = uri.getPath();
|
||||
for (Route route : this.properties.getRoutes().values()) {
|
||||
if (this.matcher.match(route.getPath(), path)) {
|
||||
String url = route.getUrl() + path;
|
||||
exchange.getAttributes().put("requestUrl", url);
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
}
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
}
|
||||
10
src/main/resources/application.yml
Normal file
10
src/main/resources/application.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
spring:
|
||||
resources:
|
||||
# TODO: how to add this programmatically
|
||||
add-mappings: false
|
||||
cloud:
|
||||
gateway:
|
||||
routes:
|
||||
test1:
|
||||
path: /**
|
||||
url: http://httpbin.org
|
||||
Reference in New Issue
Block a user