Soap 带有大附件的HttpEntity的SWA响应的Java传输失败(can';t块多部分)
请注意:此问题也已发布到官方的Apache HttpClient用户邮件列表中 问题 基于ApacheHttpComponents构建的基于Java的服务器应该如何组装和发送带有附件的大型SOAP(SWA)响应 问题详细信息 Apache HttpClient Java API不支持分块多部分HttpEntity实例。当SWA响应中的附件较大(>2 MiB)时,向模拟服务器发出SOAP请求的客户端失败(具体来说,基于Apache的Java客户端抛出org.Apache.http.NoHttpResponseException)。传输小附件时不会引发任何异常。HTTP内容长度头是正确的 用例Soap 带有大附件的HttpEntity的SWA响应的Java传输失败(can';t块多部分),soap,server,multipart,apache-httpcomponents,chunked-encoding,Soap,Server,Multipart,Apache Httpcomponents,Chunked Encoding,请注意:此问题也已发布到官方的Apache HttpClient用户邮件列表中 问题 基于ApacheHttpComponents构建的基于Java的服务器应该如何组装和发送带有附件的大型SOAP(SWA)响应 问题详细信息 Apache HttpClient Java API不支持分块多部分HttpEntity实例。当SWA响应中的附件较大(>2 MiB)时,向模拟服务器发出SOAP请求的客户端失败(具体来说,基于Apache的Java客户端抛出org.Apache.http.NoHttpRe
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.ExceptionLogger;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import static org.apache.http.HttpStatus.SC_OK;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.nio.bootstrap.HttpServer;
import org.apache.http.impl.nio.bootstrap.ServerBootstrap;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.protocol.BasicAsyncRequestConsumer;
import org.apache.http.nio.protocol.BasicAsyncResponseProducer;
import org.apache.http.nio.protocol.HttpAsyncExchange;
import org.apache.http.nio.protocol.HttpAsyncRequestConsumer;
import org.apache.http.nio.protocol.HttpAsyncRequestHandler;
import org.apache.http.protocol.HttpContext;
public class HttpComponentsConciseTest {
/*
* The random.png.gz file must be large (> 2 MiB)
*/
private static final String LARGE_COMPRESSED_FILE_NAME = "random.png.gz";
private static final File LARGE_TEST_GZIP_FILE = new File(LARGE_COMPRESSED_FILE_NAME);
private static final String SOAP_RESPONSE_MESSAGE_XML
= "<soapenv:Envelope "
+ "xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soapenv:Header/>\n"
+ " <soapenv:Body>\n"
+ " <AResponse>\n"
+ " <ResponseFile>" + LARGE_COMPRESSED_FILE_NAME + "</ResponseFile>\n"
+ " </AResponse>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>";
private static final int PORT_NUMBER = 8080;
public static void main(String[] args) {
startHttpServer();
}
private static void startHttpServer() {
IOReactorConfig config = IOReactorConfig.custom()
.setIoThreadCount(1)
.setSoTimeout(15000)
.setTcpNoDelay(true)
.build();
final HttpServer server = ServerBootstrap.bootstrap()
.setListenerPort(PORT_NUMBER)
.setServerInfo("Test/1.1")
.setIOReactorConfig(config)
.setExceptionLogger(ExceptionLogger.STD_ERR)
.registerHandler("*", new PrimaryRequestHandler())
.create();
Runtime.getRuntime().addShutdownHook(new Thread(() -> server.shutdown(5,
TimeUnit.MILLISECONDS)));
Thread serverOwner = new Thread(() -> {
try {
server.start();
} catch (IOException ex) {
Logger.getLogger(HttpComponentsConciseTest.class.getName()).log(Level.SEVERE, null,
ex);
}
}, "ServerOwner");
serverOwner.start();
}
private static class PrimaryRequestHandler implements HttpAsyncRequestHandler<HttpRequest> {
@Override
public HttpAsyncRequestConsumer<HttpRequest> processRequest(
final HttpRequest request,
final HttpContext context) {
return new BasicAsyncRequestConsumer();
}
@Override
public void handle(
final HttpRequest request,
final HttpAsyncExchange httpexchange,
final HttpContext context) throws HttpException, IOException {
HttpResponse response = httpexchange.getResponse();
String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
if (!method.equals("POST")) {
throw new MethodNotSupportedException(method + " method not supported");
}
StringBody soapResponseStringBody = new StringBody(SOAP_RESPONSE_MESSAGE_XML,
ContentType.APPLICATION_XML);
FileBody soapAttachment = new FileBody(LARGE_TEST_GZIP_FILE);
HttpEntity responseEntity = MultipartEntityBuilder.create()
.addPart("SOAP Envelope", soapResponseStringBody)
.addPart(LARGE_COMPRESSED_FILE_NAME, soapAttachment)
.build();
response.setStatusCode(SC_OK);
response.setEntity(responseEntity);
httpexchange.submitResponse(new BasicAsyncResponseProducer(response));
}
}
}
能够传输任意内容长度的SWA响应的多线程SOAP服务器
平台
Java 8 64b
必需的库
HttpCore v4.4.6+HttpTime v4.5.3
错误复制
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.ExceptionLogger;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import static org.apache.http.HttpStatus.SC_OK;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.nio.bootstrap.HttpServer;
import org.apache.http.impl.nio.bootstrap.ServerBootstrap;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.protocol.BasicAsyncRequestConsumer;
import org.apache.http.nio.protocol.BasicAsyncResponseProducer;
import org.apache.http.nio.protocol.HttpAsyncExchange;
import org.apache.http.nio.protocol.HttpAsyncRequestConsumer;
import org.apache.http.nio.protocol.HttpAsyncRequestHandler;
import org.apache.http.protocol.HttpContext;
public class HttpComponentsConciseTest {
/*
* The random.png.gz file must be large (> 2 MiB)
*/
private static final String LARGE_COMPRESSED_FILE_NAME = "random.png.gz";
private static final File LARGE_TEST_GZIP_FILE = new File(LARGE_COMPRESSED_FILE_NAME);
private static final String SOAP_RESPONSE_MESSAGE_XML
= "<soapenv:Envelope "
+ "xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soapenv:Header/>\n"
+ " <soapenv:Body>\n"
+ " <AResponse>\n"
+ " <ResponseFile>" + LARGE_COMPRESSED_FILE_NAME + "</ResponseFile>\n"
+ " </AResponse>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>";
private static final int PORT_NUMBER = 8080;
public static void main(String[] args) {
startHttpServer();
}
private static void startHttpServer() {
IOReactorConfig config = IOReactorConfig.custom()
.setIoThreadCount(1)
.setSoTimeout(15000)
.setTcpNoDelay(true)
.build();
final HttpServer server = ServerBootstrap.bootstrap()
.setListenerPort(PORT_NUMBER)
.setServerInfo("Test/1.1")
.setIOReactorConfig(config)
.setExceptionLogger(ExceptionLogger.STD_ERR)
.registerHandler("*", new PrimaryRequestHandler())
.create();
Runtime.getRuntime().addShutdownHook(new Thread(() -> server.shutdown(5,
TimeUnit.MILLISECONDS)));
Thread serverOwner = new Thread(() -> {
try {
server.start();
} catch (IOException ex) {
Logger.getLogger(HttpComponentsConciseTest.class.getName()).log(Level.SEVERE, null,
ex);
}
}, "ServerOwner");
serverOwner.start();
}
private static class PrimaryRequestHandler implements HttpAsyncRequestHandler<HttpRequest> {
@Override
public HttpAsyncRequestConsumer<HttpRequest> processRequest(
final HttpRequest request,
final HttpContext context) {
return new BasicAsyncRequestConsumer();
}
@Override
public void handle(
final HttpRequest request,
final HttpAsyncExchange httpexchange,
final HttpContext context) throws HttpException, IOException {
HttpResponse response = httpexchange.getResponse();
String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
if (!method.equals("POST")) {
throw new MethodNotSupportedException(method + " method not supported");
}
StringBody soapResponseStringBody = new StringBody(SOAP_RESPONSE_MESSAGE_XML,
ContentType.APPLICATION_XML);
FileBody soapAttachment = new FileBody(LARGE_TEST_GZIP_FILE);
HttpEntity responseEntity = MultipartEntityBuilder.create()
.addPart("SOAP Envelope", soapResponseStringBody)
.addPart(LARGE_COMPRESSED_FILE_NAME, soapAttachment)
.build();
response.setStatusCode(SC_OK);
response.setEntity(responseEntity);
httpexchange.submitResponse(new BasicAsyncResponseProducer(response));
}
}
}
导入java.io.File;
导入java.io.IOException;
导入java.nio.file.Files;
导入java.util.Locale;
导入java.util.concurrent.TimeUnit;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入org.apache.http.ExceptionLogger;
导入org.apache.http.HttpEntity;
导入org.apache.http.HttpException;
导入org.apache.http.HttpRequest;
导入org.apache.http.HttpResponse;
导入静态org.apache.http.HttpStatus.SC\u OK;
导入org.apache.http.MethodNotSupportedException;
导入org.apache.http.entity.ContentType;
导入org.apache.http.entity.mime.MultipartEntityBuilder;
导入org.apache.http.entity.mime.content.ByteArrayBody;
导入org.apache.http.entity.mime.content.StringBody;
导入org.apache.http.impl.nio.bootstrap.HttpServer;
导入org.apache.http.impl.nio.bootstrap.ServerBootstrap;
导入org.apache.http.impl.nio.reactor.IOReactorConfig;
导入org.apache.http.nio.protocol.BasicAsyncRequestConsumer;
导入org.apache.http.nio.protocol.BasicAsyncResponseProducer;
导入org.apache.http.nio.protocol.HttpAsyncExchange;
导入org.apache.http.nio.protocol.HttpAsyncRequestConsumer;
导入org.apache.http.nio.protocol.HttpAsyncRequestHandler;
导入org.apache.http.protocol.HttpContext;
公共类HttpComponents协同测试{
/*
*random.png.gz文件必须很大(>2 MiB)
*/
私有静态最终字符串大\u压缩\u文件\u NAME=“random.png.gz”;
私有静态最终文件大\u测试\u GZIP\u文件=新文件(大\u压缩\u文件名);
私有静态最终字符串SOAP\u响应\u消息\u XML
=“\n”
+“\n”
+“\n”
+"