|
39 | 39 | import io.netty.handler.codec.http.HttpUtil;
|
40 | 40 | import io.netty.handler.codec.http.HttpVersion;
|
41 | 41 |
|
| 42 | +import org.apache.http.HttpHost; |
42 | 43 | import org.apache.lucene.util.SetOnce;
|
43 | 44 | import org.elasticsearch.ElasticsearchException;
|
44 | 45 | import org.elasticsearch.ElasticsearchSecurityException;
|
45 | 46 | import org.elasticsearch.ElasticsearchWrapperException;
|
| 47 | +import org.elasticsearch.action.ActionListener; |
| 48 | +import org.elasticsearch.action.support.ActionTestUtils; |
| 49 | +import org.elasticsearch.action.support.SubscribableListener; |
| 50 | +import org.elasticsearch.client.Request; |
| 51 | +import org.elasticsearch.client.RestClient; |
46 | 52 | import org.elasticsearch.common.bytes.BytesArray;
|
47 | 53 | import org.elasticsearch.common.collect.Iterators;
|
48 | 54 | import org.elasticsearch.common.network.NetworkAddress;
|
@@ -956,6 +962,61 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
|
956 | 962 | }
|
957 | 963 | }
|
958 | 964 |
|
| 965 | + public void testRespondAfterClose() throws Exception { |
| 966 | + final String url = "/thing"; |
| 967 | + final CountDownLatch responseReleasedLatch = new CountDownLatch(1); |
| 968 | + final SubscribableListener<Void> transportClosedFuture = new SubscribableListener<>(); |
| 969 | + final CountDownLatch handlingRequestLatch = new CountDownLatch(1); |
| 970 | + |
| 971 | + final HttpServerTransport.Dispatcher dispatcher = new HttpServerTransport.Dispatcher() { |
| 972 | + @Override |
| 973 | + public void dispatchRequest(final RestRequest request, final RestChannel channel, final ThreadContext threadContext) { |
| 974 | + assertEquals(request.uri(), url); |
| 975 | + final var response = RestResponse.chunked( |
| 976 | + OK, |
| 977 | + ChunkedRestResponseBody.fromTextChunks( |
| 978 | + RestResponse.TEXT_CONTENT_TYPE, |
| 979 | + Collections.emptyIterator(), |
| 980 | + responseReleasedLatch::countDown |
| 981 | + ) |
| 982 | + ); |
| 983 | + transportClosedFuture.addListener(ActionListener.running(() -> channel.sendResponse(response))); |
| 984 | + handlingRequestLatch.countDown(); |
| 985 | + } |
| 986 | + |
| 987 | + @Override |
| 988 | + public void dispatchBadRequest(final RestChannel channel, final ThreadContext threadContext, final Throwable cause) { |
| 989 | + fail(cause, "--> Unexpected bad request [%s]", FakeRestRequest.requestToString(channel.request())); |
| 990 | + } |
| 991 | + }; |
| 992 | + |
| 993 | + try ( |
| 994 | + Netty4HttpServerTransport transport = new Netty4HttpServerTransport( |
| 995 | + Settings.EMPTY, |
| 996 | + networkService, |
| 997 | + threadPool, |
| 998 | + xContentRegistry(), |
| 999 | + dispatcher, |
| 1000 | + clusterSettings, |
| 1001 | + new SharedGroupFactory(Settings.EMPTY), |
| 1002 | + Tracer.NOOP, |
| 1003 | + TLSConfig.noTLS(), |
| 1004 | + null, |
| 1005 | + randomFrom((httpPreRequest, channel, listener) -> listener.onResponse(null), null) |
| 1006 | + ) |
| 1007 | + ) { |
| 1008 | + transport.start(); |
| 1009 | + final var address = randomFrom(transport.boundAddress().boundAddresses()).address(); |
| 1010 | + try (var client = RestClient.builder(new HttpHost(address.getAddress(), address.getPort())).build()) { |
| 1011 | + client.performRequestAsync(new Request("GET", url), ActionTestUtils.wrapAsRestResponseListener(ActionListener.noop())); |
| 1012 | + safeAwait(handlingRequestLatch); |
| 1013 | + transport.close(); |
| 1014 | + transportClosedFuture.onResponse(null); |
| 1015 | + safeAwait(responseReleasedLatch); |
| 1016 | + } |
| 1017 | + } |
| 1018 | + } |
| 1019 | + |
959 | 1020 | private Netty4HttpServerTransport getTestNetty4HttpServerTransport(
|
960 | 1021 | HttpServerTransport.Dispatcher dispatcher,
|
961 | 1022 | HttpValidator httpValidator,
|
|
0 commit comments