0

我面临以下问题:

我正在使用一个简单的方法调用另一个服务org.springframework.web.client.RestTemplate

调用它时,我需要拦截请求,修改请求体,让它继续流动。到目前为止,我没有遇到任何问题,因为org.springframework.http.client.ClientHttpRequestInterceptor我可以对我的请求做任何我想做的事情(在将 RequestObjectA 发送到我正在调用的服务之前将其转换为 requestObjectB)。

问题:如何修改响应正文?

我看到打电话时ClientHttpResponse execute = clientHttpRequestExecution.execute(httpRequest, body)我可以让身体做execute.getBody(),所以我可以修改它,但我看不到以某种方式将它设置回来的方法。

有什么办法可以解决我修改后的身体ClientHttpResponse

4

4 回答 4

3

将需要返回一个新的ClientHttpResponse承载修改的对象

我们可以将 originalResponse 的相关数据复制到 ClientHttpResponse 新建的 modifiedResponse 对象中

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        
        ClientHttpResponse response = execution.execute(request, body);
        String responseBody = new String(response.getBody().readAllBytes());
        String modifiedBody = "Just Modified";

        ClientHttpResponse modifiedResponse = new ClientHttpResponse() {
            @Override
            public HttpHeaders getHeaders() {
                return response.getHeaders();
            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream(modifiedBody.getBytes());
            }

            @Override
            public HttpStatus getStatusCode() throws IOException {
                return response.getStatusCode();
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return response.getRawStatusCode();
            }

            @Override
            public String getStatusText() throws IOException {
                return response.getStatusText();
            }

            @Override
            public void close() {

            }
        };
    return modifiedResponse;
}
于 2021-07-22T07:07:07.550 回答
0

我知道这有点老了,我很懒,正在寻找一个如何按照 OP 的要求(运气不好)做的例子,所以最终自己做了。

打击片段包装了 ClientHttpResponse,它会懒惰地将响应主体读入 BAIS,这允许多次读取主体(但确实将整个响应主体加载到内存中)。您也可以使用 setBody(...) 方法替换正文,替换响应正文也会修改 ContentLength 标头。

注意:以下代码未经测试。

public class ClientHttpResponseWrapper implements ClientHttpResponse{
    private final ClientHttpResponse response;
    private ByteArrayInputStream body;
    public ClientHttpResponseWrapper(ClientHttpResponse response) throws IOException {
        this.response=response;
        this.body=null;
    }

    public void setBody(ByteArrayInputStream body) {
        this.body = body;
    }
    @Override
    public ByteArrayInputStream getBody() throws IOException {
        if(this.body != null) {
            return this.body;
        }
        this.body=new ByteArrayInputStream(this.response.getBody().readAllBytes());
        return this.body;
    }
    
    @Override
    public HttpHeaders getHeaders() {
        if(this.body == null) {
            return this.response.getHeaders();
        }
        
        HttpHeaders out = new HttpHeaders(this.response.getHeaders());
        out.setContentLength(this.body.available());
        return out;
    }
    @Override
    public HttpStatus getStatusCode() throws IOException {
        return this.response.getStatusCode();
    }
    @Override
    public int getRawStatusCode() throws IOException {
        return this.response.getRawStatusCode();
    }
    @Override
    public String getStatusText() throws IOException {
        return this.response.getStatusText();
    }
    @Override
    public void close() {
        this.response.close();
    }
}
于 2021-10-25T03:51:24.917 回答
-2

看来您也可以在拦截器中修改响应

public class RestTemplateResponseInterceptor implements ClientHttpRequestInterceptor {
  public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
    ClientHttpResponse response = execution.execute(request, body);
    return modifyResponse(response);
  }
}
于 2020-10-15T11:58:31.690 回答
-8

是的,这很棘手,因为响应主体是 InputStream。一次读取的 InputStream 不能再次读取,具体取决于类型。

第一次读取 InputStream 对象后,可能已经到达 Stream 末尾(EOFException),或者第二次读取 InputStream 对象时 Stream 已经关闭。获取到的数据全部为空或没有获取到数据。

您可以尝试查看 MockClientHttpResponse https://www.gitmemory.com/issue/spring-projects/spring-framework/12671/771105006

于 2021-06-06T18:04:52.770 回答