Я пытаюсь сделать:Httpcomponents httpcore и HttpClient HTTP_STATUS 400
- Отправить запрос от HttpClient (основано на HttpComponents HttpClient 4,5).
- Получите этот запрос в HttpServer (на основе HttpComponents HttpCore 4.4.1).
- HttpServer должен отвечать на HttpClient с разными кодами HttpStatus и строковыми объектами как тело.
Проблема: Если HttpServer ответит кодом статуса 200 (или другими, не отмеченными), то он будет работать нормально и без исключений на стороне сервера. Но если сервер устанавливает код состояния ответа 400, то на сервере HttpServer происходит IOException. Описание на русском: «Удаленный хост принудительно разорвал первое подключение», по-английски я думаю, что это «Клиент закрытой связи». Простой: при статусе 200 нет проблем, на 400 это исключение произошло на сервере.
Исключение строки:
java.io.IOException: Удаленный хост принудительно разорвал существующее подключение на sun.nio.ch.SocketDispatcher.read0 (нативный метод) ~ [па: 1.7.0_51] на sun.nio.ch.SocketDispatcher.read (SocketDispatcher.java:43) ~ [na: 1.7.0_51] at sun.nio.ch.IOUtil.readIntoNativeBuffer (IOUtil.java:223) ~ [na: 1.7.0_51] at sun.nio.ch.IOUtil.read (IOUtil.java:197) ~ [na: 1.7.0_51] at sun.nio.ch.SocketChannelImpl.read (SocketChannelImpl.java:379) ~ [na: 1.7. 0_51] at org.apache.http.nio.reactor.ssl.SSLIOSession.receiveEncryptedData (SSLIOSession.java:449) ~ [httpcore-nio-4.4.1.jar: 4.4.1] at org.apache.http.nio. reactor.ssl.SSLIOSession.isAppInputReady (SSLIOSession.java:503) ~ [httpcore-nio-4.4.1.jar: 4.4.1] at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady (AbstractIODispatch. java: 122) ~ [httpcore-nio-4.4.1.jar: 4.4.1] at org.apache.http.impl.nio.reactor.BaseIOReactor.readable (BaseIOReactor.java:164) [httpcore-nio-4.4 .1.jar: 4.4.1] at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent (AbstractIOReactor.java:339) [httpcore-nio-4.4.1.jar: 4.4.1] at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents (AbstractIOReactor.java:317) [httpcore-nio-4.4.1.jar: 4.4.1] at org.apache.http.impl.nio.reactor .AbstractIOReact or.execute (AbstractIOReactor.java:278) [httpcore-nio-4.4.1.jar: 4.4.1] at org.apache.http.impl.nio.reactor.BaseIOReactor.execute (BaseIOReactor.java:106) [ httpcore-nio-4.4.1.jar: 4.4.1] at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor $ Worker.run (AbstractMultiworkerIOReactor.java:590) [httpcore-nio-4.4.1.jar : 4.4.1] на java.lang.Thread.run (Thread.java:744) [па: 1.7.0_51]
HttpServer код:
HttpProcessor httpproc = HttpProcessorBuilder.create()
.add(new ResponseDate())
.add(new ResponseServer("HTTP/1.1 WTX Server"))
.add(new ResponseContent())
.add(new ResponseConnControl()).build();
UriHttpAsyncRequestHandlerMapper reqistry = new UriHttpAsyncRequestHandlerMapper();
reqistry.register("*", new HttpServerURLHandler());
HttpAsyncService protocolHandler = new HttpServerConnectionsHandler(httpproc, reqistry);
try {
String keyStoreFile = Config.getString("HTTPServer.keyStoreFile");
String keyStoreFilePassword = Config.getString("HTTPServer.keyStoreFilePassword");
FileInputStream fin = new FileInputStream(keyStoreFile);
KeyStore keystore = KeyStore.getInstance("jks");
keystore.load(fin, keyStoreFilePassword.toCharArray());
KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmfactory.init(keystore, keyStoreFilePassword.toCharArray());
KeyManager[] keymanagers = kmfactory.getKeyManagers();
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(keymanagers, null, null);
NHttpConnectionFactory<DefaultNHttpServerConnection> connFactory = new SSLNHttpServerConnectionFactory(sslcontext, null, ConnectionConfig.DEFAULT);
IOEventDispatch ioEventDispatch = new DefaultHttpServerIODispatch(protocolHandler, connFactory);
IOReactorConfig config = IOReactorConfig.custom()
//.setIoThreadCount(10)
//.setSoTimeout(5000)
//.setConnectTimeout(4000)
//.setSoKeepAlive(true)
//.setSoReuseAddress(true)
//.setRcvBufSize(65535)
//.setTcpNoDelay(true)
.build();
ListeningIOReactor ioReactor = new DefaultListeningIOReactor(config);
ioReactor.listen(new InetSocketAddress(socketAddr, socketPort));
ioReactor.execute(ioEventDispatch);
} catch (Exception e) {
MDC.put(ApplicationInit.LOGGERVAR, ApplicationInit.LOGGERCTX.HTTPSERVER.toString());
logger.error("Error while creating HTTP Server instance.", e);
}
URL-код Hander:
public class HttpServerURLHandler implements HttpAsyncRequestHandler<HttpRequest> {
public static final Logger logger = LoggerFactory.getLogger(HttpServerURLHandler.class);
private BasicHttpResponse httpResponse = null;
public HttpServerURLHandler() {
super();
}
public HttpAsyncRequestConsumer<HttpRequest> processRequest(final HttpRequest request, final HttpContext context) {
return new BasicAsyncRequestConsumer();
}
public void handle(final HttpRequest httpRequest, final HttpAsyncExchange httpExchange, final HttpContext httpContext) throws HttpException, IOException {
String string1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ++++++++++++++++++++++++++++++++++++++++++++++++abcdefghijklmnopqrstuvwxyz";
string1 += "ABCDEFGHIJKLMNOPQRSTUVWXYZ++++++++++++++++++++++++++++++++++++++++++++++++abcdefghijklmnopqrstuvwxyz";
int httpCode = 400;
String httpCodeString = EnglishReasonPhraseCatalog.INSTANCE.getReason(httpCode, Locale.ENGLISH);
BasicHttpResponse httpResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, httpCode, httpCodeString);
NStringEntity answerEntity = new NStringEntity(stringXML, Consts.UTF_8);
httpResponse.setEntity(answerEntity);
httpExchange.submitResponse(new BasicAsyncResponseProducer(httpResponse));
}
}
код клиента:
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(20000)
.setConnectionRequestTimeout(20000)
.setSocketTimeout(20000)
.build();
SSLContext sslContext = null;
try {
TrustStrategy trustStrategy = new TrustStrategy() {
public boolean isTrusted(X509Certificate[] arg0, String arg1) {
return true;
}
};
sslContext = new SSLContextBuilder().loadTrustMaterial(null, trustStrategy).build();
} catch (Exception e) {
MDC.put(ApplicationInit.LOGGERVAR, ApplicationInit.LOGGERCTX.HTTPCLIENT.toString());
logger.error("Error while creating SSL context for making HTTP request", e);
}
CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(config)
.setSSLContext(sslContext)
.setSSLHostnameVerifier(new NoopHostnameVerifier())
.build();
String stringURL = "https://serverhost:port/";
try {
HttpPost post = new HttpPost(stringURL);
post.setEntity(httpClientRequest.getEntity());
CloseableHttpResponse httpResponse = client.execute(post);
// Consume entity code
HttpEntity responseEntity = httpResponse.getEntity();
String stringXMLAnswer = EntityUtils.toString(responseEntity);
EntityUtils.consume(responseEntity);
// Some next operations with responseEntity
} catch (Exception e) {
MDC.put(ApplicationInit.LOGGERVAR, ApplicationInit.LOGGERCTX.HTTPCLIENT.toString());
logger.error("Error while make request.", e);
} finally {
try {
// Closing connection
client.close();
} catch (Exception e) {
MDC.put(ApplicationInit.LOGGERVAR, ApplicationInit.LOGGERCTX.HTTPCLIENT.toString());
logger.error("Error while closing connection after making request", e);
}
}
Вы используете контент сообщения в случае ответа с статусом не 2xx? – oleg
Нет, эта ситуация возникает только в том случае, если сервер задает код статуса ответа 400. Я тестировал коды 200, 401, 402 и нормально работал. Проблема заключается только в 400 кодах ошибок. И я должен добавить некоторую информацию: проблема с кодом 400 существует только с непустым сущностью. Если сервер не установил сущность или не установил пустой объект, он работает нормально. – lanmaster
Вы потребляете контент ответного сообщения или нет? – oleg