本文主要研究下spring cloud gateway的SetStatusGatewayFilterhtml
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.javajava
@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(); } //...... }
默認建立SetStatusGatewayFilterFactoryspring
spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/SetStatusGatewayFilterFactory.javaapp
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; } } }
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才設置,實際不生效。ide