Spring Cloud Gateway:在自定义谓词中设置响应状态代码
Spring Cloud Gateway: Set response status code in custom predicate
在下面的代码片段中,我尝试将我的请求与自定义谓词进行匹配。当谓词被评估为 false 时,我想发回一个自定义状态代码(下面代码段中的 403 Forbidden),而不是在谓词失败时发送的默认 404。这是我试过的。
RouteLocator
@Bean
public RouteLocator customRoutesLocator(RouteLocatorBuilder builder
AuthenticationRoutePredicateFactory arpf) {
return builder.routes()
.route("id1", r ->r.path("/app1/**")
.uri("lb://id1")
.predicate(arpf.apply(new Config()))).build();
}
AuthenticationRoutePredicateFactory
public class AuthenticationRoutePredicateFactory
extends AbstractRoutePredicateFactory<AuthenticationRoutePredicateFactory.Config> {
public AuthenticationRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return (ServerWebExchange t) -> {
try {
Boolean isRequestAuthenticated = checkAuthenticated();
return isRequestAuthenticated;
}
} catch (HttpClientErrorException e) {
//This status code does not carried forward and 404 is displayed instead.
t.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return false;
}
};
}
@Validated
public static class Config {
public Config() {
}
}
private Boolean checkAuthenticated() {
// Some sample logic that makes a REST call and returns TRUE/FALSE/HttpClientErrorException
//Not shown here for simplicity.
return true;
}
}
当谓词returns为真时,请求被转发到URI。但是,在显示错误评估 404 时,我需要显示 403(在 HttpClientErrorException 上)。这是期望使用自定义状态代码进行响应的正确方法吗?此外,我还阅读了有关为给定路由实现自定义 Web 过滤器的内容,这些路由可能会在转发请求之前修改响应对象。在这种情况下,有没有办法在谓词失败时调用过滤器?
作为spring云网关的新手,我选择了错误的方向来解决这个问题。
客户端向 Spring 云网关发出请求。如果 Gateway Handler Mapping 确定请求与路由匹配,则将其发送到 Gateway Web Handler。谓词帮助网关处理程序映射确定该请求是否与路由匹配,并且只能 return true 或 false 值。
一旦请求与路由匹配,处理程序就会通过特定于请求的过滤器链运行请求。这是在转发请求之前可以应用“pre”或“post”请求的地方。
因此为了在有条件地转发请求之前发送自定义响应状态代码,必须编写一个自定义“预”过滤器,这可以通过以下方式实现。 (设置403状态码)
AuthenticationGatewayFilterFactory
@Component
public class AuthenticationGatewayFilterFactory
extends AbstractGatewayFilterFactory<AuthenticationGatewayFilterFactory.Config> {
public AuthenticationGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
try {
if(isRequestAuthenticated) {
return chain.filter(exchange);
}
else {
exchange.getResponse().setStatusCode(403); // Any status code can be set here.
return exchange.getResponse().complete();
}
} catch (HttpClientErrorException e) {
exchange.getResponse().setStatusCode(403); // Any status code can be set here.
return exchange.getResponse().complete();
}
};
}
public static class Config {
}
private Boolean isRequestAuthenticated(String authToken) {
// Some sample logic that makes a REST call and returns TRUE/FALSE/HttpClientErrorException
//Not shown here for simplicity.
return true;
}
RouteLocator
@Bean
public RouteLocator customRoutesLocator(RouteLocatorBuilder builder
AuthenticationGatewayFilterFactory agff) {
return builder.routes()
.route("id1", r ->r.path("/app1/**")
.uri("lb://id1")
.filter(agff.apply(new Config()))).build();
}
在下面的代码片段中,我尝试将我的请求与自定义谓词进行匹配。当谓词被评估为 false 时,我想发回一个自定义状态代码(下面代码段中的 403 Forbidden),而不是在谓词失败时发送的默认 404。这是我试过的。
RouteLocator
@Bean
public RouteLocator customRoutesLocator(RouteLocatorBuilder builder
AuthenticationRoutePredicateFactory arpf) {
return builder.routes()
.route("id1", r ->r.path("/app1/**")
.uri("lb://id1")
.predicate(arpf.apply(new Config()))).build();
}
AuthenticationRoutePredicateFactory
public class AuthenticationRoutePredicateFactory
extends AbstractRoutePredicateFactory<AuthenticationRoutePredicateFactory.Config> {
public AuthenticationRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return (ServerWebExchange t) -> {
try {
Boolean isRequestAuthenticated = checkAuthenticated();
return isRequestAuthenticated;
}
} catch (HttpClientErrorException e) {
//This status code does not carried forward and 404 is displayed instead.
t.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return false;
}
};
}
@Validated
public static class Config {
public Config() {
}
}
private Boolean checkAuthenticated() {
// Some sample logic that makes a REST call and returns TRUE/FALSE/HttpClientErrorException
//Not shown here for simplicity.
return true;
}
}
当谓词returns为真时,请求被转发到URI。但是,在显示错误评估 404 时,我需要显示 403(在 HttpClientErrorException 上)。这是期望使用自定义状态代码进行响应的正确方法吗?此外,我还阅读了有关为给定路由实现自定义 Web 过滤器的内容,这些路由可能会在转发请求之前修改响应对象。在这种情况下,有没有办法在谓词失败时调用过滤器?
作为spring云网关的新手,我选择了错误的方向来解决这个问题。
客户端向 Spring 云网关发出请求。如果 Gateway Handler Mapping 确定请求与路由匹配,则将其发送到 Gateway Web Handler。谓词帮助网关处理程序映射确定该请求是否与路由匹配,并且只能 return true 或 false 值。
一旦请求与路由匹配,处理程序就会通过特定于请求的过滤器链运行请求。这是在转发请求之前可以应用“pre”或“post”请求的地方。
因此为了在有条件地转发请求之前发送自定义响应状态代码,必须编写一个自定义“预”过滤器,这可以通过以下方式实现。 (设置403状态码)
AuthenticationGatewayFilterFactory
@Component
public class AuthenticationGatewayFilterFactory
extends AbstractGatewayFilterFactory<AuthenticationGatewayFilterFactory.Config> {
public AuthenticationGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
try {
if(isRequestAuthenticated) {
return chain.filter(exchange);
}
else {
exchange.getResponse().setStatusCode(403); // Any status code can be set here.
return exchange.getResponse().complete();
}
} catch (HttpClientErrorException e) {
exchange.getResponse().setStatusCode(403); // Any status code can be set here.
return exchange.getResponse().complete();
}
};
}
public static class Config {
}
private Boolean isRequestAuthenticated(String authToken) {
// Some sample logic that makes a REST call and returns TRUE/FALSE/HttpClientErrorException
//Not shown here for simplicity.
return true;
}
RouteLocator
@Bean
public RouteLocator customRoutesLocator(RouteLocatorBuilder builder
AuthenticationGatewayFilterFactory agff) {
return builder.routes()
.route("id1", r ->r.path("/app1/**")
.uri("lb://id1")
.filter(agff.apply(new Config()))).build();
}