fixes
This commit is contained in:
parent
2bca6e0c83
commit
f34d44faaa
|
@ -37,7 +37,7 @@
|
|||
<dependency>
|
||||
<groupId>com.marcosbarbero.cloud</groupId>
|
||||
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
|
||||
<version>LATEST</version>
|
||||
<version>2.2.0.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
@ -1,12 +1,53 @@
|
|||
package com.baeldung.spring.cloud.zuulratelimitdemo;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.netflix.zuul.filters.Route;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.RateLimitKeyGenerator;
|
||||
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.RateLimitUtils;
|
||||
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.properties.RateLimitProperties;
|
||||
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository.RateLimiterErrorHandler;
|
||||
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository.DefaultRateLimiterErrorHandler;
|
||||
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.DefaultRateLimitKeyGenerator;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ZuulRatelimitDemoApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ZuulRatelimitDemoApplication.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ZuulRatelimitDemoApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RateLimitKeyGenerator ratelimitKeyGenerator(RateLimitProperties properties, RateLimitUtils rateLimitUtils) {
|
||||
return new DefaultRateLimitKeyGenerator(properties, rateLimitUtils) {
|
||||
@Override
|
||||
public String key(HttpServletRequest request, Route route, RateLimitProperties.Policy policy) {
|
||||
return super.key(request, route, policy) + ":" + request.getMethod();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RateLimiterErrorHandler rateLimitErrorHandler() {
|
||||
return new DefaultRateLimiterErrorHandler() {
|
||||
@Override
|
||||
public void handleSaveError(String key, Exception e) {
|
||||
// custom code
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFetchError(String key, Exception e) {
|
||||
// custom code
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleError(String msg, Exception e) {
|
||||
// custom code
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,16 +11,16 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||
@RequestMapping("/greeting")
|
||||
public class GreetingController {
|
||||
|
||||
public static final String SIMPLE_RESPONSE = "Hi!";
|
||||
public static final String ADVANCED_RESPONSE = "Hello, how you doing?";
|
||||
public static final String SIMPLE_RESPONSE = "Hi!";
|
||||
public static final String ADVANCED_RESPONSE = "Hello, how you doing?";
|
||||
|
||||
@GetMapping("/simple")
|
||||
public ResponseEntity<String> serviceA() {
|
||||
return ResponseEntity.ok(SIMPLE_RESPONSE);
|
||||
}
|
||||
@GetMapping("/simple")
|
||||
public ResponseEntity<String> getSimple() {
|
||||
return ResponseEntity.ok(SIMPLE_RESPONSE);
|
||||
}
|
||||
|
||||
@GetMapping("/advanced")
|
||||
public ResponseEntity<String> serviceB() {
|
||||
return ResponseEntity.ok(ADVANCED_RESPONSE);
|
||||
}
|
||||
@GetMapping("/advanced")
|
||||
public ResponseEntity<String> getAdvanced() {
|
||||
return ResponseEntity.ok(ADVANCED_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@ zuul:
|
|||
repository: JPA
|
||||
policy-list:
|
||||
serviceSimple:
|
||||
- limit: 5
|
||||
refresh-interval: 60
|
||||
type:
|
||||
- origin
|
||||
- limit: 5
|
||||
refresh-interval: 60
|
||||
type:
|
||||
- origin
|
||||
serviceAdvanced:
|
||||
- limit: 1
|
||||
refresh-interval: 2
|
||||
type:
|
||||
- origin
|
||||
strip-prefix: true
|
||||
- limit: 1
|
||||
refresh-interval: 2
|
||||
type:
|
||||
- origin
|
||||
strip-prefix: true
|
|
@ -28,73 +28,86 @@ import org.springframework.test.context.junit4.SpringRunner;
|
|||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class GreetingControllerTest {
|
||||
|
||||
private static final String SIMPLE_GREETING = "/greeting/simple";
|
||||
private static final String ADVANCED_GREETING = "/greeting/advanced";
|
||||
private static final String SIMPLE_GREETING = "/greeting/simple";
|
||||
private static final String ADVANCED_GREETING = "/greeting/advanced";
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
|
||||
@Test
|
||||
public void whenRequestNotExceedingCapacity_thenReturnOkResponse() {
|
||||
ResponseEntity<String> response = this.restTemplate.getForEntity(SIMPLE_GREETING, String.class);
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
String key = "rate-limit-application_serviceSimple_127.0.0.1";
|
||||
assertHeaders(headers, key, false, false);
|
||||
assertEquals(OK, response.getStatusCode());
|
||||
}
|
||||
@Test
|
||||
public void whenRequestNotExceedingCapacity_thenReturnOkResponse() {
|
||||
ResponseEntity<String> response = this.restTemplate.getForEntity(SIMPLE_GREETING, String.class);
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
String key = "rate-limit-application_serviceSimple_127.0.0.1";
|
||||
|
||||
@Test
|
||||
public void whenRequestExceedingCapacity_thenReturnTooManyRequestsResponse() throws InterruptedException {
|
||||
ResponseEntity<String> response = this.restTemplate
|
||||
.getForEntity(ADVANCED_GREETING, String.class);
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
String key = "rate-limit-application_serviceAdvanced_127.0.0.1";
|
||||
assertHeaders(headers, key, false, false);
|
||||
assertEquals(OK, response.getStatusCode());
|
||||
String limit = headers.getFirst(HEADER_LIMIT + key);
|
||||
String remaining = headers.getFirst(HEADER_REMAINING + key);
|
||||
String reset = headers.getFirst(HEADER_RESET + key);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
response = this.restTemplate.getForEntity(ADVANCED_GREETING, String.class);
|
||||
assertEquals(limit, "5");
|
||||
assertEquals(remaining, "4");
|
||||
assertEquals(reset, "60000");
|
||||
|
||||
assertEquals(OK, response.getStatusCode());
|
||||
}
|
||||
|
||||
assertEquals(TOO_MANY_REQUESTS, response.getStatusCode());
|
||||
assertNotEquals(GreetingController.ADVANCED_RESPONSE, response.getBody());
|
||||
@Test
|
||||
public void whenRequestExceedingCapacity_thenReturnTooManyRequestsResponse() throws InterruptedException {
|
||||
ResponseEntity<String> response = this.restTemplate.getForEntity(ADVANCED_GREETING, String.class);
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
String key = "rate-limit-application_serviceAdvanced_127.0.0.1";
|
||||
assertHeaders(headers, key, false, false);
|
||||
assertEquals(OK, response.getStatusCode());
|
||||
|
||||
TimeUnit.SECONDS.sleep(2);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
response = this.restTemplate.getForEntity(ADVANCED_GREETING, String.class);
|
||||
}
|
||||
|
||||
response = this.restTemplate.getForEntity(ADVANCED_GREETING, String.class);
|
||||
headers = response.getHeaders();
|
||||
assertHeaders(headers, key, false, false);
|
||||
assertEquals(OK, response.getStatusCode());
|
||||
}
|
||||
headers = response.getHeaders();
|
||||
String limit = headers.getFirst(HEADER_LIMIT + key);
|
||||
String remaining = headers.getFirst(HEADER_REMAINING + key);
|
||||
String reset = headers.getFirst(HEADER_RESET + key);
|
||||
|
||||
private void assertHeaders(HttpHeaders headers, String key, boolean nullable,
|
||||
boolean quotaHeaders) {
|
||||
String quota = headers.getFirst(HEADER_QUOTA + key);
|
||||
String remainingQuota = headers.getFirst(HEADER_REMAINING_QUOTA + key);
|
||||
String limit = headers.getFirst(HEADER_LIMIT + key);
|
||||
String remaining = headers.getFirst(HEADER_REMAINING + key);
|
||||
String reset = headers.getFirst(HEADER_RESET + key);
|
||||
assertEquals(limit, "1");
|
||||
assertEquals(remaining, "0");
|
||||
assertNotEquals(reset, "2000");
|
||||
|
||||
if (nullable) {
|
||||
if (quotaHeaders) {
|
||||
assertNull(quota);
|
||||
assertNull(remainingQuota);
|
||||
} else {
|
||||
assertNull(limit);
|
||||
assertNull(remaining);
|
||||
}
|
||||
assertNull(reset);
|
||||
} else {
|
||||
if (quotaHeaders) {
|
||||
assertNotNull(quota);
|
||||
assertNotNull(remainingQuota);
|
||||
} else {
|
||||
assertNotNull(limit);
|
||||
assertNotNull(remaining);
|
||||
}
|
||||
assertNotNull(reset);
|
||||
assertEquals(TOO_MANY_REQUESTS, response.getStatusCode());
|
||||
assertNotEquals(GreetingController.ADVANCED_RESPONSE, response.getBody());
|
||||
|
||||
TimeUnit.SECONDS.sleep(2);
|
||||
|
||||
response = this.restTemplate.getForEntity(ADVANCED_GREETING, String.class);
|
||||
headers = response.getHeaders();
|
||||
assertHeaders(headers, key, false, false);
|
||||
assertEquals(OK, response.getStatusCode());
|
||||
}
|
||||
}
|
||||
|
||||
private void assertHeaders(HttpHeaders headers, String key, boolean nullable, boolean quotaHeaders) {
|
||||
String quota = headers.getFirst(HEADER_QUOTA + key);
|
||||
String remainingQuota = headers.getFirst(HEADER_REMAINING_QUOTA + key);
|
||||
String limit = headers.getFirst(HEADER_LIMIT + key);
|
||||
String remaining = headers.getFirst(HEADER_REMAINING + key);
|
||||
String reset = headers.getFirst(HEADER_RESET + key);
|
||||
|
||||
if (nullable) {
|
||||
if (quotaHeaders) {
|
||||
assertNull(quota);
|
||||
assertNull(remainingQuota);
|
||||
} else {
|
||||
assertNull(limit);
|
||||
assertNull(remaining);
|
||||
}
|
||||
assertNull(reset);
|
||||
} else {
|
||||
if (quotaHeaders) {
|
||||
assertNotNull(quota);
|
||||
assertNotNull(remainingQuota);
|
||||
} else {
|
||||
assertNotNull(limit);
|
||||
assertNotNull(remaining);
|
||||
}
|
||||
assertNotNull(reset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue