How to add some data in body of response for Cloud Api Gateway

前端 未结 2 2023
时光取名叫无心
时光取名叫无心 2021-01-12 09:29

I\'m adding some auth logic into cloud api gateway. I\'ve added GatewayFilter:

import java.util.List;

import org.sp         


        
相关标签:
2条回答
  • 2021-01-12 10:22

    After some help from spring guys, I was able to make it work. So instead of writing directly to response I had to throw my custom exception and handle it properly:

    @Bean
    public ErrorWebExceptionHandler myExceptionHandler() {
      return new MyWebExceptionHandler();
    }
    
    public class MyWebExceptionHandler implements ErrorWebExceptionHandler {
      @Override
      public Mono<Void> handle(
        ServerWebExchange exchange, Throwable ex) {
        byte[] bytes = "Some text".getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
        return exchange.getResponse().writeWith(Flux.just(buffer));
      }
    }
    
    0 讨论(0)
  • 2021-01-12 10:24

    You should use ServerHttpResponseDecorator to modify the response.

    Your code should be like:

    import java.util.List;
    
    import org.reactivestreams.Publisher;
    import org.springframework.cloud.gateway.filter.GatewayFilter;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.http.HttpStatus;
    import org.springframework.util.CollectionUtils;
    import org.springframework.util.PatternMatchUtils;
    import org.springframework.web.server.ServerWebExchange;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
    import org.springframework.core.io.buffer.DataBuffer;
    import org.springframework.core.io.buffer.DataBufferFactory;
    import org.springframework.core.Ordered;
    import org.springframework.stereotype.Component;
    
    import reactor.core.publisher.Mono;
    
    public class AuthorizationFilter implements GatewayFilter {
      @Override
      public Mono<Void> filter(
        ServerWebExchange exchange, GatewayFilterChain chain) {
        List<String> authorization = exchange.getRequest().getHeaders().get("Authorization");
        if (CollectionUtils.isEmpty(authorization) &&
          !PatternMatchUtils.simpleMatch(URL_WITHOUT_AUTH, exchange.getRequest().getURI().toString())) {
          exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
    
          ServerHttpResponse originalResponse = exchange.getResponse();
          DataBufferFactory bufferFactory = originalResponse.bufferFactory();
          ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                    return super.writeWith(fluxBody.map(dataBuffer -> {
                        // probably should reuse buffers 
                        byte[] content = new byte[dataBuffer.readableByteCount()];
                        dataBuffer.read(content);
                        byte[] uppedContent = new String(content, Charset.forName("UTF-8")).toUpperCase().getBytes();
                        return bufferFactory.wrap(uppedContent);
                    }));
                }
                return super.writeWith(body); // if body is not a flux. never got there.
            }           
          };
          return chain.filter(exchange.mutate().response(decoratedResponse).build()); // replace response with decorator
        }
        String token = authorization.get(0).split(" ")[1];
        // token validation
        return chain.filter(exchange);
      }
    }
    

    You can find a complete example here.

    0 讨论(0)
提交回复
热议问题