Spring boot Spring云网关在筛选器中发送响应
我使用SpringCloudGateway作为边缘服务器。 这就是流程 如果请求有一个名为“x-foo”的头,则查找头值,从另一台服务器获取一个字符串,并将该字符串作为响应发送,而不是实际代理请求 下面是过滤器DSL的代码Spring boot Spring云网关在筛选器中发送响应,spring-boot,spring-cloud-gateway,spring-reactive,Spring Boot,Spring Cloud Gateway,Spring Reactive,我使用SpringCloudGateway作为边缘服务器。 这就是流程 如果请求有一个名为“x-foo”的头,则查找头值,从另一台服务器获取一个字符串,并将该字符串作为响应发送,而不是实际代理请求 下面是过滤器DSL的代码 @Bean public RouteLocator routes(RouteLocatorBuilder builder) { return builder.routes() .route("foo-filter", r
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("foo-filter", r -> r.header('x-foo').and().header("x-intercepted").negate()
.filters(f -> f.filter(fooFilter))
.uri("http://localhost:8081")) // 8081 is self port, there are other proxy related configurations too
.build();
}
Foo过滤器代码
@Component
@Slf4j
public class FooFilter implements GatewayFilter {
@Autowired
private ReactiveRedisOperations<String, String> redisOps;
@Value("${header-name}")
private String headerName;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
var foo = request.getHeaders().getFirst(headerName);
return redisOps.opsForHash()
.get("foo:" + foo, "response")
.doOnSuccess(s -> {
log.info("data on success");
log.info(s.toString()); // I am getting proper response here
if (s != null) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.OK);
response.getHeaders().set("x-intercepted", "true");
byte[] bytes = s.toString().getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bytes);
response.writeWith(Mono.just(buffer));
response.setComplete();
}
})
.then(chain.filter(exchange));
}
}
@组件
@Slf4j
公共类FooFilter实现GatewayFilter{
@自动连线
私有反应器操作再发现;
@值(“${header name}”)
私有字符串头名称;
@凌驾
公共Mono筛选器(服务器WebExchange exchange、网关筛选器链){
ServerHttpRequest请求=exchange.getRequest();
var foo=request.getHeaders().getFirst(headerName);
返回redisOps.opsForHash()
.get(“foo:+foo,response”)
.doOnSuccess(s->{
日志信息(“成功数据”);
log.info(s.toString());//我在这里得到了正确的响应
如果(s!=null){
ServerHttpResponse response=exchange.getResponse();
response.setStatusCode(HttpStatus.OK);
response.getHeaders()set(“x-intercepted”,“true”);
byte[]bytes=s.toString().getBytes(StandardCharsets.UTF_8);
DataBuffer buffer=response.bufferFactory().wrap(字节);
writeWith(Mono.just(buffer));
response.setComplete();
}
})
.然后(链式过滤器(交换));
}
}
问题是,响应有一个错误,即响应获得了正确的200代码,响应中存在注入的头,但响应中没有可用的数据 我就是这样开始工作的
- 使用
而不是flatMap
doOnSuccess
- 不要使用
或然后
,而是使用开关ifempty
onErrorResume
- 返回
响应。用
@组件
@Slf4j
公共类FooFilter实现GatewayFilter{
@自动连线
私有反应器操作再发现;
@值(“${header name}”)
私有字符串头名称;
@凌驾
公共Mono筛选器(服务器WebExchange exchange、网关筛选器链){
ServerHttpRequest请求=exchange.getRequest();
var foo=request.getHeaders().getFirst(headerName);
返回redisOps.opsForHash()
.get(“foo:+foo,response”)
.flatMap(s->{
日志信息(“成功数据”);
log.info(s.toString());//我在这里得到了正确的响应
如果(s!=null){
ServerHttpResponse response=exchange.getResponse();
response.setStatusCode(HttpStatus.OK);
response.getHeaders()set(“x-intercepted”,“true”);
byte[]bytes=s.toString().getBytes(StandardCharsets.UTF_8);
DataBuffer buffer=response.bufferFactory().wrap(字节);
返回response.writeWith(Mono.just(buffer));
}else{return chain.filter(exchange).then(Mono.fromRunnable(()->{log.info(“它是空的”)}
})
.onErrorResume(链过滤器(交换));
}
}
这似乎与您的问题有关。这正是我所需要的。但是,返回后会出现错误。java.lang.UnsupportedOperationException:null位于org.springframework.http.ReadOnlyHttpHeaders.putAll(ReadOnlyHttpHeaders.java:131)~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]抑制:reactor.core.publisher.FluxOnAssembly$OnAssemblyException:在以下站点发现错误:|检查点?org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter[DefaultWebFilterChain]|检查点?org.springframework.security.web.server.authorization.AuthorizationWebFilter[DefaultWebFilterChain]您好@Akshay,请与stacktraceApparently共享更新的代码。我使用了switchIfEmpty
,这是案例早期执行。
@Component
@Slf4j
public class FooFilter implements GatewayFilter {
@Autowired
private ReactiveRedisOperations<String, String> redisOps;
@Value("${header-name}")
private String headerName;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
var foo = request.getHeaders().getFirst(headerName);
return redisOps.opsForHash()
.get("foo:" + foo, "response")
.flatMap(s -> {
log.info("data on success");
log.info(s.toString()); // I am getting proper response here
if (s != null) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.OK);
response.getHeaders().set("x-intercepted", "true");
byte[] bytes = s.toString().getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bytes);
return response.writeWith(Mono.just(buffer));
}else{ return chain.filter(exchange).then(Mono.fromRunnable(() -> {log.info("It was empty")} }
})
.onErrorResume(chain.filter(exchange));
}
}