简体   繁体   English

Spring Cloud Gateway:在自定义谓词中设置响应状态代码

[英]Spring Cloud Gateway: Set response status code in custom predicate

In the below code snippet, I am trying to match my request against a custom predicate.在下面的代码片段中,我试图将我的请求与自定义谓词进行匹配。 Upon the predicate being evaluated as false, I would like to send back a custom status code (403 Forbidden in the below snippet) instead of the default 404 that is being sent on predicate failure.在谓词被评估为 false 时,我想发回自定义状态代码(以下代码段中的 403 Forbidden),而不是在谓词失败时发送的默认 404。 Here's what I've tried.这是我尝试过的。

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 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;
}

} }

When the predicate returns as true, the request is forwarded to the URI.当谓词返回 true 时,请求被转发到 URI。 However, on false evaluation 404 is displayed, I require 403 to be displayed (On HttpClientErrorException ).但是,在显示错误评估 404 时,我需要显示 403(在 HttpClientErrorException 上)。 Is this the right way to expect a response with custom status code?.这是期望具有自定义状态代码的响应的正确方法吗?。 Additionally, I also read on implementing custom webfilters for a given route that can possibly modify the response object before forwarding the request.此外,我还阅读了为给定路由实现自定义 webfilter 的文章,该路由可能会在转发请求之前修改响应对象。 Is there a way to invoke a filter on predicate failure in that case?在这种情况下,有没有办法在谓词失败时调用过滤器?

As a newbie to spring cloud gateway, I chose the wrong direction towards approaching this problem.作为 Spring Cloud Gateway 的新手,我选择了错误的方向来解决这个问题。

Clients make requests to Spring Cloud Gateway.客户端向 Spring Cloud Gateway 发出请求。 If the Gateway Handler Mapping determines that a request matches a route, it is sent to the Gateway Web Handler.如果网关处理程序映射确定请求与路由匹配,则将其发送到网关 Web 处理程序。 Predicates aid the Gateway Handler Mapping in determining if that request matches the route and can only return either a true or false value.谓词帮助网关处理程序映射确定该请求是否与路由匹配,并且只能返回truefalse值。

Once the request matches the route, The handler runs the request through a filter chain that is specific to the request.一旦请求与路由匹配,处理程序就会通过特定于请求的过滤器链运行请求。 This is where "pre" or "post" requests can be applied before forwarding a request.这是在转发请求之前可以应用“pre”或“post”请求的地方。

Therefore In order to send a custom response status code before conditionally forwarding the request, One must write a custom "pre" filter and this can be achieved as below.因此,为了在有条件地转发请求之前发送自定义响应状态代码,必须编写自定义“预”过滤器,这可以实现如下。 (Setting 403 status code) (设置403状态码)

AuthenticationGatewayFilterFactory 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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM