如何在Spring Cloud Gateway中编辑多部分/表单数据请求数据?

时间:2019-07-02 07:42:22

标签: java spring-cloud multipartform-data spring-webflux gateway

我正在使用Spring Cloud Gateway进行参数检查,如何编辑多部分/表单数据请求数据?

我可以读取参数,但是我不知道如何编辑。

我认为问题的关键在于我不知道如何序列化和反序列化请求参数。

    Name  A  B  C  D  E  new_col
0   Anna  1  1  2  2  3    1-2-3
1    Bob  2  2  3  1  1       NA
2  Chloe  1  1  2  3  4  1-2-3-4
3  David  1  2  2  2  1       NA

1 个答案:

答案 0 :(得分:0)

对于多部分请求修改尤其是具有表单数据的请求,该过程有些棘手。不幸的是,ModifyRequestBodyGatewayFilterFactory无法直接帮助您,因为无法转换字符串-> multi-part->字符串。

这里的过程是读取整个请求,将其转换为多部分,对其进行修改,然后将其重新设置为已修改请求的字符串。现在没有工厂方法可以进行这种转换,但是您仍然可以使用该方法并执行以下操作:

             ServerRequest serverRequest = ServerRequest.create(exchange, messageReaders);
            
            // get modified body from original body o
            Mono<MultiValueMap<String, String>> modifiedBody = serverRequest.bodyToMono(String.class).flatMap(o -> {
                // create mock request to read body
                SynchronossPartHttpMessageReader synchronossReader = new SynchronossPartHttpMessageReader();
                MultipartHttpMessageReader reader = new MultipartHttpMessageReader(synchronossReader);
                MockServerHttpRequest request = MockServerHttpRequest.post("").contentType(exchange.getRequest().getHeaders().getContentType()).body(o);
                Mono<MultiValueMap<String, Part>> monoRequestParts = reader.readMono(MULTIPART_DATA_TYPE, request, Collections.emptyMap());
                // modify parts
                return monoRequestParts.flatMap(requestParts -> {
                    Map<String, List<String>> modifedBodyArray = requestParts.entrySet().stream().map(entry -> {
                        String key = entry.getKey();
                        LOGGER.info(key);
                        List<String> entries = entry.getValue().stream().map(part -> {
                            LOGGER.info("{}", part);
                            // read the input part
                            String input = ((FormFieldPart) part).value();
                            // return the modified input part
                            return new String(modifyRequest(config, exchange, key, input));
                        }).collect(Collectors.toList());
                        return new Map.Entry<String, List<String>>() {
                            @Override
                            public String getKey() {
                                return key;
                            }
                            @Override
                            public List<String> getValue() {
                                return entries;
                            }
                            @Override
                            public List<String> setValue(List<String> param1) {
                                return param1;
                            }
                        };
                    }).collect(Collectors.toMap(k -> k.getKey(), k -> k.getValue()));
                    return Mono.just(new LinkedMultiValueMap<String, String>(modifedBodyArray));
                });
            });
            
            // insert the new modified body
            BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, new ParameterizedTypeReference<MultiValueMap<String, String>>() {});
            HttpHeaders headers = new HttpHeaders();
            headers.putAll(exchange.getRequest().getHeaders());

            // the new content type will be computed by bodyInserter
            // and then set in the request decorator
            headers.remove(HttpHeaders.CONTENT_LENGTH);
            
            CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
            return bodyInserter.insert(outputMessage, new BodyInserterContext())
                    .then(Mono.defer(() -> {
                        ServerHttpRequest decorator = decorate(exchange, headers, outputMessage);
                        return chain.filter(exchange.mutate().request(decorator).build());
                    }));