Merged branch 'jetty-10.0.x' into 'jetty-10.0.x-3162_jetty_servlet_api'.
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
commit
cd488c2d7d
|
@ -37,6 +37,7 @@ import org.eclipse.jetty.client.api.Result;
|
|||
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.QuotedCSV;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -309,6 +310,8 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
|
|||
@Override
|
||||
public void onSuccess(Response response)
|
||||
{
|
||||
int status = response.getStatus();
|
||||
if (HttpStatus.isSuccess(status) || HttpStatus.isRedirection(status))
|
||||
client.getAuthenticationStore().addAuthenticationResult(authenticationResult);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,6 +103,7 @@ public class BasicAuthentication extends AbstractAuthentication
|
|||
@Override
|
||||
public void apply(Request request)
|
||||
{
|
||||
if (!request.getHeaders().contains(header, value))
|
||||
request.header(header, value);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,13 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.client;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalToIgnoringCase;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
@ -38,7 +31,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.IntFunction;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -74,6 +67,13 @@ import org.junit.jupiter.api.Test;
|
|||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalToIgnoringCase;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
||||
{
|
||||
private String realm = "TestRealm";
|
||||
|
@ -232,7 +232,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
private final AtomicInteger requests = new AtomicInteger();
|
||||
|
||||
@Override
|
||||
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
if (requests.incrementAndGet() == 1)
|
||||
|
@ -272,7 +272,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
startBasic(scenario, new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
if (request.getRequestURI().endsWith("/redirect"))
|
||||
|
@ -369,6 +369,9 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
ContentResponse response = request.timeout(5, TimeUnit.SECONDS).send();
|
||||
assertNotNull(response);
|
||||
assertEquals(401, response.getStatus());
|
||||
|
||||
Authentication.Result authenticationResult = authenticationStore.findAuthenticationResult(uri);
|
||||
assertNull(authenticationResult);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
@ -401,15 +404,11 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
.scheme(scenario.getScheme())
|
||||
.path("/secure")
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send(new Response.CompleteListener()
|
||||
{
|
||||
@Override
|
||||
public void onComplete(Result result)
|
||||
.send(result ->
|
||||
{
|
||||
assertTrue(result.isFailed());
|
||||
assertEquals(cause, result.getFailure().getMessage());
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(latch.await(5, TimeUnit.SECONDS));
|
||||
|
@ -480,7 +479,6 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
assertTrue(resultLatch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSource(ScenarioProvider.class)
|
||||
public void test_RequestFailsAfterResponse(Scenario scenario) throws Exception
|
||||
|
@ -488,8 +486,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
startBasic(scenario, new EmptyServerHandler()
|
||||
{
|
||||
@Override
|
||||
protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException, ServletException
|
||||
protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
IO.readBytes(jettyRequest.getInputStream());
|
||||
}
|
||||
|
@ -543,8 +540,9 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
{
|
||||
authLatch.await();
|
||||
}
|
||||
catch(InterruptedException e)
|
||||
{}
|
||||
catch(InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
|
||||
// Trigger request failure.
|
||||
throw new RuntimeException();
|
||||
|
@ -636,28 +634,27 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
|
||||
HeaderInfo headerInfo = aph.getHeaderInfo("Digest realm=\"thermostat\", qop=\"auth\", nonce=\"1523430383\"").get(0);
|
||||
assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfo.getParameter("qop").equals("auth"));
|
||||
assertTrue(headerInfo.getParameter("realm").equals("thermostat"));
|
||||
assertTrue(headerInfo.getParameter("nonce").equals("1523430383"));
|
||||
assertEquals("auth", headerInfo.getParameter("qop"));
|
||||
assertEquals("thermostat", headerInfo.getParameter("realm"));
|
||||
assertEquals("1523430383", headerInfo.getParameter("nonce"));
|
||||
|
||||
headerInfo = aph.getHeaderInfo("Digest qop=\"auth\", realm=\"thermostat\", nonce=\"1523430383\"").get(0);
|
||||
assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfo.getParameter("qop").equals("auth"));
|
||||
assertTrue(headerInfo.getParameter("realm").equals("thermostat"));
|
||||
assertTrue(headerInfo.getParameter("nonce").equals("1523430383"));
|
||||
assertEquals("auth", headerInfo.getParameter("qop"));
|
||||
assertEquals("thermostat", headerInfo.getParameter("realm"));
|
||||
assertEquals("1523430383", headerInfo.getParameter("nonce"));
|
||||
|
||||
headerInfo = aph.getHeaderInfo("Digest qop=\"auth\", nonce=\"1523430383\", realm=\"thermostat\"").get(0);
|
||||
assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfo.getParameter("qop").equals("auth"));
|
||||
assertTrue(headerInfo.getParameter("realm").equals("thermostat"));
|
||||
assertTrue(headerInfo.getParameter("nonce").equals("1523430383"));
|
||||
assertEquals("auth", headerInfo.getParameter("qop"));
|
||||
assertEquals("thermostat", headerInfo.getParameter("realm"));
|
||||
assertEquals("1523430383", headerInfo.getParameter("nonce"));
|
||||
|
||||
headerInfo = aph.getHeaderInfo("Digest qop=\"auth\", nonce=\"1523430383\"").get(0);
|
||||
assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfo.getParameter("qop").equals("auth"));
|
||||
assertTrue(headerInfo.getParameter("realm") == null);
|
||||
assertTrue(headerInfo.getParameter("nonce").equals("1523430383"));
|
||||
|
||||
assertEquals("auth", headerInfo.getParameter("qop"));
|
||||
assertNull(headerInfo.getParameter("realm"));
|
||||
assertEquals("1523430383", headerInfo.getParameter("nonce"));
|
||||
|
||||
// test multiple authentications
|
||||
List<HeaderInfo> headerInfoList = aph.getHeaderInfo("Digest qop=\"auth\", realm=\"thermostat\", nonce=\"1523430383\", "
|
||||
|
@ -666,34 +663,34 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
+ "Digest qop=\"auth4\", nonce=\"3526435321\"");
|
||||
|
||||
assertTrue(headerInfoList.get(0).getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfoList.get(0).getParameter("qop").equals("auth"));
|
||||
assertTrue(headerInfoList.get(0).getParameter("realm").equals("thermostat"));
|
||||
assertTrue(headerInfoList.get(0).getParameter("nonce").equals("1523430383"));
|
||||
assertEquals("auth", headerInfoList.get(0).getParameter("qop"));
|
||||
assertEquals("thermostat", headerInfoList.get(0).getParameter("realm"));
|
||||
assertEquals("1523430383", headerInfoList.get(0).getParameter("nonce"));
|
||||
|
||||
assertTrue(headerInfoList.get(1).getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfoList.get(1).getParameter("qop").equals("auth2"));
|
||||
assertTrue(headerInfoList.get(1).getParameter("realm").equals("thermostat2"));
|
||||
assertTrue(headerInfoList.get(1).getParameter("nonce").equals("4522530354"));
|
||||
assertEquals("auth2", headerInfoList.get(1).getParameter("qop"));
|
||||
assertEquals("thermostat2", headerInfoList.get(1).getParameter("realm"));
|
||||
assertEquals("4522530354", headerInfoList.get(1).getParameter("nonce"));
|
||||
|
||||
assertTrue(headerInfoList.get(2).getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfoList.get(2).getParameter("qop").equals("auth3"));
|
||||
assertTrue(headerInfoList.get(2).getParameter("realm").equals("thermostat3"));
|
||||
assertTrue(headerInfoList.get(2).getParameter("nonce").equals("9523570528"));
|
||||
assertEquals("auth3", headerInfoList.get(2).getParameter("qop"));
|
||||
assertEquals("thermostat3", headerInfoList.get(2).getParameter("realm"));
|
||||
assertEquals("9523570528", headerInfoList.get(2).getParameter("nonce"));
|
||||
|
||||
assertTrue(headerInfoList.get(3).getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfoList.get(3).getParameter("qop").equals("auth4"));
|
||||
assertTrue(headerInfoList.get(3).getParameter("realm") == null);
|
||||
assertTrue(headerInfoList.get(3).getParameter("nonce").equals("3526435321"));
|
||||
assertEquals("auth4", headerInfoList.get(3).getParameter("qop"));
|
||||
assertNull(headerInfoList.get(3).getParameter("realm"));
|
||||
assertEquals("3526435321", headerInfoList.get(3).getParameter("nonce"));
|
||||
|
||||
List<HeaderInfo> headerInfos = aph.getHeaderInfo("Newauth realm=\"apps\", type=1, title=\"Login to \\\"apps\\\"\", Basic realm=\"simple\"");
|
||||
assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Newauth"));
|
||||
assertTrue(headerInfos.get(0).getParameter("realm").equals("apps"));
|
||||
assertTrue(headerInfos.get(0).getParameter("type").equals("1"));
|
||||
assertEquals("apps", headerInfos.get(0).getParameter("realm"));
|
||||
assertEquals("1", headerInfos.get(0).getParameter("type"));
|
||||
|
||||
assertEquals(headerInfos.get(0).getParameter("title"),"Login to \"apps\"");
|
||||
|
||||
assertTrue(headerInfos.get(1).getType().equalsIgnoreCase("Basic"));
|
||||
assertTrue(headerInfos.get(1).getParameter("realm").equals("simple"));
|
||||
assertEquals("simple", headerInfos.get(1).getParameter("realm"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -702,7 +699,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
|
||||
HeaderInfo headerInfo = aph.getHeaderInfo("Scheme").get(0);
|
||||
assertTrue(headerInfo.getType().equalsIgnoreCase("Scheme"));
|
||||
assertTrue(headerInfo.getParameter("realm") == null);
|
||||
assertNull(headerInfo.getParameter("realm"));
|
||||
|
||||
List<HeaderInfo> headerInfos = aph.getHeaderInfo("Scheme1 , Scheme2 , Scheme3");
|
||||
assertEquals(3, headerInfos.size());
|
||||
|
@ -712,51 +709,49 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
|
||||
headerInfo = aph.getHeaderInfo("Scheme name=\"value\", other=\"value2\"").get(0);
|
||||
assertTrue(headerInfo.getType().equalsIgnoreCase("Scheme"));
|
||||
assertTrue(headerInfo.getParameter("name").equals("value"));
|
||||
assertTrue(headerInfo.getParameter("other").equals("value2"));
|
||||
assertEquals("value", headerInfo.getParameter("name"));
|
||||
assertEquals("value2", headerInfo.getParameter("other"));
|
||||
|
||||
headerInfo = aph.getHeaderInfo("Scheme name = value , other = \"value2\" ").get(0);
|
||||
assertTrue(headerInfo.getType().equalsIgnoreCase("Scheme"));
|
||||
assertTrue(headerInfo.getParameter("name").equals("value"));
|
||||
assertTrue(headerInfo.getParameter("other").equals("value2"));
|
||||
assertEquals("value", headerInfo.getParameter("name"));
|
||||
assertEquals("value2", headerInfo.getParameter("other"));
|
||||
|
||||
headerInfos = aph.getHeaderInfo(", , , , ,,,Scheme name=value, ,,Scheme2 name=value2,, ,,");
|
||||
assertEquals(headerInfos.size(), 2);
|
||||
assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Scheme"));
|
||||
assertTrue(headerInfos.get(0).getParameter("nAmE").equals("value"));
|
||||
assertEquals("value", headerInfos.get(0).getParameter("nAmE"));
|
||||
assertTrue(headerInfos.get(1).getType().equalsIgnoreCase("Scheme2"));
|
||||
|
||||
headerInfos = aph.getHeaderInfo("Scheme name=value, Scheme2 name=value2");
|
||||
assertEquals(headerInfos.size(), 2);
|
||||
assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Scheme"));
|
||||
assertTrue(headerInfos.get(0).getParameter("nAmE").equals("value"));
|
||||
assertEquals("value", headerInfos.get(0).getParameter("nAmE"));
|
||||
assertThat(headerInfos.get(1).getType(), equalToIgnoringCase("Scheme2"));
|
||||
|
||||
assertTrue(headerInfos.get(1).getParameter("nAmE").equals("value2"));
|
||||
assertEquals("value2", headerInfos.get(1).getParameter("nAmE"));
|
||||
|
||||
headerInfos = aph.getHeaderInfo("Scheme , ,, ,, name=value, Scheme2 name=value2");
|
||||
assertEquals(headerInfos.size(), 2);
|
||||
assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Scheme"));
|
||||
assertTrue(headerInfos.get(0).getParameter("name").equals("value"));
|
||||
assertEquals("value", headerInfos.get(0).getParameter("name"));
|
||||
assertTrue(headerInfos.get(1).getType().equalsIgnoreCase("Scheme2"));
|
||||
assertTrue(headerInfos.get(1).getParameter("name").equals("value2"));
|
||||
assertEquals("value2", headerInfos.get(1).getParameter("name"));
|
||||
|
||||
//Negotiate with base64 Content
|
||||
headerInfo = aph.getHeaderInfo("Negotiate TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFAs4OAAAADw==").get(0);
|
||||
assertTrue(headerInfo.getType().equalsIgnoreCase("Negotiate"));
|
||||
assertTrue(headerInfo.getBase64().equals("TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFAs4OAAAADw=="));
|
||||
assertEquals("TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFAs4OAAAADw==", headerInfo.getBase64());
|
||||
|
||||
headerInfos = aph.getHeaderInfo("Negotiate TlRMTVNTUAABAAAAAAAAAFAs4OAAAADw==, "
|
||||
+ "Negotiate YIIJvwYGKwYBBQUCoIIJszCCCa+gJDAi=");
|
||||
assertTrue(headerInfos.get(0).getType().equalsIgnoreCase("Negotiate"));
|
||||
assertTrue(headerInfos.get(0).getBase64().equals("TlRMTVNTUAABAAAAAAAAAFAs4OAAAADw=="));
|
||||
assertEquals("TlRMTVNTUAABAAAAAAAAAFAs4OAAAADw==", headerInfos.get(0).getBase64());
|
||||
|
||||
assertTrue(headerInfos.get(1).getType().equalsIgnoreCase("Negotiate"));
|
||||
assertTrue(headerInfos.get(1).getBase64().equals("YIIJvwYGKwYBBQUCoIIJszCCCa+gJDAi="));
|
||||
assertEquals("YIIJvwYGKwYBBQUCoIIJszCCCa+gJDAi=", headerInfos.get(1).getBase64());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testEqualsInParam()
|
||||
{
|
||||
|
@ -765,10 +760,9 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
|
||||
headerInfo = aph.getHeaderInfo("Digest realm=\"=the=rmo=stat=\", qop=\"=a=u=t=h=\", nonce=\"=1523430383=\"").get(0);
|
||||
assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfo.getParameter("qop").equals("=a=u=t=h="));
|
||||
assertTrue(headerInfo.getParameter("realm").equals("=the=rmo=stat="));
|
||||
assertTrue(headerInfo.getParameter("nonce").equals("=1523430383="));
|
||||
|
||||
assertEquals("=a=u=t=h=", headerInfo.getParameter("qop"));
|
||||
assertEquals("=the=rmo=stat=", headerInfo.getParameter("realm"));
|
||||
assertEquals("=1523430383=", headerInfo.getParameter("nonce"));
|
||||
|
||||
// test multiple authentications
|
||||
List<HeaderInfo> headerInfoList = aph.getHeaderInfo("Digest qop=\"=au=th=\", realm=\"=ther=mostat=\", nonce=\"=152343=0383=\", "
|
||||
|
@ -776,23 +770,23 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
+ "Digest qop=\"auth3=\", nonce=\"9523570528=\", realm=\"thermostat3=\", ");
|
||||
|
||||
assertTrue(headerInfoList.get(0).getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfoList.get(0).getParameter("qop").equals("=au=th="));
|
||||
assertTrue(headerInfoList.get(0).getParameter("realm").equals("=ther=mostat="));
|
||||
assertTrue(headerInfoList.get(0).getParameter("nonce").equals("=152343=0383="));
|
||||
assertEquals("=au=th=", headerInfoList.get(0).getParameter("qop"));
|
||||
assertEquals("=ther=mostat=", headerInfoList.get(0).getParameter("realm"));
|
||||
assertEquals("=152343=0383=", headerInfoList.get(0).getParameter("nonce"));
|
||||
|
||||
assertTrue(headerInfoList.get(1).getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfoList.get(1).getParameter("qop").equals("=auth2"));
|
||||
assertTrue(headerInfoList.get(1).getParameter("realm").equals("=thermostat2"));
|
||||
assertTrue(headerInfoList.get(1).getParameter("nonce").equals("=4522530354"));
|
||||
assertEquals("=auth2", headerInfoList.get(1).getParameter("qop"));
|
||||
assertEquals("=thermostat2", headerInfoList.get(1).getParameter("realm"));
|
||||
assertEquals("=4522530354", headerInfoList.get(1).getParameter("nonce"));
|
||||
|
||||
assertTrue(headerInfoList.get(2).getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfoList.get(2).getParameter("qop").equals("auth3="));
|
||||
assertTrue(headerInfoList.get(2).getParameter("realm").equals("thermostat3="));
|
||||
assertTrue(headerInfoList.get(2).getParameter("nonce").equals("9523570528="));
|
||||
assertEquals("auth3=", headerInfoList.get(2).getParameter("qop"));
|
||||
assertEquals("thermostat3=", headerInfoList.get(2).getParameter("realm"));
|
||||
assertEquals("9523570528=", headerInfoList.get(2).getParameter("nonce"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleChallangeLooksLikeMultipleChallenge()
|
||||
public void testSingleChallengeLooksLikeMultipleChallenges()
|
||||
{
|
||||
AuthenticationProtocolHandler aph = new WWWAuthenticationProtocolHandler(client);
|
||||
List<HeaderInfo> headerInfoList = aph.getHeaderInfo("Digest param=\",f \"");
|
||||
|
@ -803,8 +797,8 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
|
|||
|
||||
HeaderInfo headerInfo = headerInfoList.get(0);
|
||||
assertTrue(headerInfo.getType().equalsIgnoreCase("Digest"));
|
||||
assertTrue(headerInfo.getParameter("qop").equals(",Digest realm=hello"));
|
||||
assertTrue(headerInfo.getParameter("realm").equals("thermostat"));
|
||||
assertEquals(",Digest realm=hello", headerInfo.getParameter("qop"));
|
||||
assertEquals("thermostat", headerInfo.getParameter("realm"));
|
||||
assertEquals(headerInfo.getParameter("nonce"), "1523430383=");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.client;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -41,6 +39,8 @@ import org.eclipse.jetty.util.B64Code;
|
|||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class HttpClientProxyTest extends AbstractHttpClientServerTest
|
||||
{
|
||||
@ParameterizedTest
|
||||
|
@ -315,7 +315,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest
|
|||
assertEquals(status, response1.getStatus());
|
||||
assertEquals(3, requests.get());
|
||||
|
||||
// Make again the request, authentication is cached, expect 204.
|
||||
// Make again the request, only the server authentication is cached, expect 407 + 204.
|
||||
requests.set(0);
|
||||
ContentResponse response2 = client.newRequest(serverHost, serverPort)
|
||||
.scheme(scenario.getScheme())
|
||||
|
@ -323,7 +323,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest
|
|||
.send();
|
||||
|
||||
assertEquals(status, response2.getStatus());
|
||||
assertEquals(1, requests.get());
|
||||
assertEquals(2, requests.get());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
|
|
@ -424,8 +424,9 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
{
|
||||
Connection old_connection = getConnection();
|
||||
|
||||
ByteBuffer prefilled = (old_connection instanceof Connection.UpgradeFrom)
|
||||
?((Connection.UpgradeFrom)old_connection).onUpgradeFrom():null;
|
||||
ByteBuffer buffer = (old_connection instanceof Connection.UpgradeFrom) ?
|
||||
((Connection.UpgradeFrom)old_connection).onUpgradeFrom() :
|
||||
null;
|
||||
old_connection.onClose();
|
||||
old_connection.getEndPoint().setConnection(newConnection);
|
||||
|
||||
|
@ -434,9 +435,9 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
this, old_connection, newConnection, BufferUtil.toDetailString(prefilled));
|
||||
|
||||
if (newConnection instanceof Connection.UpgradeTo)
|
||||
((Connection.UpgradeTo)newConnection).onUpgradeTo(prefilled);
|
||||
else if (BufferUtil.hasContent(prefilled))
|
||||
throw new IllegalStateException();
|
||||
((Connection.UpgradeTo)newConnection).onUpgradeTo(buffer);
|
||||
else if (BufferUtil.hasContent(buffer))
|
||||
throw new IllegalStateException("Cannot upgrade: " + newConnection + " does not implement " + Connection.UpgradeTo.class.getName());
|
||||
|
||||
newConnection.onOpen();
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import java.util.Collections;
|
|||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
|
@ -60,6 +61,20 @@ import org.eclipse.jetty.util.thread.strategy.EatWhatYouKill;
|
|||
public class ManagedSelector extends ContainerLifeCycle implements Dumpable
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ManagedSelector.class);
|
||||
private static final boolean FORCE_SELECT_NOW;
|
||||
static
|
||||
{
|
||||
String property = System.getProperty("org.eclipse.jetty.io.forceSelectNow");
|
||||
if (property != null)
|
||||
{
|
||||
FORCE_SELECT_NOW = Boolean.parseBoolean(property);
|
||||
}
|
||||
else
|
||||
{
|
||||
property = System.getProperty("os.name");
|
||||
FORCE_SELECT_NOW = property != null && property.toLowerCase(Locale.ENGLISH).contains("windows");
|
||||
}
|
||||
}
|
||||
|
||||
private final AtomicBoolean _started = new AtomicBoolean(false);
|
||||
private boolean _selecting = false;
|
||||
|
@ -457,6 +472,7 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
|
|||
if (Thread.interrupted() && !isRunning())
|
||||
throw new ClosedSelectorException();
|
||||
|
||||
if (FORCE_SELECT_NOW)
|
||||
selected = selector.selectNow();
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
|
|
|
@ -76,7 +76,7 @@ import org.eclipse.jetty.util.thread.Invocable;
|
|||
* be called again and make another best effort attempt to progress the connection.
|
||||
*
|
||||
*/
|
||||
public class SslConnection extends AbstractConnection
|
||||
public class SslConnection extends AbstractConnection implements Connection.UpgradeTo
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(SslConnection.class);
|
||||
private static final String TLS_1_3 = "TLSv1.3";
|
||||
|
@ -260,6 +260,22 @@ public class SslConnection extends AbstractConnection
|
|||
this._allowMissingCloseMessage = allowMissingCloseMessage;
|
||||
}
|
||||
|
||||
private void acquireEncryptedInput()
|
||||
{
|
||||
if (_encryptedInput == null)
|
||||
_encryptedInput = _bufferPool.acquire(_sslEngine.getSession().getPacketBufferSize(), _encryptedDirectBuffers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgradeTo(ByteBuffer buffer)
|
||||
{
|
||||
if (BufferUtil.hasContent(buffer))
|
||||
{
|
||||
acquireEncryptedInput();
|
||||
BufferUtil.append(_encryptedInput, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen()
|
||||
{
|
||||
|
@ -526,8 +542,7 @@ public class SslConnection extends AbstractConnection
|
|||
throw new IllegalStateException("Unexpected HandshakeStatus " + status);
|
||||
}
|
||||
|
||||
if (_encryptedInput == null)
|
||||
_encryptedInput = _bufferPool.acquire(_sslEngine.getSession().getPacketBufferSize(), _encryptedDirectBuffers);
|
||||
acquireEncryptedInput();
|
||||
|
||||
// can we use the passed buffer if it is big enough
|
||||
ByteBuffer app_in;
|
||||
|
|
|
@ -29,7 +29,10 @@ import org.eclipse.jetty.http.HttpHeader;
|
|||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.http.QuotedCSV;
|
||||
import org.eclipse.jetty.server.HttpConfiguration.Customizer;
|
||||
import org.eclipse.jetty.util.HostPort;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -54,6 +57,8 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
*/
|
||||
public class ForwardedRequestCustomizer implements Customizer
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ForwardedRequestCustomizer.class);
|
||||
|
||||
private HostPortHttpField _forcedHost;
|
||||
private String _forwardedHeader = HttpHeader.FORWARDED.toString();
|
||||
private String _forwardedHostHeader = HttpHeader.X_FORWARDED_HOST.toString();
|
||||
|
@ -297,7 +302,7 @@ public class ForwardedRequestCustomizer implements Customizer
|
|||
RFC7239 rfc7239 = null;
|
||||
String forwardedHost = null;
|
||||
String forwardedServer = null;
|
||||
String forwardedFor = null;
|
||||
HostPort forwardedFor = null;
|
||||
String forwardedProto = null;
|
||||
String forwardedHttps = null;
|
||||
|
||||
|
@ -333,7 +338,7 @@ public class ForwardedRequestCustomizer implements Customizer
|
|||
forwardedServer = getLeftMost(field.getValue());
|
||||
|
||||
if (forwardedFor==null && _forwardedForHeader!=null && _forwardedForHeader.equalsIgnoreCase(name))
|
||||
forwardedFor = getLeftMost(field.getValue());
|
||||
forwardedFor = getRemoteAddr(field.getValue());
|
||||
|
||||
if (forwardedProto==null && _forwardedProtoHeader!=null && _forwardedProtoHeader.equalsIgnoreCase(name))
|
||||
forwardedProto = getLeftMost(field.getValue());
|
||||
|
@ -389,7 +394,7 @@ public class ForwardedRequestCustomizer implements Customizer
|
|||
}
|
||||
else if (forwardedFor != null)
|
||||
{
|
||||
request.setRemoteAddr(InetSocketAddress.createUnresolved(forwardedFor,request.getRemotePort()));
|
||||
request.setRemoteAddr(InetSocketAddress.createUnresolved(forwardedFor.getHost(), (forwardedFor.getPort() > 0) ? forwardedFor.getPort() : request.getRemotePort()));
|
||||
}
|
||||
|
||||
// handle protocol identifier
|
||||
|
@ -431,6 +436,26 @@ public class ForwardedRequestCustomizer implements Customizer
|
|||
return headerValue.substring(0,commaIndex).trim();
|
||||
}
|
||||
|
||||
protected HostPort getRemoteAddr(String headerValue)
|
||||
{
|
||||
String leftMost = getLeftMost(headerValue);
|
||||
if (leftMost == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new HostPort(leftMost);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// failed to parse in host[:port] format
|
||||
LOG.ignore(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
|
|
@ -50,7 +50,7 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
/**
|
||||
* <p>A {@link Connection} that handles the HTTP protocol.</p>
|
||||
*/
|
||||
public class HttpConnection extends AbstractConnection implements Runnable, HttpTransport, Connection.UpgradeFrom, WriteFlusher.Listener
|
||||
public class HttpConnection extends AbstractConnection implements Runnable, HttpTransport, WriteFlusher.Listener, Connection.UpgradeFrom, Connection.UpgradeTo
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(HttpConnection.class);
|
||||
public static final HttpField CONNECTION_CLOSE = new PreEncodedHttpField(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE.asString());
|
||||
|
@ -193,6 +193,13 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgradeTo(ByteBuffer buffer)
|
||||
{
|
||||
if (BufferUtil.hasContent(buffer))
|
||||
BufferUtil.append(getRequestBuffer(), buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFlushed(long bytes) throws IOException
|
||||
{
|
||||
|
@ -497,7 +504,10 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
public void onOpen()
|
||||
{
|
||||
super.onOpen();
|
||||
if (isRequestBufferEmpty())
|
||||
fillInterested();
|
||||
else
|
||||
getExecutor().execute(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* <p>A ConnectionFactory whose connections detect whether the first bytes are
|
||||
* TLS bytes and upgrades to either a TLS connection or to another configurable
|
||||
* connection.</p>
|
||||
*/
|
||||
public class OptionalSslConnectionFactory extends AbstractConnectionFactory
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(OptionalSslConnection.class);
|
||||
private static final int TLS_ALERT_FRAME_TYPE = 0x15;
|
||||
private static final int TLS_HANDSHAKE_FRAME_TYPE = 0x16;
|
||||
private static final int TLS_MAJOR_VERSION = 3;
|
||||
|
||||
private final SslConnectionFactory sslConnectionFactory;
|
||||
private final String otherProtocol;
|
||||
|
||||
/**
|
||||
* <p>Creates a new ConnectionFactory whose connections can upgrade to TLS or another protocol.</p>
|
||||
* <p>If {@code otherProtocol} is {@code null}, and the first bytes are not TLS, then
|
||||
* {@link #otherProtocol(ByteBuffer, EndPoint)} is called.</p>
|
||||
*
|
||||
* @param sslConnectionFactory The SslConnectionFactory to use if the first bytes are TLS
|
||||
* @param otherProtocol the protocol of the ConnectionFactory to use if the first bytes are not TLS,
|
||||
* or null to explicitly handle the non-TLS case
|
||||
*/
|
||||
public OptionalSslConnectionFactory(SslConnectionFactory sslConnectionFactory, String otherProtocol)
|
||||
{
|
||||
super("ssl|other");
|
||||
this.sslConnectionFactory = sslConnectionFactory;
|
||||
this.otherProtocol = otherProtocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection newConnection(Connector connector, EndPoint endPoint)
|
||||
{
|
||||
return configure(new OptionalSslConnection(endPoint, connector), connector, endPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param buffer The buffer with the first bytes of the connection
|
||||
* @return whether the bytes seem TLS bytes
|
||||
*/
|
||||
protected boolean seemsTLS(ByteBuffer buffer)
|
||||
{
|
||||
int tlsFrameType = buffer.get(0) & 0xFF;
|
||||
int tlsMajorVersion = buffer.get(1) & 0xFF;
|
||||
return (tlsFrameType == TLS_HANDSHAKE_FRAME_TYPE || tlsFrameType == TLS_ALERT_FRAME_TYPE) && tlsMajorVersion == TLS_MAJOR_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Callback method invoked when {@code otherProtocol} is {@code null}
|
||||
* and the first bytes are not TLS.</p>
|
||||
* <p>This typically happens when a client is trying to connect to a TLS
|
||||
* port using the {@code http} scheme (and not the {@code https} scheme).</p>
|
||||
*
|
||||
* @param buffer The buffer with the first bytes of the connection
|
||||
* @param endPoint The connection EndPoint object
|
||||
* @see #seemsTLS(ByteBuffer)
|
||||
*/
|
||||
protected void otherProtocol(ByteBuffer buffer, EndPoint endPoint)
|
||||
{
|
||||
// There are always at least 2 bytes.
|
||||
int byte1 = buffer.get(0) & 0xFF;
|
||||
int byte2 = buffer.get(1) & 0xFF;
|
||||
if (byte1 == 'G' && byte2 == 'E')
|
||||
{
|
||||
// Plain text HTTP to a HTTPS port,
|
||||
// write a minimal response.
|
||||
String body = "" +
|
||||
"<!DOCTYPE html>\r\n" +
|
||||
"<html>\r\n" +
|
||||
"<head><title>Bad Request</title></head>\r\n" +
|
||||
"<body>" +
|
||||
"<h1>Bad Request</h1>" +
|
||||
"<p>HTTP request to HTTPS port</p>" +
|
||||
"</body>\r\n" +
|
||||
"</html>";
|
||||
String response = "" +
|
||||
"HTTP/1.1 400 Bad Request\r\n" +
|
||||
"Content-Type: text/html\r\n" +
|
||||
"Content-Length: " + body.length() + "\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n" +
|
||||
body;
|
||||
Callback.Completable completable = new Callback.Completable();
|
||||
endPoint.write(completable, ByteBuffer.wrap(response.getBytes(StandardCharsets.US_ASCII)));
|
||||
completable.whenComplete((r, x) -> endPoint.close());
|
||||
}
|
||||
else
|
||||
{
|
||||
endPoint.close();
|
||||
}
|
||||
}
|
||||
|
||||
private class OptionalSslConnection extends AbstractConnection implements Connection.UpgradeFrom
|
||||
{
|
||||
private final Connector connector;
|
||||
private final ByteBuffer buffer;
|
||||
|
||||
public OptionalSslConnection(EndPoint endPoint, Connector connector)
|
||||
{
|
||||
super(endPoint, connector.getExecutor());
|
||||
this.connector = connector;
|
||||
this.buffer = BufferUtil.allocateDirect(1536);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen()
|
||||
{
|
||||
super.onOpen();
|
||||
fillInterested();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFillable()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int filled = getEndPoint().fill(buffer);
|
||||
if (filled > 0)
|
||||
{
|
||||
// Always have at least 2 bytes.
|
||||
if (BufferUtil.length(buffer) >= 2)
|
||||
{
|
||||
upgrade(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (filled == 0)
|
||||
{
|
||||
fillInterested();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
LOG.warn(x);
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer onUpgradeFrom()
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private void upgrade(ByteBuffer buffer)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Read {}", BufferUtil.toDetailString(buffer));
|
||||
|
||||
EndPoint endPoint = getEndPoint();
|
||||
if (seemsTLS(buffer))
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Detected TLS bytes, upgrading to {}", sslConnectionFactory);
|
||||
endPoint.upgrade(sslConnectionFactory.newConnection(connector, endPoint));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (otherProtocol != null)
|
||||
{
|
||||
ConnectionFactory connectionFactory = connector.getConnectionFactory(otherProtocol);
|
||||
if (connectionFactory != null)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Detected non-TLS bytes, upgrading to {}", connectionFactory);
|
||||
Connection next = connectionFactory.newConnection(connector, endPoint);
|
||||
endPoint.upgrade(next);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.warn("Missing {} {} in {}", otherProtocol, ConnectionFactory.class.getSimpleName(), connector);
|
||||
close();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Detected non-TLS bytes, but no other protocol to upgrade to");
|
||||
otherProtocol(buffer, endPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -233,6 +233,38 @@ public class ForwardedRequestCustomizerTest
|
|||
assertEquals("0",_results.poll());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForIpv4WithPort() throws Exception
|
||||
{
|
||||
String response=_connector.getResponse(
|
||||
"GET / HTTP/1.1\n"+
|
||||
"Host: myhost\n"+
|
||||
"X-Forwarded-For: 10.9.8.7:1111,6.5.4.3:2222\n"+
|
||||
"\n");
|
||||
assertThat(response, Matchers.containsString("200 OK"));
|
||||
assertEquals("http",_results.poll());
|
||||
assertEquals("myhost",_results.poll());
|
||||
assertEquals("80",_results.poll());
|
||||
assertEquals("10.9.8.7",_results.poll());
|
||||
assertEquals("1111",_results.poll());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForIpv6WithPort() throws Exception
|
||||
{
|
||||
String response=_connector.getResponse(
|
||||
"GET / HTTP/1.1\n"+
|
||||
"Host: myhost\n"+
|
||||
"X-Forwarded-For: [2001:db8:cafe::17]:1111,6.5.4.3:2222\n"+
|
||||
"\n");
|
||||
assertThat(response, Matchers.containsString("200 OK"));
|
||||
assertEquals("http",_results.poll());
|
||||
assertEquals("myhost",_results.poll());
|
||||
assertEquals("80",_results.poll());
|
||||
assertEquals("[2001:db8:cafe::17]",_results.poll());
|
||||
assertEquals("1111",_results.poll());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLegacyProto() throws Exception
|
||||
{
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
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.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class OptionalSslConnectionTest
|
||||
{
|
||||
private Server server;
|
||||
private ServerConnector connector;
|
||||
|
||||
private void startServer(Function<SslConnectionFactory, OptionalSslConnectionFactory> configFn, Handler handler) throws Exception
|
||||
{
|
||||
QueuedThreadPool serverThreads = new QueuedThreadPool();
|
||||
serverThreads.setName("server");
|
||||
server = new Server(serverThreads);
|
||||
|
||||
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
sslContextFactory.setKeyStorePath(keystore);
|
||||
sslContextFactory.setKeyStorePassword("storepwd");
|
||||
sslContextFactory.setKeyManagerPassword("keypwd");
|
||||
|
||||
HttpConfiguration httpConfig = new HttpConfiguration();
|
||||
HttpConnectionFactory http = new HttpConnectionFactory(httpConfig);
|
||||
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, http.getProtocol());
|
||||
OptionalSslConnectionFactory sslOrOther = configFn.apply(ssl);
|
||||
connector = new ServerConnector(server, 1, 1, sslOrOther, ssl, http);
|
||||
server.addConnector(connector);
|
||||
|
||||
server.setHandler(handler);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
if (server != null)
|
||||
server.stop();
|
||||
}
|
||||
|
||||
private OptionalSslConnectionFactory optionalSsl(SslConnectionFactory ssl)
|
||||
{
|
||||
return new OptionalSslConnectionFactory(ssl, ssl.getNextProtocol());
|
||||
}
|
||||
|
||||
private OptionalSslConnectionFactory optionalSslNoOtherProtocol(SslConnectionFactory ssl)
|
||||
{
|
||||
return new OptionalSslConnectionFactory(ssl, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalSslConnection() throws Exception
|
||||
{
|
||||
startServer(this::optionalSsl, new EmptyServerHandler());
|
||||
|
||||
String request = "" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n";
|
||||
byte[] requestBytes = request.getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
// Try first a plain text connection.
|
||||
try (Socket plain = new Socket())
|
||||
{
|
||||
plain.connect(new InetSocketAddress("localhost", connector.getLocalPort()), 1000);
|
||||
OutputStream plainOutput = plain.getOutputStream();
|
||||
plainOutput.write(requestBytes);
|
||||
plainOutput.flush();
|
||||
|
||||
plain.setSoTimeout(5000);
|
||||
InputStream plainInput = plain.getInputStream();
|
||||
HttpTester.Response response = HttpTester.parseResponse(plainInput);
|
||||
assertNotNull(response);
|
||||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
}
|
||||
|
||||
// Then try a SSL connection.
|
||||
SslContextFactory sslContextFactory = new SslContextFactory(true);
|
||||
sslContextFactory.start();
|
||||
try (Socket ssl = sslContextFactory.newSslSocket())
|
||||
{
|
||||
ssl.connect(new InetSocketAddress("localhost", connector.getLocalPort()), 1000);
|
||||
OutputStream sslOutput = ssl.getOutputStream();
|
||||
sslOutput.write(requestBytes);
|
||||
sslOutput.flush();
|
||||
|
||||
ssl.setSoTimeout(5000);
|
||||
InputStream sslInput = ssl.getInputStream();
|
||||
HttpTester.Response response = HttpTester.parseResponse(sslInput);
|
||||
assertNotNull(response);
|
||||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
}
|
||||
finally
|
||||
{
|
||||
sslContextFactory.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalSslConnectionWithOnlyOneByteShouldIdleTimeout() throws Exception
|
||||
{
|
||||
startServer(this::optionalSsl, new EmptyServerHandler());
|
||||
long idleTimeout = 1000;
|
||||
connector.setIdleTimeout(idleTimeout);
|
||||
|
||||
try (Socket socket = new Socket())
|
||||
{
|
||||
socket.connect(new InetSocketAddress("localhost", connector.getLocalPort()), 1000);
|
||||
OutputStream output = socket.getOutputStream();
|
||||
output.write(0x16);
|
||||
output.flush();
|
||||
|
||||
socket.setSoTimeout((int)(2 * idleTimeout));
|
||||
InputStream input = socket.getInputStream();
|
||||
int read = input.read();
|
||||
assertEquals(-1, read);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalSslConnectionWithUnknownBytes() throws Exception
|
||||
{
|
||||
startServer(this::optionalSslNoOtherProtocol, new EmptyServerHandler());
|
||||
|
||||
try (Socket socket = new Socket())
|
||||
{
|
||||
socket.connect(new InetSocketAddress("localhost", connector.getLocalPort()), 1000);
|
||||
OutputStream output = socket.getOutputStream();
|
||||
output.write(0x00);
|
||||
output.flush();
|
||||
Thread.sleep(500);
|
||||
output.write(0x00);
|
||||
output.flush();
|
||||
|
||||
socket.setSoTimeout(5000);
|
||||
InputStream input = socket.getInputStream();
|
||||
int read = input.read();
|
||||
assertEquals(-1, read);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalSslConnectionWithHTTPBytes() throws Exception
|
||||
{
|
||||
startServer(this::optionalSslNoOtherProtocol, new EmptyServerHandler());
|
||||
|
||||
String request = "" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n";
|
||||
byte[] requestBytes = request.getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
// Send a plain text HTTP request to SSL port,
|
||||
// we should get back a minimal HTTP response.
|
||||
try (Socket socket = new Socket())
|
||||
{
|
||||
socket.connect(new InetSocketAddress("localhost", connector.getLocalPort()), 1000);
|
||||
OutputStream output = socket.getOutputStream();
|
||||
output.write(requestBytes);
|
||||
output.flush();
|
||||
|
||||
socket.setSoTimeout(5000);
|
||||
InputStream input = socket.getInputStream();
|
||||
HttpTester.Response response = HttpTester.parseResponse(input);
|
||||
assertNotNull(response);
|
||||
assertEquals(HttpStatus.BAD_REQUEST_400, response.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
private static class EmptyServerHandler extends AbstractHandler.ErrorDispatchHandler
|
||||
{
|
||||
@Override
|
||||
protected void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
jettyRequest.setHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
#org.eclipse.jetty.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.server.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.server.ConnectionLimit.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.server.AcceptRateLimit.LEVEL=DEBUG
|
|
@ -18,20 +18,21 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.javax.client;
|
||||
|
||||
import org.eclipse.jetty.websocket.javax.common.UpgradeRequest;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.Principal;
|
||||
|
||||
import org.eclipse.jetty.websocket.core.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.javax.common.UpgradeRequest;
|
||||
|
||||
/**
|
||||
* Representing the Jetty {@link org.eclipse.jetty.client.HttpClient}'s {@link org.eclipse.jetty.client.HttpRequest}
|
||||
* in the {@link UpgradeRequest} interface.
|
||||
*/
|
||||
public class DelegatedClientUpgradeRequest implements UpgradeRequest
|
||||
public class DelegatedJavaxClientUpgradeRequest implements UpgradeRequest
|
||||
{
|
||||
private final org.eclipse.jetty.websocket.core.client.UpgradeRequest delegate;
|
||||
private final ClientUpgradeRequest delegate;
|
||||
|
||||
public DelegatedClientUpgradeRequest(org.eclipse.jetty.websocket.core.client.UpgradeRequest delegate)
|
||||
public DelegatedJavaxClientUpgradeRequest(ClientUpgradeRequest delegate)
|
||||
{
|
||||
this.delegate = delegate;
|
||||
}
|
|
@ -18,24 +18,24 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.javax.client;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.websocket.core.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.javax.common.UpgradeResponse;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Representing the Jetty {@link org.eclipse.jetty.client.HttpClient}'s {@link HttpResponse}
|
||||
* in the {@link UpgradeResponse} interface.
|
||||
*/
|
||||
public class DelegatedClientUpgradeResponse implements UpgradeResponse
|
||||
public class DelegatedJavaxClientUpgradeResponse implements UpgradeResponse
|
||||
{
|
||||
private HttpResponse delegate;
|
||||
|
||||
public DelegatedClientUpgradeResponse(HttpResponse response)
|
||||
public DelegatedJavaxClientUpgradeResponse(HttpResponse response)
|
||||
{
|
||||
this.delegate = response;
|
||||
}
|
|
@ -18,51 +18,53 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.javax.client;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import javax.websocket.Session;
|
||||
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||
import org.eclipse.jetty.websocket.core.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient;
|
||||
import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketFrameHandler;
|
||||
import org.eclipse.jetty.websocket.javax.common.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.javax.common.UpgradeResponse;
|
||||
|
||||
import javax.websocket.Session;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ClientUpgradeRequestImpl extends org.eclipse.jetty.websocket.core.client.UpgradeRequest
|
||||
public class JavaxClientUpgradeRequest extends ClientUpgradeRequest
|
||||
{
|
||||
private final JavaxWebSocketClientContainer containerContext;
|
||||
private final Object websocketPojo;
|
||||
private final CompletableFuture<Session> futureJavaxSession;
|
||||
private final CompletableFuture<Session> futureSession;
|
||||
|
||||
public ClientUpgradeRequestImpl(JavaxWebSocketClientContainer clientContainer, WebSocketCoreClient coreClient, URI requestURI, Object websocketPojo)
|
||||
public JavaxClientUpgradeRequest(JavaxWebSocketClientContainer clientContainer, WebSocketCoreClient coreClient, URI requestURI, Object websocketPojo)
|
||||
{
|
||||
super(coreClient, requestURI);
|
||||
this.containerContext = clientContainer;
|
||||
this.websocketPojo = websocketPojo;
|
||||
this.futureJavaxSession = new CompletableFuture<>();
|
||||
this.futureSession = new CompletableFuture<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleException(Throwable failure)
|
||||
{
|
||||
super.handleException(failure);
|
||||
futureJavaxSession.completeExceptionally(failure);
|
||||
futureSession.completeExceptionally(failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameHandler getFrameHandler(WebSocketCoreClient coreClient, HttpResponse response)
|
||||
{
|
||||
UpgradeRequest upgradeRequest = new DelegatedClientUpgradeRequest(this);
|
||||
UpgradeResponse upgradeResponse = new DelegatedClientUpgradeResponse(response);
|
||||
UpgradeRequest upgradeRequest = new DelegatedJavaxClientUpgradeRequest(this);
|
||||
UpgradeResponse upgradeResponse = new DelegatedJavaxClientUpgradeResponse(response);
|
||||
|
||||
JavaxWebSocketFrameHandler frameHandler = containerContext.newFrameHandler(websocketPojo, upgradeRequest, upgradeResponse, futureJavaxSession);
|
||||
JavaxWebSocketFrameHandler frameHandler = containerContext.newFrameHandler(websocketPojo, upgradeRequest, upgradeResponse, futureSession);
|
||||
|
||||
return frameHandler;
|
||||
}
|
||||
|
||||
public CompletableFuture<Session> getFutureSession()
|
||||
{
|
||||
return futureJavaxSession;
|
||||
return futureSession;
|
||||
}
|
||||
}
|
|
@ -125,7 +125,7 @@ public class JavaxWebSocketClientContainer extends JavaxWebSocketContainer imple
|
|||
* @param upgradeRequest the upgrade request information
|
||||
* @return the future for the session, available on success of connect
|
||||
*/
|
||||
private CompletableFuture<Session> connect(ClientUpgradeRequestImpl upgradeRequest)
|
||||
private CompletableFuture<Session> connect(JavaxClientUpgradeRequest upgradeRequest)
|
||||
{
|
||||
CompletableFuture<Session> fut = upgradeRequest.getFutureSession();
|
||||
try
|
||||
|
@ -145,7 +145,7 @@ public class JavaxWebSocketClientContainer extends JavaxWebSocketContainer imple
|
|||
Objects.requireNonNull(configuredEndpoint, "WebSocket configured endpoint cannot be null");
|
||||
Objects.requireNonNull(destURI, "Destination URI cannot be null");
|
||||
|
||||
ClientUpgradeRequestImpl upgradeRequest = new ClientUpgradeRequestImpl(this, getWebSocketCoreClient(), destURI, configuredEndpoint);
|
||||
JavaxClientUpgradeRequest upgradeRequest = new JavaxClientUpgradeRequest(this, getWebSocketCoreClient(), destURI, configuredEndpoint);
|
||||
|
||||
EndpointConfig config = configuredEndpoint.getConfig();
|
||||
if (config != null && config instanceof ClientEndpointConfig)
|
||||
|
|
|
@ -18,19 +18,20 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.javax.common;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry;
|
||||
|
||||
import javax.websocket.Extension;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.websocket.Extension;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry;
|
||||
|
||||
public abstract class JavaxWebSocketContainer extends ContainerLifeCycle implements javax.websocket.WebSocketContainer
|
||||
{
|
||||
private long defaultAsyncSendTimeout = -1;
|
||||
|
@ -105,7 +106,7 @@ public abstract class JavaxWebSocketContainer extends ContainerLifeCycle impleme
|
|||
public JavaxWebSocketFrameHandler newFrameHandler(Object websocketPojo, UpgradeRequest upgradeRequest, UpgradeResponse upgradeResponse,
|
||||
CompletableFuture<Session> futureSession)
|
||||
{
|
||||
return getFrameHandlerFactory().newJavaxFrameHandler(websocketPojo, upgradeRequest, upgradeResponse, futureSession);
|
||||
return getFrameHandlerFactory().newJavaxWebSocketFrameHandler(websocketPojo, upgradeRequest, upgradeResponse, futureSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Optional;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
|
@ -229,16 +230,14 @@ public class JavaxWebSocketFrameHandler implements FrameHandler
|
|||
openHandle.invoke();
|
||||
|
||||
container.addBean(session, true);
|
||||
futureSession.complete(session);
|
||||
callback.succeeded();
|
||||
futureSession.complete(session);
|
||||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
Exception wse = new WebSocketException(endpointInstance.getClass().getName() + " OPEN method error: " + cause.getMessage(), cause);
|
||||
|
||||
// TODO This feels like double handling of the exception? Review need for futureSession
|
||||
futureSession.completeExceptionally(wse);
|
||||
callback.failed(wse);
|
||||
futureSession.completeExceptionally(wse);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,32 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.javax.common;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.OnClose;
|
||||
import javax.websocket.OnError;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.PongMessage;
|
||||
import javax.websocket.Session;
|
||||
|
||||
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
|
||||
import org.eclipse.jetty.websocket.javax.common.decoders.AvailableDecoders;
|
||||
import org.eclipse.jetty.websocket.javax.common.messages.ByteArrayMessageSink;
|
||||
|
@ -37,31 +63,6 @@ import org.eclipse.jetty.websocket.javax.common.util.InvalidSignatureException;
|
|||
import org.eclipse.jetty.websocket.javax.common.util.InvokerUtils;
|
||||
import org.eclipse.jetty.websocket.javax.common.util.ReflectUtils;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.OnClose;
|
||||
import javax.websocket.OnError;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.PongMessage;
|
||||
import javax.websocket.Session;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.eclipse.jetty.websocket.javax.common.JavaxWebSocketFrameHandlerMetadata.MessageMetadata;
|
||||
|
||||
|
@ -107,7 +108,8 @@ public abstract class JavaxWebSocketFrameHandlerFactory
|
|||
|
||||
public abstract JavaxWebSocketFrameHandlerMetadata createMetadata(Class<?> endpointClass, EndpointConfig endpointConfig);
|
||||
|
||||
public JavaxWebSocketFrameHandler newJavaxFrameHandler(Object endpointInstance, UpgradeRequest upgradeRequest, UpgradeResponse upgradeResponse,
|
||||
public JavaxWebSocketFrameHandler newJavaxWebSocketFrameHandler(Object endpointInstance, UpgradeRequest upgradeRequest,
|
||||
UpgradeResponse upgradeResponse,
|
||||
CompletableFuture<Session> futureSession)
|
||||
{
|
||||
Object endpoint;
|
||||
|
|
|
@ -69,7 +69,7 @@ public abstract class AbstractJavaxWebSocketFrameHandlerTest
|
|||
UpgradeRequest upgradeRequest = new UpgradeRequestAdapter();
|
||||
UpgradeResponse upgradeResponse = new UpgradeResponseAdapter();
|
||||
|
||||
JavaxWebSocketFrameHandler localEndpoint = factory.newJavaxFrameHandler(endpoint,
|
||||
JavaxWebSocketFrameHandler localEndpoint = factory.newJavaxWebSocketFrameHandler(endpoint,
|
||||
upgradeRequest, upgradeResponse, new CompletableFuture<>());
|
||||
|
||||
return localEndpoint;
|
||||
|
|
|
@ -18,23 +18,24 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.javax.server;
|
||||
|
||||
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
|
||||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||
import org.eclipse.jetty.websocket.javax.server.internal.PathParamIdentifier;
|
||||
import org.eclipse.jetty.websocket.javax.server.internal.UpgradeRequestAdapter;
|
||||
import org.eclipse.jetty.websocket.javax.server.internal.UpgradeResponseAdapter;
|
||||
import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketContainer;
|
||||
import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketFrameHandlerFactory;
|
||||
import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketFrameHandlerMetadata;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.servlet.FrameHandlerFactory;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import javax.websocket.Endpoint;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
|
||||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||
import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketContainer;
|
||||
import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketFrameHandlerFactory;
|
||||
import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketFrameHandlerMetadata;
|
||||
import org.eclipse.jetty.websocket.javax.server.internal.DelegatedJavaxServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.javax.server.internal.PathParamIdentifier;
|
||||
import org.eclipse.jetty.websocket.javax.server.internal.UpgradeResponseAdapter;
|
||||
import org.eclipse.jetty.websocket.servlet.FrameHandlerFactory;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||
|
||||
public class JavaxWebSocketServerFrameHandlerFactory extends JavaxWebSocketFrameHandlerFactory implements FrameHandlerFactory
|
||||
{
|
||||
|
@ -68,6 +69,6 @@ public class JavaxWebSocketServerFrameHandlerFactory extends JavaxWebSocketFrame
|
|||
public FrameHandler newFrameHandler(Object websocketPojo, ServletUpgradeRequest upgradeRequest, ServletUpgradeResponse upgradeResponse)
|
||||
{
|
||||
CompletableFuture<Session> completableFuture = new CompletableFuture<>();
|
||||
return newJavaxFrameHandler(websocketPojo, new UpgradeRequestAdapter(upgradeRequest), new UpgradeResponseAdapter(upgradeResponse), completableFuture);
|
||||
return newJavaxWebSocketFrameHandler(websocketPojo, new DelegatedJavaxServletUpgradeRequest(upgradeRequest), new UpgradeResponseAdapter(upgradeResponse), completableFuture);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,17 +18,17 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.javax.server.internal;
|
||||
|
||||
import org.eclipse.jetty.websocket.javax.common.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.Principal;
|
||||
|
||||
public class UpgradeRequestAdapter implements UpgradeRequest
|
||||
import org.eclipse.jetty.websocket.javax.common.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
|
||||
public class DelegatedJavaxServletUpgradeRequest implements UpgradeRequest
|
||||
{
|
||||
private final ServletUpgradeRequest servletRequest;
|
||||
|
||||
public UpgradeRequestAdapter(ServletUpgradeRequest servletRequest)
|
||||
public DelegatedJavaxServletUpgradeRequest(ServletUpgradeRequest servletRequest)
|
||||
{
|
||||
this.servletRequest = servletRequest;
|
||||
}
|
|
@ -38,7 +38,7 @@ import org.eclipse.jetty.websocket.core.Behavior;
|
|||
import org.eclipse.jetty.websocket.core.CloseStatus;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||
import org.eclipse.jetty.websocket.core.client.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient;
|
||||
import org.eclipse.jetty.websocket.core.internal.Generator;
|
||||
|
||||
|
@ -184,7 +184,7 @@ public class NetworkFuzzer extends Fuzzer.Adapter implements Fuzzer, AutoCloseab
|
|||
}
|
||||
}
|
||||
|
||||
public static class RawUpgradeRequest extends UpgradeRequest
|
||||
public static class RawUpgradeRequest extends ClientUpgradeRequest
|
||||
{
|
||||
private final CompletableFuture<FrameCapture> futureCapture;
|
||||
private EndPoint endPoint;
|
||||
|
|
|
@ -84,7 +84,7 @@ public class SessionAddMessageHandlerTest
|
|||
|
||||
JavaxWebSocketFrameHandlerFactory frameHandlerFactory = new JavaxWebSocketClientFrameHandlerFactory(container);
|
||||
CompletableFuture<Session> futureSession = new CompletableFuture<>();
|
||||
frameHandler = frameHandlerFactory.newJavaxFrameHandler(ei, handshakeRequest, handshakeResponse, futureSession);
|
||||
frameHandler = frameHandlerFactory.newJavaxWebSocketFrameHandler(ei, handshakeRequest, handshakeResponse, futureSession);
|
||||
frameHandler.onOpen(new FrameHandler.CoreSession.Empty(), Callback.NOOP);
|
||||
|
||||
// Session
|
||||
|
|
|
@ -18,37 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.javax.tests.server;
|
||||
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||
import org.eclipse.jetty.websocket.core.OpCode;
|
||||
import org.eclipse.jetty.websocket.core.client.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient;
|
||||
import org.eclipse.jetty.websocket.javax.server.internal.JavaxWebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.javax.tests.LocalServer;
|
||||
import org.eclipse.jetty.websocket.javax.tests.Timeouts;
|
||||
import org.eclipse.jetty.websocket.javax.tests.framehandlers.FrameHandlerTracker;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.websocket.DecodeException;
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.Extension;
|
||||
import javax.websocket.HandshakeResponse;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.HandshakeRequest;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.InetSocketAddress;
|
||||
|
@ -69,6 +38,38 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.websocket.DecodeException;
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.Extension;
|
||||
import javax.websocket.HandshakeResponse;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.HandshakeRequest;
|
||||
import javax.websocket.server.ServerContainer;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||
import org.eclipse.jetty.websocket.core.OpCode;
|
||||
import org.eclipse.jetty.websocket.core.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient;
|
||||
import org.eclipse.jetty.websocket.javax.server.internal.JavaxWebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.javax.tests.LocalServer;
|
||||
import org.eclipse.jetty.websocket.javax.tests.Timeouts;
|
||||
import org.eclipse.jetty.websocket.javax.tests.framehandlers.FrameHandlerTracker;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
|
@ -430,7 +431,7 @@ public class ConfiguratorTest
|
|||
URI wsUri = server.getWsUri().resolve("/capture-request-headers");
|
||||
|
||||
FrameHandlerTracker clientSocket = new FrameHandlerTracker();
|
||||
UpgradeRequest upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
upgradeRequest.addExtensions("identity");
|
||||
Future<FrameHandler.CoreSession> clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
||||
|
@ -454,7 +455,7 @@ public class ConfiguratorTest
|
|||
URI wsUri = server.getWsUri().resolve("/no-extensions");
|
||||
|
||||
FrameHandlerTracker clientSocket = new FrameHandlerTracker();
|
||||
UpgradeRequest upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
upgradeRequest.addExtensions("identity");
|
||||
Future<FrameHandler.CoreSession> clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
||||
|
@ -478,7 +479,7 @@ public class ConfiguratorTest
|
|||
URI wsUri = server.getWsUri().resolve("/capture-request-headers");
|
||||
|
||||
FrameHandlerTracker clientSocket = new FrameHandlerTracker();
|
||||
UpgradeRequest upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
upgradeRequest.header("X-Dummy", "Bogus");
|
||||
Future<FrameHandler.CoreSession> clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
||||
|
@ -503,7 +504,7 @@ public class ConfiguratorTest
|
|||
|
||||
// First Request
|
||||
FrameHandlerTracker clientSocket = new FrameHandlerTracker();
|
||||
UpgradeRequest upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
Future<FrameHandler.CoreSession> clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
||||
FrameHandler.CoreSession channel = clientConnectFuture.get(Timeouts.CONNECT_MS, TimeUnit.MILLISECONDS);
|
||||
|
@ -522,7 +523,7 @@ public class ConfiguratorTest
|
|||
|
||||
// Second request
|
||||
clientSocket = new FrameHandlerTracker();
|
||||
upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
||||
channel = clientConnectFuture.get(Timeouts.CONNECT_MS, TimeUnit.MILLISECONDS);
|
||||
|
@ -550,7 +551,7 @@ public class ConfiguratorTest
|
|||
URI wsUri = server.getWsUri().resolve("/addr");
|
||||
|
||||
FrameHandlerTracker clientSocket = new FrameHandlerTracker();
|
||||
UpgradeRequest upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
Future<FrameHandler.CoreSession> clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
||||
FrameHandler.CoreSession channel = clientConnectFuture.get(Timeouts.CONNECT_MS, TimeUnit.MILLISECONDS);
|
||||
|
@ -591,7 +592,7 @@ public class ConfiguratorTest
|
|||
ProtocolsConfigurator.seenProtocols.set(null);
|
||||
|
||||
FrameHandlerTracker clientSocket = new FrameHandlerTracker();
|
||||
UpgradeRequest upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
upgradeRequest.setSubProtocols("status");
|
||||
Future<FrameHandler.CoreSession> clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
||||
|
@ -610,7 +611,7 @@ public class ConfiguratorTest
|
|||
ProtocolsConfigurator.seenProtocols.set(null);
|
||||
|
||||
FrameHandlerTracker clientSocket = new FrameHandlerTracker();
|
||||
UpgradeRequest upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
upgradeRequest.setSubProtocols("echo", "chat", "status");
|
||||
Future<FrameHandler.CoreSession> clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
||||
|
@ -629,7 +630,7 @@ public class ConfiguratorTest
|
|||
ProtocolsConfigurator.seenProtocols.set(null);
|
||||
|
||||
FrameHandlerTracker clientSocket = new FrameHandlerTracker();
|
||||
UpgradeRequest upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
upgradeRequest.header("sec-websocket-protocol", "echo, chat, status");
|
||||
Future<FrameHandler.CoreSession> clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
||||
|
@ -648,7 +649,7 @@ public class ConfiguratorTest
|
|||
ProtocolsConfigurator.seenProtocols.set(null);
|
||||
|
||||
FrameHandlerTracker clientSocket = new FrameHandlerTracker();
|
||||
UpgradeRequest upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
// header name is not to spec (case wise)
|
||||
upgradeRequest.header("Sec-Websocket-Protocol", "echo, chat, status");
|
||||
Future<FrameHandler.CoreSession> clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
@ -682,7 +683,7 @@ public class ConfiguratorTest
|
|||
URI wsUri = server.getWsUri().resolve("/timedecoder");
|
||||
|
||||
FrameHandlerTracker clientSocket = new FrameHandlerTracker();
|
||||
UpgradeRequest upgradeRequest = UpgradeRequest.from(client, wsUri, clientSocket);
|
||||
ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, wsUri, clientSocket);
|
||||
upgradeRequest.setSubProtocols("gmt");
|
||||
Future<FrameHandler.CoreSession> clientConnectFuture = client.connect(upgradeRequest);
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
|||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.client.impl.ClientUpgradeRequestImpl;
|
||||
import org.eclipse.jetty.websocket.client.impl.JettyClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandler;
|
||||
import org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandlerFactory;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry;
|
||||
|
@ -107,7 +107,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketPoli
|
|||
*/
|
||||
public CompletableFuture<Session> connect(Object websocket, URI toUri, UpgradeRequest request) throws IOException
|
||||
{
|
||||
ClientUpgradeRequestImpl upgradeRequest = new ClientUpgradeRequestImpl(this, coreClient, request, toUri, websocket);
|
||||
JettyClientUpgradeRequest upgradeRequest = new JettyClientUpgradeRequest(this, coreClient, request, toUri, websocket);
|
||||
coreClient.connect(upgradeRequest);
|
||||
return upgradeRequest.getFutureSession();
|
||||
}
|
||||
|
|
|
@ -18,14 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.client.impl;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.util.UrlEncoded;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
|
@ -35,19 +27,28 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.util.UrlEncoded;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.core.client.ClientUpgradeRequest;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
* Representing the Jetty {@link org.eclipse.jetty.client.HttpClient}'s {@link org.eclipse.jetty.client.HttpRequest}
|
||||
* in the {@link UpgradeRequest} interface.
|
||||
*/
|
||||
public class DelegatedClientUpgradeRequest implements UpgradeRequest
|
||||
public class DelegatedJettyClientUpgradeRequest implements UpgradeRequest
|
||||
{
|
||||
private final org.eclipse.jetty.websocket.core.client.UpgradeRequest delegate;
|
||||
private final ClientUpgradeRequest delegate;
|
||||
private SocketAddress localSocketAddress;
|
||||
private SocketAddress remoteSocketAddress;
|
||||
|
||||
public DelegatedClientUpgradeRequest(org.eclipse.jetty.websocket.core.client.UpgradeRequest delegate)
|
||||
public DelegatedJettyClientUpgradeRequest(ClientUpgradeRequest delegate)
|
||||
{
|
||||
this.delegate = delegate;
|
||||
}
|
|
@ -18,11 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.client.impl;
|
||||
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -30,15 +25,20 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
|
||||
/**
|
||||
* Representing the Jetty {@link org.eclipse.jetty.client.HttpClient}'s {@link org.eclipse.jetty.client.HttpResponse}
|
||||
* in the {@link UpgradeResponse} interface.
|
||||
*/
|
||||
public class DelegatedClientUpgradeResponse implements UpgradeResponse
|
||||
public class DelegatedJettyClientUpgradeResponse implements UpgradeResponse
|
||||
{
|
||||
private HttpResponse delegate;
|
||||
|
||||
public DelegatedClientUpgradeResponse(HttpResponse response)
|
||||
public DelegatedJettyClientUpgradeResponse(HttpResponse response)
|
||||
{
|
||||
this.delegate = response;
|
||||
}
|
|
@ -18,41 +18,39 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.client.impl;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandler;
|
||||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||
import org.eclipse.jetty.websocket.core.client.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ClientUpgradeRequestImpl extends UpgradeRequest
|
||||
public class JettyClientUpgradeRequest extends ClientUpgradeRequest
|
||||
{
|
||||
private final WebSocketClient containerContext;
|
||||
private final Object websocketPojo;
|
||||
private final CompletableFuture<Session> onOpenFuture;
|
||||
private final CompletableFuture<Session> futureSession;
|
||||
private final DelegatedClientUpgradeRequest handshakeRequest;
|
||||
private final DelegatedJettyClientUpgradeRequest handshakeRequest;
|
||||
|
||||
public ClientUpgradeRequestImpl(WebSocketClient clientContainer, WebSocketCoreClient coreClient, org.eclipse.jetty.websocket.api.UpgradeRequest request,
|
||||
public JettyClientUpgradeRequest(WebSocketClient clientContainer, WebSocketCoreClient coreClient, UpgradeRequest request,
|
||||
URI requestURI, Object websocketPojo)
|
||||
{
|
||||
super(coreClient, requestURI);
|
||||
this.containerContext = clientContainer;
|
||||
this.websocketPojo = websocketPojo;
|
||||
|
||||
this.onOpenFuture = new CompletableFuture<>();
|
||||
this.futureSession = super.futureCoreSession.thenCombine(onOpenFuture, (channel, session) -> session);
|
||||
this.futureSession = new CompletableFuture<>();
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
|
@ -89,7 +87,7 @@ public class ClientUpgradeRequestImpl extends UpgradeRequest
|
|||
version(HttpVersion.fromString(request.getHttpVersion()));
|
||||
}
|
||||
|
||||
handshakeRequest = new DelegatedClientUpgradeRequest(this);
|
||||
handshakeRequest = new DelegatedJettyClientUpgradeRequest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,16 +100,16 @@ public class ClientUpgradeRequestImpl extends UpgradeRequest
|
|||
protected void handleException(Throwable failure)
|
||||
{
|
||||
super.handleException(failure);
|
||||
onOpenFuture.completeExceptionally(failure);
|
||||
futureSession.completeExceptionally(failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameHandler getFrameHandler(WebSocketCoreClient coreClient, HttpResponse response)
|
||||
{
|
||||
UpgradeResponse upgradeResponse = new DelegatedClientUpgradeResponse(response);
|
||||
UpgradeResponse upgradeResponse = new DelegatedJettyClientUpgradeResponse(response);
|
||||
|
||||
JettyWebSocketFrameHandler frameHandler = containerContext.newFrameHandler(websocketPojo,
|
||||
handshakeRequest, upgradeResponse, onOpenFuture);
|
||||
handshakeRequest, upgradeResponse, futureSession);
|
||||
|
||||
return frameHandler;
|
||||
}
|
|
@ -141,13 +141,13 @@ public class JettyWebSocketFrameHandler implements FrameHandler
|
|||
if (openHandle != null)
|
||||
openHandle.invoke();
|
||||
|
||||
futureSession.complete(session);
|
||||
callback.succeeded();
|
||||
futureSession.complete(session);
|
||||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
// TODO should futureSession be failed here?
|
||||
callback.failed(new WebSocketException(endpointInstance.getClass().getName() + " OPEN method error: " + cause.getMessage(), cause));
|
||||
futureSession.completeExceptionally(cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,7 +236,10 @@ public class JettyWebSocketFrameHandler implements FrameHandler
|
|||
{
|
||||
// No message sink is active
|
||||
if (activeMessageSink == null)
|
||||
{
|
||||
callback.succeeded();
|
||||
return;
|
||||
}
|
||||
|
||||
// Accept the payload into the message sink
|
||||
activeMessageSink.accept(frame, callback);
|
||||
|
|
|
@ -61,7 +61,6 @@ import org.eclipse.jetty.websocket.common.message.PartialTextMessageSink;
|
|||
import org.eclipse.jetty.websocket.common.message.ReaderMessageSink;
|
||||
import org.eclipse.jetty.websocket.common.message.StringMessageSink;
|
||||
import org.eclipse.jetty.websocket.common.util.ReflectUtils;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
|
||||
/**
|
||||
* Factory to create {@link JettyWebSocketFrameHandler} instances suitable for
|
||||
|
@ -351,7 +350,7 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
|
|||
{
|
||||
assertSignatureValid(endpointClass, onmethod, OnWebSocketFrame.class);
|
||||
final InvokerUtils.Arg SESSION = new InvokerUtils.Arg(Session.class);
|
||||
final InvokerUtils.Arg FRAME = new InvokerUtils.Arg(Frame.class).required();
|
||||
final InvokerUtils.Arg FRAME = new InvokerUtils.Arg(org.eclipse.jetty.websocket.api.extensions.Frame.class).required();
|
||||
MethodHandle methodHandle = InvokerUtils.mutatedInvoker(endpointClass, onmethod, SESSION, FRAME);
|
||||
metadata.setFrameHandler(methodHandle, onmethod);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ package org.eclipse.jetty.websocket.common.endpoints.annotated;
|
|||
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.core.Frame;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
|
||||
@WebSocket
|
||||
public class FrameSocket
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
|
|||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.websocket.common.JettyWebSocketFrameHandlerFactory;
|
||||
import org.eclipse.jetty.websocket.core.FrameHandler;
|
||||
import org.eclipse.jetty.websocket.server.internal.UpgradeRequestAdapter;
|
||||
import org.eclipse.jetty.websocket.server.internal.DelegatedJettyServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.server.internal.UpgradeResponseAdapter;
|
||||
import org.eclipse.jetty.websocket.servlet.FrameHandlerFactory;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
|
@ -67,7 +67,7 @@ public class JettyServerFrameHandlerFactory
|
|||
@Override
|
||||
public FrameHandler newFrameHandler(Object websocketPojo, ServletUpgradeRequest upgradeRequest, ServletUpgradeResponse upgradeResponse)
|
||||
{
|
||||
return super.newJettyFrameHandler(websocketPojo, new UpgradeRequestAdapter(upgradeRequest), new UpgradeResponseAdapter(upgradeResponse),
|
||||
return super.newJettyFrameHandler(websocketPojo, new DelegatedJettyServletUpgradeRequest(upgradeRequest), new UpgradeResponseAdapter(upgradeResponse),
|
||||
new CompletableFuture<>());
|
||||
}
|
||||
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.server.internal;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.security.Principal;
|
||||
|
@ -29,11 +25,15 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class UpgradeRequestAdapter implements UpgradeRequest
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
|
||||
public class DelegatedJettyServletUpgradeRequest implements UpgradeRequest
|
||||
{
|
||||
private final ServletUpgradeRequest servletRequest;
|
||||
|
||||
public UpgradeRequestAdapter(ServletUpgradeRequest servletRequest)
|
||||
public DelegatedJettyServletUpgradeRequest(ServletUpgradeRequest servletRequest)
|
||||
{
|
||||
this.servletRequest = servletRequest;
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
<name>Jetty :: Websocket :: org.eclipse.jetty.websocket :: Tests</name>
|
||||
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.jetty.tests</bundle-symbolic-name>
|
||||
<bundle-symbolic-name>${project.groupId}.jetty.websocket.tests</bundle-symbolic-name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -32,6 +32,11 @@
|
|||
<artifactId>jetty-websocket-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>jetty-http-tools</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
@ -42,27 +47,21 @@
|
|||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>ban-java-servlet-api</id>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<rules>
|
||||
<bannedDependencies>
|
||||
<includes>
|
||||
<include>javax.servlet</include>
|
||||
<include>servletapi</include>
|
||||
<include>org.eclipse.jetty.orbit:javax.servlet</include>
|
||||
<include>org.mortbay.jetty:servlet-api</include>
|
||||
<include>jetty:servlet-api</include>
|
||||
<include>jetty-servlet-api</include>
|
||||
</includes>
|
||||
</bannedDependencies>
|
||||
</rules>
|
||||
<instructions>
|
||||
<Bundle-Description>jetty.websocket Integration Tests</Bundle-Description>
|
||||
<Export-Package>
|
||||
org.eclipse.jetty.websocket.jetty.tests.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}"
|
||||
</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
|
|
@ -40,7 +40,7 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class JettyWebsocketTest
|
||||
public class JettyWebSocketTest
|
||||
{
|
||||
|
||||
@WebSocket
|
|
@ -27,7 +27,7 @@ import java.util.Map;
|
|||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.websocket.core.client.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.server.Negotiation;
|
||||
|
||||
/**
|
||||
|
@ -42,8 +42,8 @@ import org.eclipse.jetty.websocket.core.server.Negotiation;
|
|||
* <li>On the server, the application layer must provide a {@link org.eclipse.jetty.websocket.core.server.WebSocketNegotiator} instance
|
||||
* to negotiate and accept websocket connections, which will return the FrameHandler instance to use from
|
||||
* {@link org.eclipse.jetty.websocket.core.server.WebSocketNegotiator#negotiate(Negotiation)}.</li>
|
||||
* <li>On the client, the application returns the FrameHandler instance to user from the {@link UpgradeRequest}
|
||||
* instance that it passes to the {@link org.eclipse.jetty.websocket.core.client.WebSocketCoreClient#connect(UpgradeRequest)} method/</li>
|
||||
* <li>On the client, the application returns the FrameHandler instance to user from the {@link ClientUpgradeRequest}
|
||||
* instance that it passes to the {@link org.eclipse.jetty.websocket.core.client.WebSocketCoreClient#connect(ClientUpgradeRequest)} method/</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Once instantiated the FrameHandler follows is used as follows:
|
||||
|
|
|
@ -64,11 +64,11 @@ import org.eclipse.jetty.websocket.core.internal.WebSocketChannel;
|
|||
import org.eclipse.jetty.websocket.core.internal.WebSocketConnection;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketCore;
|
||||
|
||||
public abstract class UpgradeRequest extends HttpRequest implements Response.CompleteListener, HttpConnectionUpgrader
|
||||
public abstract class ClientUpgradeRequest extends HttpRequest implements Response.CompleteListener, HttpConnectionUpgrader
|
||||
{
|
||||
public static UpgradeRequest from(WebSocketCoreClient webSocketClient, URI requestURI, FrameHandler frameHandler)
|
||||
public static ClientUpgradeRequest from(WebSocketCoreClient webSocketClient, URI requestURI, FrameHandler frameHandler)
|
||||
{
|
||||
return new UpgradeRequest(webSocketClient, requestURI)
|
||||
return new ClientUpgradeRequest(webSocketClient, requestURI)
|
||||
{
|
||||
@Override
|
||||
public FrameHandler getFrameHandler(WebSocketCoreClient coreClient, HttpResponse response)
|
||||
|
@ -78,7 +78,7 @@ public abstract class UpgradeRequest extends HttpRequest implements Response.Com
|
|||
};
|
||||
}
|
||||
|
||||
private static final Logger LOG = Log.getLogger(UpgradeRequest.class);
|
||||
private static final Logger LOG = Log.getLogger(ClientUpgradeRequest.class);
|
||||
protected final CompletableFuture<FrameHandler.CoreSession> futureCoreSession;
|
||||
private final WebSocketCoreClient wsClient;
|
||||
private List<UpgradeListener> upgradeListeners = new ArrayList<>();
|
||||
|
@ -91,7 +91,7 @@ public abstract class UpgradeRequest extends HttpRequest implements Response.Com
|
|||
*/
|
||||
private List<String> subProtocols = new ArrayList<>();
|
||||
|
||||
public UpgradeRequest(WebSocketCoreClient webSocketClient, URI requestURI)
|
||||
public ClientUpgradeRequest(WebSocketCoreClient webSocketClient, URI requestURI)
|
||||
{
|
||||
super(webSocketClient.getHttpClient(), new HttpConversation(), requestURI);
|
||||
|
||||
|
@ -347,11 +347,12 @@ public abstract class UpgradeRequest extends HttpRequest implements Response.Com
|
|||
try
|
||||
{
|
||||
endp.upgrade(wsConnection);
|
||||
}
|
||||
finally
|
||||
{
|
||||
futureCoreSession.complete(wsChannel);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
futureCoreSession.completeExceptionally(t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
|
@ -83,11 +83,11 @@ public class WebSocketCoreClient extends ContainerLifeCycle implements FrameHand
|
|||
|
||||
public CompletableFuture<FrameHandler.CoreSession> connect(FrameHandler frameHandler, URI wsUri) throws IOException
|
||||
{
|
||||
UpgradeRequest request = UpgradeRequest.from(this, wsUri, frameHandler);
|
||||
ClientUpgradeRequest request = ClientUpgradeRequest.from(this, wsUri, frameHandler);
|
||||
return connect(request);
|
||||
}
|
||||
|
||||
public CompletableFuture<FrameHandler.CoreSession> connect(UpgradeRequest request) throws IOException
|
||||
public CompletableFuture<FrameHandler.CoreSession> connect(ClientUpgradeRequest request) throws IOException
|
||||
{
|
||||
if (!isStarted())
|
||||
{
|
||||
|
|
|
@ -18,13 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.core.chat;
|
||||
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.core.MessageHandler;
|
||||
import org.eclipse.jetty.websocket.core.client.UpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URI;
|
||||
|
@ -34,6 +27,13 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.core.MessageHandler;
|
||||
import org.eclipse.jetty.websocket.core.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient;
|
||||
|
||||
public class ChatWebSocketClient
|
||||
{
|
||||
private static Logger LOG = Log.getLogger(ChatWebSocketClient.class);
|
||||
|
@ -51,7 +51,7 @@ public class ChatWebSocketClient
|
|||
|
||||
URI wsUri = baseWebsocketUri.resolve("/chat");
|
||||
handler = MessageHandler.from(this::onText, null);
|
||||
UpgradeRequest request = UpgradeRequest.from(client, wsUri, handler);
|
||||
ClientUpgradeRequest request = ClientUpgradeRequest.from(client, wsUri, handler);
|
||||
request.setSubProtocols("chat");
|
||||
client.connect(request).get(5, TimeUnit.SECONDS);
|
||||
handler.sendText("[" + name + ": has joined the room]", Callback.NOOP, false);
|
||||
|
|
|
@ -179,7 +179,7 @@ public class WebSocketClientServerTest
|
|||
|
||||
public void start() throws Exception
|
||||
{
|
||||
UpgradeRequest request = UpgradeRequest.from(client, baseWebSocketUri.resolve("/test"), handler);
|
||||
ClientUpgradeRequest request = ClientUpgradeRequest.from(client, baseWebSocketUri.resolve("/test"), handler);
|
||||
request.setSubProtocols("test");
|
||||
this.client.start();
|
||||
Future<FrameHandler.CoreSession> response = client.connect(request);
|
||||
|
|
Loading…
Reference in New Issue