Binds configuration to Configurable factory beans directly using Boot Binder.
Deprecates the use of Tuple. Depracates ArgumentHints in favor of ShortcutConfigurable. Creates Configurable interface to allow factories to create a configuration object that can be bound to properties. Creates StatefulConfigurable interface that extends Configurable and allows singlton beans (like RedisRateLimiter) to store a map of configuration keyed on route id. These beans use events like FilterArgsEvent and PredicateArgsEvent to gather configuration as it is read for each route.
This commit is contained in:
@@ -41,7 +41,7 @@ import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
public class GatewaySampleApplication {
|
||||
|
||||
@Bean
|
||||
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {
|
||||
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
|
||||
//@formatter:off
|
||||
return builder.routes()
|
||||
.route(r -> r.host("**.abc.org").and().path("/image/png")
|
||||
@@ -56,21 +56,17 @@ public class GatewaySampleApplication {
|
||||
)
|
||||
.route(r -> r.order(-1)
|
||||
.host("**.throttle.org").and().path("/get")
|
||||
.filters(f -> f.filter(throttle.apply(1,
|
||||
1,
|
||||
10,
|
||||
TimeUnit.SECONDS)))
|
||||
.filters(f -> f.filter(new ThrottleGatewayFilter()
|
||||
.setCapacity(1)
|
||||
.setRefillTokens(1)
|
||||
.setRefillPeriod(10)
|
||||
.setRefillUnit(TimeUnit.SECONDS)))
|
||||
.uri("http://httpbin.org:80")
|
||||
)
|
||||
.build();
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ThrottleGatewayFilterFactory throttleWebFilterFactory() {
|
||||
return new ThrottleGatewayFilterFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> testFunRouterFunction() {
|
||||
RouterFunction<ServerResponse> route = RouterFunctions.route(
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.gateway.sample;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.isomorphism.util.TokenBucket;
|
||||
import org.isomorphism.util.TokenBuckets;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Sample throttling filter.
|
||||
* See https://github.com/bbeck/token-bucket
|
||||
*/
|
||||
public class ThrottleGatewayFilter implements GatewayFilter {
|
||||
private static final Log log = LogFactory.getLog(ThrottleGatewayFilter.class);
|
||||
|
||||
int capacity;
|
||||
int refillTokens;
|
||||
int refillPeriod;
|
||||
TimeUnit refillUnit;
|
||||
|
||||
public int getCapacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public ThrottleGatewayFilter setCapacity(int capacity) {
|
||||
this.capacity = capacity;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getRefillTokens() {
|
||||
return refillTokens;
|
||||
}
|
||||
|
||||
public ThrottleGatewayFilter setRefillTokens(int refillTokens) {
|
||||
this.refillTokens = refillTokens;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getRefillPeriod() {
|
||||
return refillPeriod;
|
||||
}
|
||||
|
||||
public ThrottleGatewayFilter setRefillPeriod(int refillPeriod) {
|
||||
this.refillPeriod = refillPeriod;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TimeUnit getRefillUnit() {
|
||||
return refillUnit;
|
||||
}
|
||||
|
||||
public ThrottleGatewayFilter setRefillUnit(TimeUnit refillUnit) {
|
||||
this.refillUnit = refillUnit;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
|
||||
TokenBucket tokenBucket = TokenBuckets.builder()
|
||||
.withCapacity(capacity)
|
||||
.withFixedIntervalRefillStrategy(refillTokens, refillPeriod, refillUnit)
|
||||
.build();
|
||||
|
||||
//TODO: get a token bucket for a key
|
||||
log.debug("TokenBucket capacity: " + tokenBucket.getCapacity());
|
||||
boolean consumed = tokenBucket.tryConsume();
|
||||
if (consumed) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
|
||||
return exchange.getResponse().setComplete();
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.gateway.sample;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.isomorphism.util.TokenBucket;
|
||||
import org.isomorphism.util.TokenBuckets;
|
||||
import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.tuple.Tuple;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Sample throttling filter.
|
||||
* See https://github.com/bbeck/token-bucket
|
||||
*/
|
||||
public class ThrottleGatewayFilterFactory implements GatewayFilterFactory {
|
||||
private Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@Override
|
||||
public GatewayFilter apply(Tuple args) {
|
||||
int capacity = args.getInt("capacity");
|
||||
int refillTokens = args.getInt("refillTokens");
|
||||
int refillPeriod = args.getInt("refillPeriod");
|
||||
TimeUnit refillUnit = TimeUnit.valueOf(args.getString("refillUnit"));
|
||||
return apply(capacity, refillTokens, refillPeriod, refillUnit);
|
||||
}
|
||||
|
||||
public GatewayFilter apply(int capacity, int refillTokens, int refillPeriod, TimeUnit refillUnit) {
|
||||
|
||||
final TokenBucket tokenBucket = TokenBuckets.builder()
|
||||
.withCapacity(capacity)
|
||||
.withFixedIntervalRefillStrategy(refillTokens, refillPeriod, refillUnit)
|
||||
.build();
|
||||
|
||||
return (exchange, chain) -> {
|
||||
//TODO: get a token bucket for a key
|
||||
log.debug("TokenBucket capacity: " + tokenBucket.getCapacity());
|
||||
boolean consumed = tokenBucket.tryConsume();
|
||||
if (consumed) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
|
||||
return exchange.getResponse().setComplete();
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user