当前位置: 首页 > 知识库问答 >
问题:

Spring云网关修改代理错误响应

林玮
2023-03-14

我有以下来自数据库的路由配置

@Bean
    public RouteLocator routeLocator(
        final PathRoutePredicateFactory predicateFactory,
        final RouteConfigDao routeConfigDao) {

        return () -> routeConfigDao.findAll()
            .map(routeConfig -> Route.async()
                .asyncPredicate(predicateFactory.applyAsync(config -> config.setPatterns(of(routeConfig.getPath()))))
                .id(routeConfig.getName())
                .uri(routeConfig.getUrl())
                // .filter(gatewayFilterSupplier())
                .build());

    }

所有代理服务都将返回公共响应json以防出现错误场景

{
  "errorCode": "ASD-325",
  "errorField": "Name"
}

共有1个答案

刘丰羽
2023-03-14

在spring gateway GlobalFilter的帮助下,我找到了解决问题的方法。使用GlobalFilter,我能够截获下游API响应并检查错误响应。

    import com.rmurugaian.spring.cloud.spi.MessageServiceProvider;
    import org.reactivestreams.Publisher;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.core.io.buffer.DataBuffer;
    import org.springframework.core.io.buffer.DataBufferFactory;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;

    import java.nio.charset.StandardCharsets;

    @Component
    public class DownstreamErrorResponseFilter implements GlobalFilter, Ordered {

    private final MessageServiceProvider messagingService;

    public DownstreamErrorResponseFilter(final MessageServiceProvider messagingService) {
        this.messagingService = messagingService;
    }

    @Override
    public Mono<Void> filter(final ServerWebExchange exchange, final GatewayFilterChain chain) {
        final ServerHttpResponse originalResponse = exchange.getResponse();
        final DataBufferFactory bufferFactory = originalResponse.bufferFactory();
        final ServerHttpResponseDecorator decoratedResponse =
                new ErrorResponseResolveDecorator(originalResponse, bufferFactory, messagingService);
        return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }

    private static class ErrorResponseResolveDecorator extends ServerHttpResponseDecorator {
        private final ServerHttpResponse originalResponse;
        private final DataBufferFactory bufferFactory;
        private final MessageServiceProvider messagingService;

        ErrorResponseResolveDecorator(
                final ServerHttpResponse delegate,
                final DataBufferFactory bufferFactory,
                final MessageServiceProvider messagingService) {

            super(delegate);
            this.originalResponse = delegate;
            this.bufferFactory = bufferFactory;
            this.messagingService = messagingService;
        }

        @SuppressWarnings("unchecked")
        @Override
        public Mono<Void> writeWith(final Publisher<? extends DataBuffer> body) {
            final HttpStatus statusCode = getStatusCode();
            if (statusCode.isError()) {
                if (body instanceof Flux) {
                    final Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                    final Flux<DataBuffer> responseFlux =
                            fluxBody
                                    .map(DownstreamErrorResponseFilter::readAsString)
                                    .flatMap(messagingService::resolveErrorResponse)
                                    .map(String::getBytes)
                                    .map(bufferFactory::wrap);
                    return super.writeWith(responseFlux);
                }
            }
            return originalResponse.writeWith(body); // if body is not a flux. never got there.
        }
    }

    private static String readAsString(final DataBuffer dataBuffer) {
        final byte[] content = new byte[dataBuffer.readableByteCount()];
        dataBuffer.read(content);
        return new String(content, StandardCharsets.UTF_8);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
 类似资料:
  • 我正在尝试使用AWS lambda设置一个hello world示例并通过api网关提供它。我单击了“创建Lambda函数”,它设置了api网关并选择了空白函数选项。我添加了在AWS网关上找到的lambda函数入门指南: 问题是,当我向它发出GET请求时,它会返回502响应{“message”:“Internal server error”}。日志显示“由于配置错误,执行失败:Lambda代理响应

  • 问题内容: 我正在尝试使用AWS Lambda建立一个hello world示例,并通过api网关为其提供服务。我单击了“创建Lambda函数”,这将设置api通道并选择了Blank Function选项。我添加了在AWS网关入门指南中找到的lambda函数: 问题是,当我向它发出GET请求时,它返回了502响应。并且日志显示“由于配置错误,执行失败:Lambda代理响应格式错误”。 问题答案:

  • 我试图用AWS lambda建立一个hello world示例,并通过api网关为其服务。我点击了“创建一个Lambda函数”,它设置了api网关,并选择了空白函数选项。我添加了在AWS网关入门指南上找到的lambda函数: 问题是,当我向它发出GET请求时,它返回502响应。日志上写着“由于配置错误执行失败:Lambda代理响应不正确”。

  • 我用无服务器创建了一个lambda函数。我用lambda控制台测试了lambda函数,它工作得很好。但是,在转换之前,我得到了endpoint响应体:null和执行失败,原因是配置错误:当我试图为该函数调用APIendpoint时,错误的Lambda代理响应。 并且调用了查询字符串参数的endpoint:。 我不知道为什么我的函数已经以这里的格式返回了响应,但仍然得到了格式错误的Lambda代理响

  • 我试图在aws.lamda-service上的node.js中创建函数,并在函数控制台进行测试,效果良好,但当调用api时,它不能导出到外部,api网关错误“malformed Lambda proxy response”状态错误502 有什么想法吗

  • 当通过URL调用我的Web应用程序中不存在的项目时,Spring会使用JSON响应,其中包含(时间、状态、错误、消息、路径)等数据。所以,我需要更改这个JSON的结构,特别是我需要删除路径。我该怎么做?我应该在我的项目中在哪里实现异常的自定义?向大家问好! json响应修改