Remove `@Disabled` from more `jetty-core/jetty-server` tests (#9162)
* Remove @Disabled from ConnectorTimeoutTests * Remove @Disabled from SlowClientsTest * Remove @Disabled from SslConnectionFactoryTest * Remove @Disabled from DetectorConnectionTest * Disabling quiche from checkstyle * Removing ConnectorTimeoutTest BlockingTimeout tests + The concept of HttpConfiguration.blockingTimeout has been removed, these tests are no longer relevant
This commit is contained in:
parent
a37b8523e5
commit
fc762aea7d
|
@ -20,6 +20,12 @@
|
|||
<property name="fileNamePattern" value="module\-info\.java$"/>
|
||||
</module>
|
||||
|
||||
<!-- Excludes all quiche files -->
|
||||
<!-- See https://checkstyle.org/config_filefilters.html -->
|
||||
<module name="BeforeExecutionExclusionFileFilter">
|
||||
<property name="fileNamePattern" value="[/\\]org[/\\]eclipse[/\\]jetty[/\\]quic[/\\]quiche[/\\]"/>
|
||||
</module>
|
||||
|
||||
<!-- Checks for whitespace -->
|
||||
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
|
||||
<module name="FileTabCharacter">
|
||||
|
|
|
@ -13,10 +13,8 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -27,20 +25,17 @@ import java.util.concurrent.Exchanger;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.io.ByteBufferAccumulator;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.ssl.SslConnection;
|
||||
import org.eclipse.jetty.logging.StacklessLogging;
|
||||
import org.eclipse.jetty.server.handler.EchoHandler;
|
||||
import org.eclipse.jetty.server.internal.HttpChannelState;
|
||||
import org.eclipse.jetty.util.Blocker;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.NanoTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -48,12 +43,9 @@ import org.slf4j.LoggerFactory;
|
|||
import static java.time.Duration.ofSeconds;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
|
||||
|
@ -101,7 +93,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
"GET / HTTP/1.0\r\n" +
|
||||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"connection: keep-alive\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
os.flush();
|
||||
|
||||
IO.toString(is);
|
||||
|
@ -132,13 +124,13 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
{
|
||||
String content = "Wibble";
|
||||
byte[] contentB = content.getBytes("utf-8");
|
||||
byte[] contentB = content.getBytes(StandardCharsets.UTF_8);
|
||||
os.write((
|
||||
"POST /echo HTTP/1.1\r\n" +
|
||||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"content-type: text/plain; charset=utf-8\r\n" +
|
||||
"content-length: " + contentB.length + "\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
os.write(contentB);
|
||||
os.flush();
|
||||
|
||||
|
@ -185,7 +177,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
"GET / HTTP/1.0\r\n" +
|
||||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"connection: close\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
os.flush();
|
||||
|
||||
// Get the server side endpoint
|
||||
|
@ -240,14 +232,14 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
InputStream is = client.getInputStream();
|
||||
|
||||
String content = "Wibble";
|
||||
byte[] contentB = content.getBytes("utf-8");
|
||||
byte[] contentB = content.getBytes(StandardCharsets.UTF_8);
|
||||
os.write((
|
||||
"POST /echo HTTP/1.1\r\n" +
|
||||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"content-type: text/plain; charset=utf-8\r\n" +
|
||||
"content-length: " + contentB.length + "\r\n" +
|
||||
"connection: close\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
os.write(contentB);
|
||||
os.flush();
|
||||
|
||||
|
@ -273,212 +265,6 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
assertFalse(((Channel)transport).isOpen());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("Unstable")
|
||||
@Disabled // TODO make more stable
|
||||
public void testNoBlockingTimeoutRead() throws Exception
|
||||
{
|
||||
startServer(new EchoHandler());
|
||||
Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
|
||||
client.setSoTimeout(10000);
|
||||
InputStream is = client.getInputStream();
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
long start = NanoTime.now();
|
||||
|
||||
OutputStream os = client.getOutputStream();
|
||||
os.write(("GET / HTTP/1.1\r\n" +
|
||||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"Transfer-Encoding: chunked\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n" +
|
||||
"5\r\n" +
|
||||
"LMNOP\r\n")
|
||||
.getBytes("utf-8"));
|
||||
os.flush();
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(250);
|
||||
os.write("1".getBytes("utf-8"));
|
||||
os.flush();
|
||||
Thread.sleep(250);
|
||||
os.write("0".getBytes("utf-8"));
|
||||
os.flush();
|
||||
Thread.sleep(250);
|
||||
os.write("\r".getBytes("utf-8"));
|
||||
os.flush();
|
||||
Thread.sleep(250);
|
||||
os.write("\n".getBytes("utf-8"));
|
||||
os.flush();
|
||||
Thread.sleep(250);
|
||||
os.write("0123456789ABCDEF\r\n".getBytes("utf-8"));
|
||||
os.write("0\r\n".getBytes("utf-8"));
|
||||
os.write("\r\n".getBytes("utf-8"));
|
||||
os.flush();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
long duration = NanoTime.millisSince(start);
|
||||
assertThat(duration, greaterThan(500L));
|
||||
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
{
|
||||
// read the response
|
||||
String response = IO.toString(is);
|
||||
assertThat(response, startsWith("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString("LMNOP0123456789ABCDEF"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("Unstable")
|
||||
@Disabled // TODO make more stable
|
||||
public void testBlockingTimeoutRead() throws Exception
|
||||
{
|
||||
startServer(new EchoHandler());
|
||||
Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
|
||||
client.setSoTimeout(10000);
|
||||
InputStream is = client.getInputStream();
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
OutputStream os = client.getOutputStream();
|
||||
|
||||
long start = NanoTime.now();
|
||||
os.write(("GET / HTTP/1.1\r\n" +
|
||||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"Transfer-Encoding: chunked\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n" +
|
||||
"5\r\n" +
|
||||
"LMNOP\r\n")
|
||||
.getBytes("utf-8"));
|
||||
os.flush();
|
||||
|
||||
try (StacklessLogging stackless = new StacklessLogging(HttpChannelState.class))
|
||||
{
|
||||
Thread.sleep(300);
|
||||
os.write("1".getBytes("utf-8"));
|
||||
os.flush();
|
||||
Thread.sleep(300);
|
||||
os.write("0".getBytes("utf-8"));
|
||||
os.flush();
|
||||
Thread.sleep(300);
|
||||
os.write("\r".getBytes("utf-8"));
|
||||
os.flush();
|
||||
Thread.sleep(300);
|
||||
os.write("\n".getBytes("utf-8"));
|
||||
os.flush();
|
||||
Thread.sleep(300);
|
||||
os.write("0123456789ABCDEF\r\n".getBytes("utf-8"));
|
||||
os.write("0\r\n".getBytes("utf-8"));
|
||||
os.write("\r\n".getBytes("utf-8"));
|
||||
os.flush();
|
||||
}
|
||||
|
||||
long duration = NanoTime.millisSince(start);
|
||||
assertThat(duration, greaterThan(500L));
|
||||
|
||||
// read the response
|
||||
String response = IO.toString(is);
|
||||
assertThat(response, startsWith("HTTP/1.1 500 "));
|
||||
assertThat(response, containsString("InterruptedIOException"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("Unstable")
|
||||
@Disabled // TODO make more stable
|
||||
public void testNoBlockingTimeoutWrite() throws Exception
|
||||
{
|
||||
startServer(new HugeResponseHandler());
|
||||
Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
OutputStream os = client.getOutputStream();
|
||||
BufferedReader is = new BufferedReader(new InputStreamReader(client.getInputStream(), StandardCharsets.ISO_8859_1), 2048);
|
||||
|
||||
os.write((
|
||||
"GET / HTTP/1.0\r\n" +
|
||||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"connection: keep-alive\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.flush();
|
||||
|
||||
// read the header
|
||||
String line = is.readLine();
|
||||
assertThat(line, startsWith("HTTP/1.1 200 OK"));
|
||||
while (line.length() != 0)
|
||||
{
|
||||
line = is.readLine();
|
||||
}
|
||||
|
||||
for (int i = 0; i < (128 * 1024); i++)
|
||||
{
|
||||
if (i % 1028 == 0)
|
||||
{
|
||||
Thread.sleep(20);
|
||||
}
|
||||
line = is.readLine();
|
||||
assertThat(line, notNullValue());
|
||||
assertEquals(1022, line.length());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("Unstable")
|
||||
@Disabled // TODO make more stable
|
||||
public void testBlockingTimeoutWrite() throws Exception
|
||||
{
|
||||
startServer(new HugeResponseHandler());
|
||||
Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
OutputStream os = client.getOutputStream();
|
||||
BufferedReader is = new BufferedReader(new InputStreamReader(client.getInputStream(), StandardCharsets.ISO_8859_1), 2048);
|
||||
|
||||
os.write((
|
||||
"GET / HTTP/1.0\r\n" +
|
||||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"connection: keep-alive\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.flush();
|
||||
|
||||
// read the header
|
||||
String line = is.readLine();
|
||||
assertThat(line, startsWith("HTTP/1.1 200 OK"));
|
||||
while (line.length() != 0)
|
||||
{
|
||||
line = is.readLine();
|
||||
}
|
||||
|
||||
long start = NanoTime.now();
|
||||
try (StacklessLogging stackless = new StacklessLogging(HttpChannelState.class, AbstractConnection.class))
|
||||
{
|
||||
for (int i = 0; i < (128 * 1024); i++)
|
||||
{
|
||||
if (i % 1028 == 0)
|
||||
{
|
||||
Thread.sleep(20);
|
||||
}
|
||||
line = is.readLine();
|
||||
if (line == null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertThat(NanoTime.millisSince(start), lessThan(20L * 128L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxIdleNoRequest() throws Exception
|
||||
{
|
||||
|
@ -490,7 +276,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
|
||||
OutputStream os = client.getOutputStream();
|
||||
long start = NanoTime.now();
|
||||
os.write("GET ".getBytes("utf-8"));
|
||||
os.write("GET ".getBytes(StandardCharsets.UTF_8));
|
||||
os.flush();
|
||||
|
||||
Thread.sleep(sleepTime);
|
||||
|
@ -559,7 +345,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
"Content-Length: 20\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
os.flush();
|
||||
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
|
@ -583,41 +369,51 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
@Test
|
||||
public void testMaxIdleDispatch() throws Exception
|
||||
{
|
||||
startServer(new EchoHandler());
|
||||
Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
|
||||
client.setSoTimeout(10000);
|
||||
InputStream is = client.getInputStream();
|
||||
assertFalse(client.isClosed());
|
||||
startServer(new EchoWholeHandler());
|
||||
|
||||
OutputStream os = client.getOutputStream();
|
||||
long start = NanoTime.now();
|
||||
os.write((
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"connection: keep-alive\r\n" +
|
||||
"Content-Length: 20\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n" +
|
||||
"1234567890").getBytes("utf-8"));
|
||||
os.flush();
|
||||
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
|
||||
{
|
||||
try
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
try (InputStream is = client.getInputStream();
|
||||
OutputStream os = client.getOutputStream())
|
||||
{
|
||||
String response = IO.toString(is);
|
||||
assertThat(response, containsString("500"));
|
||||
assertEquals(-1, is.read());
|
||||
assertFalse(client.isClosed());
|
||||
long start = NanoTime.now();
|
||||
|
||||
byte[] requestBody = "1234567890".getBytes(StandardCharsets.UTF_8);
|
||||
// We want a situation where the request says it has a body,
|
||||
// but the request hasn't sent all of it.
|
||||
int requestBodyLength = requestBody.length * 2;
|
||||
|
||||
String rawRequest = ("""
|
||||
GET / HTTP/1.1\r
|
||||
host: localhost:%d\r
|
||||
connection: keep-alive\r
|
||||
Content-Length: %d\r
|
||||
Content-Type: text/plain\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""").formatted(_serverURI.getPort(), requestBodyLength);
|
||||
|
||||
os.write(rawRequest.getBytes(StandardCharsets.UTF_8));
|
||||
os.write(requestBody);
|
||||
os.flush();
|
||||
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
{
|
||||
// We expect a 500 response to occur due to the idle timeout triggering.
|
||||
// See: ServerConnector.setIdleTimeout(long ms);
|
||||
String response = IO.toString(is);
|
||||
assertThat(response, containsString("500"));
|
||||
assertEquals(-1, is.read());
|
||||
});
|
||||
|
||||
long duration = NanoTime.millisSince(start);
|
||||
assertThat(duration + 100, greaterThanOrEqualTo(MAX_IDLE_TIME));
|
||||
assertThat(duration - 100, lessThan(maximumTestRuntime));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
long duration = NanoTime.millisSince(start);
|
||||
assertThat(duration + 100, greaterThanOrEqualTo(MAX_IDLE_TIME));
|
||||
assertThat(duration - 100, lessThan(maximumTestRuntime));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -633,7 +429,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
InputStream is = client.getInputStream();
|
||||
|
||||
String content = "Wibble\r\n";
|
||||
byte[] contentB = content.getBytes("utf-8");
|
||||
byte[] contentB = content.getBytes(StandardCharsets.UTF_8);
|
||||
os.write((
|
||||
"GET / HTTP/1.0\r\n" +
|
||||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
|
@ -641,7 +437,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
"Content-Length: " + (contentB.length * 20) + "\r\n" +
|
||||
"Content-Type: text/plain\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
os.flush();
|
||||
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
|
@ -680,7 +476,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"connection: keep-alive\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
os.flush();
|
||||
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
|
@ -712,7 +508,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
"host: localhost:" + _serverURI.getPort() + "\r\n" +
|
||||
"connection: keep-alive\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
"\r\n").getBytes(StandardCharsets.UTF_8));
|
||||
os.flush();
|
||||
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
|
@ -750,17 +546,26 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
|
||||
protected static class HugeResponseHandler extends Handler.Abstract
|
||||
{
|
||||
private final int iterations;
|
||||
|
||||
public HugeResponseHandler(int iterations)
|
||||
{
|
||||
this.iterations = iterations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(Request request, Response response, Callback callback) throws Exception
|
||||
{
|
||||
response.setStatus(200);
|
||||
byte[] buffer = new byte[128 * 1024 * 1024];
|
||||
// Create a big single buffer
|
||||
byte[] buffer = new byte[iterations * 1024 * 1024];
|
||||
Arrays.fill(buffer, (byte)'x');
|
||||
for (int i = 0; i < 128 * 1024; i++)
|
||||
// Toss in an LF after every iteration
|
||||
for (int i = 0; i < iterations * 1024; i++)
|
||||
{
|
||||
buffer[i * 1024 + 1022] = '\r';
|
||||
buffer[i * 1024 + 1023] = '\n';
|
||||
}
|
||||
// Write it as a single buffer
|
||||
response.write(true, ByteBuffer.wrap(buffer), callback);
|
||||
return true;
|
||||
}
|
||||
|
@ -784,4 +589,73 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A handler that will echo the request body to the response body, but only
|
||||
* once the entire body content has been received.
|
||||
*/
|
||||
public static class EchoWholeHandler extends Handler.Abstract
|
||||
{
|
||||
@Override
|
||||
public boolean process(Request request, Response response, Callback callback) throws Exception
|
||||
{
|
||||
long expectedContentLength = request.getHeaders().getLongField(HttpHeader.CONTENT_LENGTH);
|
||||
if (expectedContentLength <= 0)
|
||||
{
|
||||
callback.succeeded();
|
||||
return true;
|
||||
}
|
||||
|
||||
request.demand(new WholeProcess(request, response, callback));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accumulate the Request body until it's entirely received,
|
||||
* then write the body back to the response body.
|
||||
*/
|
||||
private static class WholeProcess implements Runnable
|
||||
{
|
||||
Request request;
|
||||
Response response;
|
||||
Callback callback;
|
||||
ByteBufferAccumulator bufferAccumulator;
|
||||
|
||||
public WholeProcess(Request request, Response response, Callback callback)
|
||||
{
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.callback = callback;
|
||||
this.bufferAccumulator = new ByteBufferAccumulator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Content.Chunk chunk = request.read();
|
||||
if (chunk == null)
|
||||
{
|
||||
request.demand(this);
|
||||
return;
|
||||
}
|
||||
if (chunk instanceof Content.Chunk.Error error)
|
||||
{
|
||||
callback.failed(error.getCause());
|
||||
return;
|
||||
}
|
||||
// copy buffer
|
||||
bufferAccumulator.copyBuffer(chunk.getByteBuffer().slice());
|
||||
chunk.release();
|
||||
if (chunk.isLast())
|
||||
{
|
||||
// write accumulated buffers
|
||||
response.write(true, bufferAccumulator.toByteBuffer(), callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.net.Socket;
|
|||
import java.net.SocketException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
@ -32,14 +33,12 @@ import org.eclipse.jetty.io.Connection;
|
|||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.logging.StacklessLogging;
|
||||
import org.eclipse.jetty.server.handler.DumpHandler;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.MavenPaths;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
@ -91,9 +90,9 @@ public class DetectorConnectionTest
|
|||
|
||||
private String getResponseOverSsl(String request) throws Exception
|
||||
{
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore.p12").getAbsolutePath();
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
sslContextFactory.start();
|
||||
|
||||
|
@ -140,6 +139,7 @@ public class DetectorConnectionTest
|
|||
socket.getOutputStream().write("OX".getBytes(StandardCharsets.US_ASCII));
|
||||
socket.getOutputStream().close();
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
assertThrows(SocketException.class, () -> socket.getInputStream().read());
|
||||
}
|
||||
}
|
||||
|
@ -160,6 +160,7 @@ public class DetectorConnectionTest
|
|||
socket.getOutputStream().write(" ".getBytes(StandardCharsets.US_ASCII));
|
||||
socket.getOutputStream().close();
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
assertThrows(SocketException.class, () -> socket.getInputStream().read());
|
||||
}
|
||||
}
|
||||
|
@ -175,11 +176,12 @@ public class DetectorConnectionTest
|
|||
|
||||
try (Socket socket = new Socket(_server.getURI().getHost(), _server.getURI().getPort()))
|
||||
{
|
||||
socket.getOutputStream().write(TypeUtil.fromHexString("0D0A0D0A000D0A515549540A")); // proxy V2 Preamble
|
||||
socket.getOutputStream().write(StringUtil.fromHexString("0D0A0D0A000D0A515549540A")); // proxy V2 Preamble
|
||||
Thread.sleep(100); // make sure the onFillable callback gets called
|
||||
socket.getOutputStream().write(TypeUtil.fromHexString("21")); // V2, PROXY
|
||||
socket.getOutputStream().write(StringUtil.fromHexString("21")); // V2, PROXY
|
||||
socket.getOutputStream().close();
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
assertThrows(SocketException.class, () -> socket.getInputStream().read());
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +197,7 @@ public class DetectorConnectionTest
|
|||
|
||||
try (Socket socket = new Socket(_server.getURI().getHost(), _server.getURI().getPort()))
|
||||
{
|
||||
socket.getOutputStream().write(TypeUtil.fromHexString(
|
||||
socket.getOutputStream().write(StringUtil.fromHexString(
|
||||
// proxy V2 Preamble
|
||||
"0D0A0D0A000D0A515549540A" +
|
||||
// V2, PROXY
|
||||
|
@ -207,23 +209,23 @@ public class DetectorConnectionTest
|
|||
"000C"
|
||||
));
|
||||
Thread.sleep(100); // make sure the onFillable callback gets called
|
||||
socket.getOutputStream().write(TypeUtil.fromHexString(
|
||||
socket.getOutputStream().write(StringUtil.fromHexString(
|
||||
// uint32_t src_addr; uint32_t dst_addr; uint16_t src_port; uint16_t dst_port;
|
||||
"C0A80001" // 8080
|
||||
));
|
||||
socket.getOutputStream().close();
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
assertThrows(SocketException.class, () -> socket.getInputStream().read());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // TODO
|
||||
public void testDetectingSslProxyToHttpNoSslWithProxy() throws Exception
|
||||
{
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore.p12").getAbsolutePath();
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory();
|
||||
|
@ -233,18 +235,18 @@ public class DetectorConnectionTest
|
|||
|
||||
start(detector, http);
|
||||
|
||||
String request = "PROXY TCP 1.2.3.4 5.6.7.8 111 222\r\n" +
|
||||
"GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String request = """
|
||||
PROXY TCP 1.2.3.4 5.6.7.8 111 222\r
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String response = getResponse(request);
|
||||
|
||||
assertThat(response, Matchers.containsString("HTTP/1.1 200"));
|
||||
assertThat(response, Matchers.containsString("pathInContext=/path"));
|
||||
assertThat(response, Matchers.containsString("servername=server"));
|
||||
assertThat(response, Matchers.containsString("serverport=80"));
|
||||
assertThat(response, Matchers.containsString("localname=5.6.7.8"));
|
||||
assertThat(response, Matchers.containsString("local=5.6.7.8:222"));
|
||||
assertThat(response, Matchers.containsString("remote=1.2.3.4:111"));
|
||||
}
|
||||
|
@ -252,9 +254,9 @@ public class DetectorConnectionTest
|
|||
@Test
|
||||
public void testDetectingSslProxyToHttpWithSslNoProxy() throws Exception
|
||||
{
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore.p12").getAbsolutePath();
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory();
|
||||
|
@ -264,10 +266,12 @@ public class DetectorConnectionTest
|
|||
|
||||
start(detector, http);
|
||||
|
||||
String request = "GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String request = """
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String response = getResponseOverSsl(request);
|
||||
|
||||
assertThat(response, Matchers.containsString("HTTP/1.1 200"));
|
||||
|
@ -276,9 +280,9 @@ public class DetectorConnectionTest
|
|||
@Test
|
||||
public void testDetectingSslProxyToHttpWithSslWithProxy() throws Exception
|
||||
{
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore.p12").getAbsolutePath();
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory();
|
||||
|
@ -288,11 +292,13 @@ public class DetectorConnectionTest
|
|||
|
||||
start(detector, http);
|
||||
|
||||
String request = "PROXY TCP 1.2.3.4 5.6.7.8 111 222\r\n" +
|
||||
"GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String request = """
|
||||
PROXY TCP 1.2.3.4 5.6.7.8 111 222\r
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String response = getResponseOverSsl(request);
|
||||
|
||||
// SSL matched, so the upgrade was made to HTTP which does not understand the proxy request
|
||||
|
@ -302,9 +308,9 @@ public class DetectorConnectionTest
|
|||
@Test
|
||||
public void testDetectionUnsuccessfulUpgradesToNextProtocol() throws Exception
|
||||
{
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore.p12").getAbsolutePath();
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory();
|
||||
|
@ -314,10 +320,12 @@ public class DetectorConnectionTest
|
|||
|
||||
start(detector, http);
|
||||
|
||||
String request = "GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String request = """
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String response = getResponse(request);
|
||||
|
||||
assertThat(response, Matchers.containsString("HTTP/1.1 200"));
|
||||
|
@ -326,9 +334,9 @@ public class DetectorConnectionTest
|
|||
@Test
|
||||
public void testDetectorToNextDetector() throws Exception
|
||||
{
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore.p12").getAbsolutePath();
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory();
|
||||
|
@ -339,11 +347,13 @@ public class DetectorConnectionTest
|
|||
|
||||
start(sslDetector, proxyDetector, http);
|
||||
|
||||
String request = "PROXY TCP 1.2.3.4 5.6.7.8 111 222\r\n" +
|
||||
"GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String request = """
|
||||
PROXY TCP 1.2.3.4 5.6.7.8 111 222\r
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String response = getResponseOverSsl(request);
|
||||
|
||||
// SSL matched, so the upgrade was made to proxy which itself upgraded to HTTP
|
||||
|
@ -377,10 +387,12 @@ public class DetectorConnectionTest
|
|||
|
||||
start(detector, http);
|
||||
|
||||
String request = "GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String request = """
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String response = getResponse(request);
|
||||
|
||||
assertEquals("No upgrade for you", response);
|
||||
|
@ -390,9 +402,9 @@ public class DetectorConnectionTest
|
|||
@Test
|
||||
public void testDetectorWithProxyThatHasNoNextProto() throws Exception
|
||||
{
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore.p12").getAbsolutePath();
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory();
|
||||
|
@ -402,11 +414,13 @@ public class DetectorConnectionTest
|
|||
|
||||
start(detector, http);
|
||||
|
||||
String request = "PROXY TCP 1.2.3.4 5.6.7.8 111 222\r\n" +
|
||||
"GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String request = """
|
||||
PROXY TCP 1.2.3.4 5.6.7.8 111 222\r
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String response = getResponse(request);
|
||||
|
||||
// ProxyConnectionFactory has no next protocol -> it cannot upgrade
|
||||
|
@ -416,9 +430,9 @@ public class DetectorConnectionTest
|
|||
@Test
|
||||
public void testOptionalSsl() throws Exception
|
||||
{
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore.p12").getAbsolutePath();
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory();
|
||||
|
@ -427,11 +441,12 @@ public class DetectorConnectionTest
|
|||
|
||||
start(detector, http);
|
||||
|
||||
String request =
|
||||
"GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String request = """
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String clearTextResponse = getResponse(request);
|
||||
String sslResponse = getResponseOverSsl(request);
|
||||
|
||||
|
@ -443,9 +458,9 @@ public class DetectorConnectionTest
|
|||
@Test
|
||||
public void testDetectorThatHasNoConfiguredNextProto() throws Exception
|
||||
{
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore.p12").getAbsolutePath();
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
|
||||
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString());
|
||||
|
@ -453,11 +468,12 @@ public class DetectorConnectionTest
|
|||
|
||||
start(detector);
|
||||
|
||||
String request =
|
||||
"GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String request = """
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String response = getResponse(request);
|
||||
|
||||
assertThat(response, Matchers.nullValue());
|
||||
|
@ -489,11 +505,11 @@ public class DetectorConnectionTest
|
|||
"1F90"; // 8080
|
||||
|
||||
String httpReq = """
|
||||
GET /path HTTP/1.1
|
||||
Host: server:80
|
||||
Connection: close
|
||||
|
||||
""";
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
try (StacklessLogging ignore = new StacklessLogging(DetectorConnectionFactory.class))
|
||||
{
|
||||
String response = getResponse(StringUtil.fromHexString(proxyReq), httpReq.getBytes(StandardCharsets.US_ASCII));
|
||||
|
@ -558,12 +574,13 @@ public class DetectorConnectionTest
|
|||
"3039" + // 12345
|
||||
"1F90"; // 8080
|
||||
|
||||
String httpReq =
|
||||
"GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String response = getResponse(TypeUtil.fromHexString(proxyReq), httpReq.getBytes(StandardCharsets.US_ASCII));
|
||||
String httpReq = """
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String response = getResponse(StringUtil.fromHexString(proxyReq), httpReq.getBytes(StandardCharsets.US_ASCII));
|
||||
|
||||
assertThat(response, Matchers.nullValue());
|
||||
}
|
||||
|
@ -604,11 +621,12 @@ public class DetectorConnectionTest
|
|||
|
||||
start(detector, noUpgradeTo);
|
||||
|
||||
String request =
|
||||
"GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
String request = """
|
||||
GET /path HTTP/1.1\r
|
||||
Host: server:80\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""";
|
||||
String response = getResponse(request);
|
||||
|
||||
assertThat(response, Matchers.nullValue());
|
||||
|
@ -617,9 +635,9 @@ public class DetectorConnectionTest
|
|||
@Test
|
||||
public void testGeneratedProtocolNames()
|
||||
{
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore.p12").getAbsolutePath();
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
|
||||
ProxyConnectionFactory proxy = new ProxyConnectionFactory(HttpVersion.HTTP_1_1.asString());
|
||||
|
|
|
@ -14,13 +14,11 @@
|
|||
package org.eclipse.jetty.server;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.time.Duration.ofSeconds;
|
||||
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
|
||||
|
||||
@Disabled // TODO
|
||||
public class ServerConnectorTimeoutTest extends ConnectorTimeoutTest
|
||||
{
|
||||
@BeforeEach
|
||||
|
@ -28,11 +26,11 @@ public class ServerConnectorTimeoutTest extends ConnectorTimeoutTest
|
|||
{
|
||||
ServerConnector connector = new ServerConnector(_server, 1, 1);
|
||||
connector.setIdleTimeout(MAX_IDLE_TIME);
|
||||
_server.addConnector(connector);
|
||||
initServer(connector);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartStopStart() throws Exception
|
||||
public void testStartStopStart()
|
||||
{
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
{
|
||||
|
@ -40,165 +38,4 @@ public class ServerConnectorTimeoutTest extends ConnectorTimeoutTest
|
|||
_server.start();
|
||||
});
|
||||
}
|
||||
|
||||
/* TODO
|
||||
@Test
|
||||
public void testIdleTimeoutAfterSuspend() throws Exception
|
||||
{
|
||||
_server.stop();
|
||||
SuspendHandler handler = new SuspendHandler();
|
||||
SessionHandler session = new SessionHandler();
|
||||
session.setHandler(handler);
|
||||
_server.setHandler(session);
|
||||
_server.start();
|
||||
|
||||
handler.setSuspendFor(100);
|
||||
handler.setResumeAfter(25);
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
{
|
||||
String process = process(null).toUpperCase(Locale.ENGLISH);
|
||||
assertThat(process, containsString("RESUMED"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleTimeoutAfterTimeout() throws Exception
|
||||
{
|
||||
SuspendHandler handler = new SuspendHandler();
|
||||
_server.stop();
|
||||
SessionHandler session = new SessionHandler();
|
||||
session.setHandler(handler);
|
||||
_server.setHandler(session);
|
||||
_server.start();
|
||||
|
||||
handler.setSuspendFor(50);
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
{
|
||||
String process = process(null).toUpperCase(Locale.ENGLISH);
|
||||
assertThat(process, containsString("TIMEOUT"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleTimeoutAfterComplete() throws Exception
|
||||
{
|
||||
SuspendHandler handler = new SuspendHandler();
|
||||
_server.stop();
|
||||
SessionHandler session = new SessionHandler();
|
||||
session.setHandler(handler);
|
||||
_server.setHandler(session);
|
||||
_server.start();
|
||||
|
||||
handler.setSuspendFor(100);
|
||||
handler.setCompleteAfter(25);
|
||||
assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
{
|
||||
String process = process(null).toUpperCase(Locale.ENGLISH);
|
||||
assertThat(process, containsString("COMPLETED"));
|
||||
});
|
||||
}
|
||||
|
||||
private String process(String content) throws IOException, InterruptedException
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n";
|
||||
|
||||
if (content == null)
|
||||
request += "\r\n";
|
||||
else
|
||||
request += "Content-Length: " + content.length() + "\r\n" + "\r\n" + content;
|
||||
return getResponse(request);
|
||||
}
|
||||
}
|
||||
|
||||
private String getResponse(String request) throws IOException, InterruptedException
|
||||
{
|
||||
try (Socket socket = new Socket((String)null, _connector.getLocalPort()))
|
||||
{
|
||||
socket.setSoTimeout((int)(10 * MAX_IDLE_TIME));
|
||||
socket.getOutputStream().write(request.getBytes(StandardCharsets.UTF_8));
|
||||
InputStream inputStream = socket.getInputStream();
|
||||
long start = NanoTime.now();
|
||||
String response = IO.toString(inputStream);
|
||||
assertThat(NanoTime.millisSince(start), greaterThanOrEqualTo(MAX_IDLE_TIME - 100L));
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpWriteIdleTimeout() throws Exception
|
||||
{
|
||||
_httpConfiguration.setIdleTimeout(500);
|
||||
configureServer(new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
IO.copy(request.getInputStream(), response.getOutputStream());
|
||||
}
|
||||
});
|
||||
Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
final OutputStream os = client.getOutputStream();
|
||||
final InputStream is = client.getInputStream();
|
||||
final StringBuilder response = new StringBuilder();
|
||||
|
||||
CompletableFuture<Void> responseFuture = CompletableFuture.runAsync(() ->
|
||||
{
|
||||
try (InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8))
|
||||
{
|
||||
int c;
|
||||
while ((c = reader.read()) != -1)
|
||||
{
|
||||
response.append((char)c);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Valid path (as connection is forcibly closed)
|
||||
// t.printStackTrace(System.err);
|
||||
}
|
||||
});
|
||||
|
||||
CompletableFuture<Void> requestFuture = CompletableFuture.runAsync(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
os.write((
|
||||
"POST /echo HTTP/1.0\r\n" +
|
||||
"host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
|
||||
"content-type: text/plain; charset=utf-8\r\n" +
|
||||
"content-length: 20\r\n" +
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.flush();
|
||||
|
||||
os.write("123456789\n".getBytes("utf-8"));
|
||||
os.flush();
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
os.write("=========\n".getBytes("utf-8"));
|
||||
os.flush();
|
||||
}
|
||||
catch (InterruptedException | IOException e)
|
||||
{
|
||||
// Valid path, as write of second half of content can fail
|
||||
// e.printStackTrace(System.err);
|
||||
}
|
||||
});
|
||||
|
||||
try (StacklessLogging ignore = new StacklessLogging(HttpChannel.class))
|
||||
{
|
||||
requestFuture.get(2, TimeUnit.SECONDS);
|
||||
responseFuture.get(3, TimeUnit.SECONDS);
|
||||
|
||||
assertThat(response.toString(), containsString(" 500 "));
|
||||
assertThat(response.toString(), not(containsString("=========")));
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -13,43 +13,37 @@
|
|||
|
||||
package org.eclipse.jetty.server.ssl;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyStore;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import org.eclipse.jetty.server.ConnectorTimeoutTest;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.toolchain.test.MavenPaths;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
|
||||
@Disabled // TODO
|
||||
public class SslSelectChannelTimeoutTest extends ConnectorTimeoutTest
|
||||
public class ServerConnectorSslTimeoutTest extends ConnectorTimeoutTest
|
||||
{
|
||||
static SSLContext __sslContext;
|
||||
|
||||
@Override
|
||||
protected Socket newSocket(String host, int port) throws Exception
|
||||
{
|
||||
return __sslContext.getSocketFactory().createSocket(host, port);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void init() throws Exception
|
||||
{
|
||||
String keystorePath = System.getProperty("basedir", ".") + "/src/test/resources/keystore.p12";
|
||||
Path keystorePath = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystorePath);
|
||||
sslContextFactory.setKeyStorePath(keystorePath.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
ServerConnector connector = new ServerConnector(_server, 1, 1, sslContextFactory);
|
||||
connector.setIdleTimeout(MAX_IDLE_TIME); //250 msec max idle
|
||||
connector.setIdleTimeout(MAX_IDLE_TIME);
|
||||
_server.addConnector(connector);
|
||||
|
||||
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
try (InputStream stream = new FileInputStream(keystorePath))
|
||||
try (InputStream stream = Files.newInputStream(keystorePath))
|
||||
{
|
||||
keystore.load(stream, "storepwd".toCharArray());
|
||||
}
|
||||
|
@ -58,4 +52,10 @@ public class SslSelectChannelTimeoutTest extends ConnectorTimeoutTest
|
|||
__sslContext = SSLContext.getInstance("SSL");
|
||||
__sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Socket newSocket(String host, int port) throws Exception
|
||||
{
|
||||
return __sslContext.getSocketFactory().createSocket(host, port);
|
||||
}
|
||||
}
|
|
@ -13,144 +13,150 @@
|
|||
|
||||
package org.eclipse.jetty.server.ssl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.MavenPaths;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static java.time.Duration.ofSeconds;
|
||||
|
||||
@Tag("Unstable")
|
||||
@Disabled
|
||||
public class SlowClientsTest
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SlowClientsTest.class);
|
||||
private Server server;
|
||||
private SslContextFactory.Server sslContextFactory;
|
||||
|
||||
@BeforeEach
|
||||
public void initServer() throws Exception
|
||||
{
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
server = new Server();
|
||||
ServerConnector connector = new ServerConnector(server, 1, 1, sslContextFactory);
|
||||
connector.setPort(0);
|
||||
server.addConnector(connector);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopServer()
|
||||
{
|
||||
LifeCycle.stop(server);
|
||||
}
|
||||
|
||||
public void startServer(Handler handler) throws Exception
|
||||
{
|
||||
server.setHandler(handler);
|
||||
server.start();
|
||||
}
|
||||
|
||||
public Socket newSocketToServer() throws IOException
|
||||
{
|
||||
URI serverURI = server.getURI();
|
||||
SSLContext sslContext = sslContextFactory.getSslContext();
|
||||
return sslContext.getSocketFactory().createSocket(serverURI.getHost(), serverURI.getPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSlowClientsWithSmallThreadPool() throws Exception
|
||||
{
|
||||
File keystore = MavenTestingUtils.getTestResourceFile("keystore.p12");
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystore.getAbsolutePath());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
final int maxThreads = 6;
|
||||
final int contentLength = 8 * 1024 * 1024; // 8MB
|
||||
|
||||
int maxThreads = 6;
|
||||
int contentLength = 8 * 1024 * 1024;
|
||||
QueuedThreadPool serverThreads = new QueuedThreadPool(maxThreads);
|
||||
serverThreads.setDetailedDump(true);
|
||||
Server server = new Server(serverThreads);
|
||||
|
||||
try
|
||||
((QueuedThreadPool)server.getThreadPool()).setMaxThreads(maxThreads);
|
||||
startServer(new Handler.Abstract()
|
||||
{
|
||||
ServerConnector connector = new ServerConnector(server, 1, 1, sslContextFactory);
|
||||
connector.setPort(8888);
|
||||
server.addConnector(connector);
|
||||
server.setHandler(new Handler.Abstract.NonBlocking()
|
||||
@Override
|
||||
public boolean process(Request request, Response response, Callback callback)
|
||||
{
|
||||
@Override
|
||||
public boolean process(Request request, Response response, Callback callback)
|
||||
{
|
||||
LOG.info("SERVING {}", request);
|
||||
// Write some big content.
|
||||
response.write(true, BufferUtil.toBuffer(new byte[contentLength]), new Callback()
|
||||
{
|
||||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
callback.succeeded();
|
||||
LOG.info("SERVED {}", request);
|
||||
}
|
||||
response.write(true, BufferUtil.toBuffer(contentLength), callback);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
callback.failed(x);
|
||||
}
|
||||
}
|
||||
);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
server.start();
|
||||
|
||||
SSLContext sslContext = sslContextFactory.getSslContext();
|
||||
|
||||
Assertions.assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
Assertions.assertTimeoutPreemptively(ofSeconds(10), () ->
|
||||
{
|
||||
// Twice as many clients as threads in thread pool.
|
||||
CompletableFuture<?>[] futures = new CompletableFuture[2 * maxThreads];
|
||||
ExecutorService executor = Executors.newFixedThreadPool(futures.length);
|
||||
for (int i = 0; i < futures.length; i++)
|
||||
{
|
||||
CompletableFuture<?>[] futures = new CompletableFuture[2 * maxThreads];
|
||||
ExecutorService executor = Executors.newFixedThreadPool(futures.length);
|
||||
for (int i = 0; i < futures.length; i++)
|
||||
int k = i;
|
||||
futures[i] = CompletableFuture.runAsync(() ->
|
||||
{
|
||||
int k = i;
|
||||
futures[i] = CompletableFuture.runAsync(() ->
|
||||
try (Socket socket = newSocketToServer())
|
||||
{
|
||||
try (SSLSocket socket = (SSLSocket)sslContext.getSocketFactory().createSocket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
socket.setSoTimeout(contentLength / 1024);
|
||||
OutputStream output = socket.getOutputStream();
|
||||
String target = "/" + k;
|
||||
String request = "GET " + target + " HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n";
|
||||
output.write(request.getBytes(StandardCharsets.UTF_8));
|
||||
output.flush();
|
||||
socket.setSoTimeout(contentLength / 1024);
|
||||
OutputStream output = socket.getOutputStream();
|
||||
String target = "/" + k;
|
||||
String rawRequest = """
|
||||
GET %s HTTP/1.1\r
|
||||
Host: localhost\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""".formatted(target);
|
||||
output.write(rawRequest.getBytes(StandardCharsets.UTF_8));
|
||||
output.flush();
|
||||
|
||||
while (serverThreads.getIdleThreads() > 0)
|
||||
{
|
||||
Thread.sleep(50);
|
||||
}
|
||||
int delayReadCount = 10;
|
||||
|
||||
InputStream input = socket.getInputStream();
|
||||
while (true)
|
||||
InputStream input = socket.getInputStream();
|
||||
while (true)
|
||||
{
|
||||
int read = input.read();
|
||||
if (read < 0)
|
||||
break;
|
||||
// simulate a slow client (for a bit).
|
||||
// we are testing that the server thread pool doesn't misbehave
|
||||
// in this scenario, where there are more clients active than server threads.
|
||||
if (delayReadCount > 0)
|
||||
{
|
||||
int read = input.read();
|
||||
if (read < 0)
|
||||
break;
|
||||
TimeUnit.MILLISECONDS.sleep(200);
|
||||
delayReadCount--;
|
||||
}
|
||||
LOG.info("FINISHED {}", target);
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
throw new UncheckedIOException(x);
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
throw new UncheckedIOException(new InterruptedIOException());
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
CompletableFuture.allOf(futures).join();
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
LOG.info("FINISHED {}", target);
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
throw new UncheckedIOException(x);
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
throw new UncheckedIOException(new InterruptedIOException());
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
CompletableFuture.allOf(futures).join();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
|
||||
package org.eclipse.jetty.server.ssl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -29,6 +29,8 @@ import javax.net.ssl.SSLParameters;
|
|||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
|
@ -40,6 +42,7 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.SocketCustomizationListener;
|
||||
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||
import org.eclipse.jetty.toolchain.test.MavenPaths;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
|
@ -47,15 +50,15 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
|
|||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@Disabled // TODO Fix?
|
||||
public class SslConnectionFactoryTest
|
||||
{
|
||||
private Server _server;
|
||||
|
@ -65,11 +68,7 @@ public class SslConnectionFactoryTest
|
|||
@BeforeEach
|
||||
public void before() throws Exception
|
||||
{
|
||||
String keystorePath = "src/test/resources/keystore.p12";
|
||||
File keystoreFile = new File(keystorePath);
|
||||
if (!keystoreFile.exists())
|
||||
throw new FileNotFoundException(keystoreFile.getAbsolutePath());
|
||||
|
||||
Path keystoreFile = MavenPaths.findTestResourceFile("keystore.p12");
|
||||
_server = new Server();
|
||||
|
||||
HttpConfiguration httpConfig = new HttpConfiguration();
|
||||
|
@ -78,7 +77,7 @@ public class SslConnectionFactoryTest
|
|||
httpConfig.setOutputBufferSize(32768);
|
||||
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.getAbsolutePath());
|
||||
sslContextFactory.setKeyStorePath(keystoreFile.toString());
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
|
||||
SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString());
|
||||
|
@ -116,15 +115,15 @@ public class SslConnectionFactoryTest
|
|||
@Test
|
||||
public void testConnect() throws Exception
|
||||
{
|
||||
String response = getResponse("127.0.0.1", null);
|
||||
assertThat(response, Matchers.containsString("host=127.0.0.1"));
|
||||
HttpTester.Response response = getResponse("127.0.0.1", null);
|
||||
assertThat(response.getContent(), containsString("host=127.0.0.1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSNIConnect() throws Exception
|
||||
{
|
||||
String response = getResponse("localhost", "localhost", "localhost");
|
||||
assertThat(response, Matchers.containsString("host=localhost"));
|
||||
HttpTester.Response response = getResponse("localhost", "localhost", "localhost");
|
||||
assertThat(response.getContent(), containsString("host=localhost"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -174,13 +173,13 @@ public class SslConnectionFactoryTest
|
|||
}
|
||||
});
|
||||
|
||||
String response = getResponse("127.0.0.1", null);
|
||||
assertThat(response, Matchers.containsString("host=127.0.0.1"));
|
||||
HttpTester.Response response = getResponse("127.0.0.1", null);
|
||||
assertThat(response.getContent(), containsString("host=127.0.0.1"));
|
||||
|
||||
assertEquals("customize connector class org.eclipse.jetty.io.ssl.SslConnection,false", history.poll());
|
||||
assertEquals("customize ssl class org.eclipse.jetty.io.ssl.SslConnection,false", history.poll());
|
||||
assertEquals("customize connector class org.eclipse.jetty.server.HttpConnection,true", history.poll());
|
||||
assertEquals("customize http class org.eclipse.jetty.server.HttpConnection,true", history.poll());
|
||||
assertEquals("customize connector class org.eclipse.jetty.server.internal.HttpConnection,true", history.poll());
|
||||
assertEquals("customize http class org.eclipse.jetty.server.internal.HttpConnection,true", history.poll());
|
||||
assertEquals(0, history.size());
|
||||
}
|
||||
|
||||
|
@ -192,45 +191,58 @@ public class SslConnectionFactoryTest
|
|||
assertThrows(IllegalStateException.class, () -> _server.start());
|
||||
}
|
||||
|
||||
private String getResponse(String host, String cn) throws Exception
|
||||
private HttpTester.Response getResponse(String host, String cn) throws Exception
|
||||
{
|
||||
String response = getResponse(host, host, cn);
|
||||
assertThat(response, Matchers.startsWith("HTTP/1.1 200 OK"));
|
||||
assertThat(response, Matchers.containsString("url=/ctx/path"));
|
||||
HttpTester.Response response = getResponse(host, host, cn);
|
||||
assertThat(response.getStatus(), is(HttpStatus.OK_200));
|
||||
assertThat(response.getContent(), containsString("url=https://%s:%d/ctx/path".formatted(host, _port)));
|
||||
return response;
|
||||
}
|
||||
|
||||
private String getResponse(String sniHost, String reqHost, String cn) throws Exception
|
||||
private HttpTester.Response getResponse(String sniHost, String reqHost, String cn) throws Exception
|
||||
{
|
||||
SslContextFactory clientContextFactory = new SslContextFactory.Client(true);
|
||||
clientContextFactory.start();
|
||||
SSLSocketFactory factory = clientContextFactory.getSslContext().getSocketFactory();
|
||||
|
||||
SSLSocket sslSocket = (SSLSocket)factory.createSocket("127.0.0.1", _port);
|
||||
|
||||
if (cn != null)
|
||||
try (SSLSocket sslSocket = (SSLSocket)factory.createSocket("127.0.0.1", _port))
|
||||
{
|
||||
SNIHostName serverName = new SNIHostName(sniHost);
|
||||
List<SNIServerName> serverNames = new ArrayList<>();
|
||||
serverNames.add(serverName);
|
||||
if (cn != null)
|
||||
{
|
||||
SNIHostName serverName = new SNIHostName(sniHost);
|
||||
List<SNIServerName> serverNames = new ArrayList<>();
|
||||
serverNames.add(serverName);
|
||||
|
||||
SSLParameters params = sslSocket.getSSLParameters();
|
||||
params.setServerNames(serverNames);
|
||||
sslSocket.setSSLParameters(params);
|
||||
SSLParameters params = sslSocket.getSSLParameters();
|
||||
params.setServerNames(serverNames);
|
||||
sslSocket.setSSLParameters(params);
|
||||
}
|
||||
sslSocket.startHandshake();
|
||||
|
||||
if (cn != null)
|
||||
{
|
||||
X509Certificate cert = ((X509Certificate)sslSocket.getSession().getPeerCertificates()[0]);
|
||||
assertThat(cert.getSubjectX500Principal().getName("CANONICAL"), Matchers.startsWith("cn=" + cn));
|
||||
}
|
||||
|
||||
try (OutputStream os = sslSocket.getOutputStream();
|
||||
InputStream in = sslSocket.getInputStream())
|
||||
{
|
||||
String rawRequest = """
|
||||
GET /ctx/path HTTP/1.1\r
|
||||
Host: %s:%d\r
|
||||
Connection: close\r
|
||||
\r
|
||||
""".formatted(reqHost, _port);
|
||||
|
||||
os.write(rawRequest.getBytes(StandardCharsets.UTF_8));
|
||||
String rawResponse = IO.toString(in);
|
||||
return HttpTester.parseResponse(rawResponse);
|
||||
}
|
||||
}
|
||||
sslSocket.startHandshake();
|
||||
|
||||
if (cn != null)
|
||||
finally
|
||||
{
|
||||
X509Certificate cert = ((X509Certificate)sslSocket.getSession().getPeerCertificates()[0]);
|
||||
assertThat(cert.getSubjectX500Principal().getName("CANONICAL"), Matchers.startsWith("cn=" + cn));
|
||||
clientContextFactory.stop();
|
||||
}
|
||||
|
||||
sslSocket.getOutputStream().write(("GET /ctx/path HTTP/1.0\r\nHost: " + reqHost + ":" + _port + "\r\n\r\n").getBytes(StandardCharsets.ISO_8859_1));
|
||||
String response = IO.toString(sslSocket.getInputStream());
|
||||
|
||||
sslSocket.close();
|
||||
clientContextFactory.stop();
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue