web-dev-qa-db-ja.com

Zuulポストフィルターで応答本文を取得する方法?

Zuulをpostフィルターのプロキシーとして使用しながら、応答本文を読み取るにはどうすればよいですか?

私はこのようなコードを呼び出そうとしています:

@Component
public class PostFilter extends ZuulFilter {

    private static final Logger log = LoggerFactory.getLogger(PostFilter.class);

    @Override
    public String filterType() {
        return "post";
    }

    @Override
    public int filterOrder() {
        return 2000;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.getResponseBody(); // null

        // cant't do this, cause input stream is used later in other filters and I got InputStream Closed exception
        // GZIPInputStream gzipInputStream = new GZIPInputStream(stream);
        return null;
    }

}
12
Dariusz Mydlarz

私はこれをなんとか乗り越えました。ソリューションは4つのステップで構成されています。

  1. ctx.getResponseDataStream()をByteArrayOutputStreamに読み込みます
  2. OutputStreamを2つのInputStreamにコピーします。
  3. カスタムの目的でそれを使用してください。
  4. 2番目を使用してコンテキストに再割り当てします:context.setResponseBody(inputStream)
    • ポイント1からストリームを読み取ると、ストリームを再度読み取ることができないため、この方法で、まだ読み取られていない新しい新鮮なストリームを渡します
11
Dariusz Mydlarz

提案をありがとう、これは私が使用したコードで機能します。

try (final InputStream responseDataStream = ctx.getResponseDataStream()) {
   final String responseData = CharStreams.toString(new InputStreamReader(responseDataStream, "UTF-8"));
   ctx.setResponseBody(responseData);
} catch (IOException e) {
   logger.warn("Error reading body",e);
}
3
codesalsa

この example を見るとわかるように、応答の本文を抽出するには、2つの方法があります。

1- ctx.getResponseBody();

2- ctx.getResponseDataStream();

Nullでないものを確認し、それを使用する必要があります。

3
Pablo Valiente

誰かが圧縮された回答に苦労している場合、私が使用した解決策は次のとおりです:

// Read the compressed response
RequestContext ctx = RequestContext.getCurrentContext();
InputStream compressedResponseDataStream = ctx.getResponseDataStream();
try {
    // Uncompress and transform the response
    InputStream responseDataStream = new GZIPInputStream(compressedResponseDataStream);
    String responseAsString = StreamUtils.copyToString(responseDataStream, Charset.forName("UTF-8"));
    // Do want you want with your String response
    ...
    // Replace the response with the modified object
    ctx.setResponseBody(responseAsString);
} catch (IOException e) {
    logger.warn("Error reading body", e);
}
2
VincentS

FilterNumberに注意してください

1000を超える値を使用すると、応答の本文が既に読み込まれており、

私は数字の10を使用し、うまくいきました

1
Pedro Romão

答えはどれもうまくいきませんでした。 1)フィルターの次数は1000より低くする必要があります(応答フィルターを送信)

2)コード:

 private String getResponseData(RequestContext ctx) throws IOException {
    String responseData = null;

    final InputStream responseDataStream = ctx.getResponseDataStream();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ByteArrayOutputStream copy = new ByteArrayOutputStream();
    int read = 0;
    byte[] buff = new byte[1024];
    while ((read = responseDataStream.read(buff)) != -1) {
        bos.write(buff, 0, read);
        copy.write(buff, 0, read);
    }
    InputStream isFromFirstData = new ByteArrayInputStream(bos.toByteArray());

    boolean responseGZipped = ctx.getResponseGZipped();
    try {
        InputStream zin = null;
        if (responseGZipped) {
            zin = new GZIPInputStream(isFromFirstData);
        } else {
            zin = responseDataStream;
        }
        responseData = CharStreams.toString(new InputStreamReader(zin, "UTF-8"));
        ctx.setResponseDataStream(new ByteArrayInputStream(copy.toByteArray()));

    } catch (IOException e) {
        logger.warn("Error reading body {}", e.getMessage());
    }

    return responseData;
}
1
Damian