序
本文主要研究下spring cloud gateway的SetStatusGatewayFilter
GatewayAutoConfiguration
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java
@Configuration
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore(HttpHandlerAutoConfiguration.class)
@AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class})
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
//......
@Bean
public SetStatusGatewayFilterFactory setStatusGatewayFilterFactory() {
return new SetStatusGatewayFilterFactory();
}
//......
}
默认创建SetStatusGatewayFilterFactory
SetStatusGatewayFilterFactory
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/SetStatusGatewayFilterFactory.java
public class SetStatusGatewayFilterFactory extends AbstractGatewayFilterFactory<SetStatusGatewayFilterFactory.Config> {
public static final String STATUS_KEY = "status";
public SetStatusGatewayFilterFactory() {
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(STATUS_KEY);
}
@Override
public GatewayFilter apply(Config config) {
final HttpStatus status = ServerWebExchangeUtils.parse(config.status);
final Integer intStatus;
if (status == null) {
intStatus = Integer.parseInt(config.status);
} else {
intStatus = null;
}
return (exchange, chain) -> {
// option 1 (runs in filter order)
/*exchange.getResponse().beforeCommit(() -> {
exchange.getResponse().setStatusCode(finalStatus);
return Mono.empty();
});
return chain.filter(exchange);*/
// option 2 (runs in reverse filter order)
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// check not really needed, since it is guarded in setStatusCode,
// but it's a good example
if (!exchange.getResponse().isCommitted()) {
if (status != null) { // standard status
setResponseStatus(exchange, status);
} else if (intStatus != null && exchange.getResponse() instanceof AbstractServerHttpResponse) { //non-standard
((AbstractServerHttpResponse)exchange.getResponse()).setStatusCodeValue(intStatus);
}
}
}));
};
}
public static class Config {
//TODO: relaxed HttpStatus converter
private String status;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
}
- 可以看到,就是简单地根据status来设置response的status
- 注意这里有两个option,源码注释掉了option1,改为使用option2
实例
spring:
cloud:
gateway:
routes:
- id: setstatusstring_route
uri: http://example.org
predicates:
- Path=/foo/**
filters:
- SetStatus=BAD_REQUEST
- id: setstatusint_route
uri: http://example.org
predicates:
- Path=/name/**
filters:
- SetStatus=401
小结
SetStatusGatewayFilter就是简单地设置response,使用option1方式的话,是在response commit之前设置的,而且一旦设置就直接return,不再继续走filter了,因而SetStatus可以生效;使用option2的话,是逆filter顺序执行的,会先判断是否commit,未commit才设置,实际不生效。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。