From 2569972ca1330dfe811be9d713fc5a005f5d7cfd Mon Sep 17 00:00:00 2001 From: trytocatch Date: Mon, 22 May 2023 22:00:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8E=9F=E6=9D=A5=E7=9A=84getResponseBody?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=9C=A8=E6=9F=90=E4=BA=9B=E6=83=85=E5=86=B5?= =?UTF-8?q?=E4=B8=8B=E4=BC=9A=E8=AF=AF=E4=BF=AE=E6=94=B9responseBody?= =?UTF-8?q?=EF=BC=8C=E5=BC=95=E5=8F=91=E9=97=AE=E9=A2=98=EF=BC=8C=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E7=9B=B4=E6=8E=A5=E4=BD=BF=E7=94=A8byte=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E6=9D=A5=E9=81=BF=E5=85=8D=E6=95=B0=E6=8D=AE=E8=A2=AB?= =?UTF-8?q?=E7=AF=A1=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApacheHttpClientProcessor.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/repeater-plugins/apache-http-client-plugin/src/main/java/com/alibaba/jvm/sandbox/repeater/plugin/apachehttpclient/ApacheHttpClientProcessor.java b/repeater-plugins/apache-http-client-plugin/src/main/java/com/alibaba/jvm/sandbox/repeater/plugin/apachehttpclient/ApacheHttpClientProcessor.java index 6df688e9..76c25b71 100644 --- a/repeater-plugins/apache-http-client-plugin/src/main/java/com/alibaba/jvm/sandbox/repeater/plugin/apachehttpclient/ApacheHttpClientProcessor.java +++ b/repeater-plugins/apache-http-client-plugin/src/main/java/com/alibaba/jvm/sandbox/repeater/plugin/apachehttpclient/ApacheHttpClientProcessor.java @@ -234,21 +234,23 @@ private String getResponseBody(Object response, ClassLoader classLoader) throws Boolean isRepeatable = (Boolean)MethodUtils.invokeMethod(httpEntity, "isRepeatable"); if (isRepeatable){ - return this.getResponseBodyStr(httpEntity, classLoader); + return this.getResponseBodyStrAndBytes(httpEntity, classLoader, null); }else { if (this.canResetContent(httpEntity, classLoader)){ - String responseBodyStr = this.getResponseBodyStr(httpEntity, classLoader); + byte[][] holder = new byte[1][]; + String responseBodyStr = this.getResponseBodyStrAndBytes(httpEntity, classLoader, holder); // 重新设置返回结果中的流 - this.reSetResponseStream(classLoader, httpEntity, responseBodyStr, false); + this.reSetResponseStream(classLoader, httpEntity, holder[0], false); return responseBodyStr; }else { // 如果当前这个wrappedEntity没有setContent方法,就尝试在当前wrappedEntity内部取属性wrappedEntity Object httpEntityInside = this.getWrappedEntity(httpEntity, classLoader); if (this.canResetContent(httpEntityInside, classLoader)){ + byte[][] holder = new byte[1][]; // 有些压缩数据需要特殊处理,所以还是从最外层的httpEntity获取数据 - String responseBodyStr = this.getResponseBodyStr(httpEntity, classLoader); + String responseBodyStr = this.getResponseBodyStrAndBytes(httpEntity, classLoader, holder); // 重新设置返回结果中的流 - this.reSetResponseStream(classLoader, httpEntityInside, responseBodyStr, true); + this.reSetResponseStream(classLoader, httpEntityInside, holder[0], true); // org.apache.http.client.entity.DecompressingEntity,将content置为null,下次读取是触发重新执行getDecompressingStream方法 this.setContentNull(httpEntity, classLoader); return responseBodyStr; @@ -259,12 +261,16 @@ private String getResponseBody(Object response, ClassLoader classLoader) throws } } - private String getResponseBodyStr(Object httpEntity, ClassLoader classLoader) throws Exception{ + private String getResponseBodyStrAndBytes(Object httpEntity, ClassLoader classLoader, byte[][] holder) throws Exception{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); MethodUtils.invokeMethod(httpEntity, "writeTo", baos); Charset charset = this.determineCharset(httpEntity, classLoader); - return new String(baos.toByteArray(), charset); + byte[] bytes = baos.toByteArray(); + if(holder != null){ + holder[0] = bytes; + } + return new String(bytes, charset); } private boolean canResetContent(Object httpEntity, ClassLoader classLoader) throws Exception{ @@ -282,23 +288,22 @@ private Object getWrappedEntity(Object httpEntity, ClassLoader classLoader) thro } // 这里对请求的流进行了重新复制,不同场景的可靠性需要验证 - private void reSetResponseStream(ClassLoader classLoader, Object httpEntity, String responseBodyStr, Boolean gizp) throws Exception { + private void reSetResponseStream(ClassLoader classLoader, Object httpEntity, byte[] bytes, Boolean gizp) throws Exception { Class wrappedEntityClass = classLoader.loadClass("org.apache.http.entity.HttpEntityWrapper"); Field wrappedEntityField = FieldUtils.getDeclaredField(wrappedEntityClass, "wrappedEntity", true); Object wrappedEntity = wrappedEntityField.get(httpEntity); if (gizp){ - MethodUtils.invokeMethod(wrappedEntity, "setContent", this.getGzipByte(responseBodyStr, classLoader, httpEntity)); + MethodUtils.invokeMethod(wrappedEntity, "setContent", this.getGzipByte(bytes, classLoader, httpEntity)); }else { - MethodUtils.invokeMethod(wrappedEntity, "setContent", new ByteArrayInputStream(responseBodyStr.getBytes())); + MethodUtils.invokeMethod(wrappedEntity, "setContent", new ByteArrayInputStream(bytes)); } } - private InputStream getGzipByte(String responseBodyStr, ClassLoader classLoader, Object httpEntity) throws Exception{ + private InputStream getGzipByte(byte[] bytes, ClassLoader classLoader, Object httpEntity) throws Exception{ ByteArrayOutputStream out = new ByteArrayOutputStream(); GZIPOutputStream gzip; - Charset charset = this.determineCharset(httpEntity, classLoader); gzip = new GZIPOutputStream(out); - gzip.write(responseBodyStr.getBytes(charset)); + gzip.write(bytes); gzip.close(); return new ByteArrayInputStream(out.toByteArray());