Merge branch 'jetty-9.3.x' into release-9.3.10
This commit is contained in:
commit
f2264c96a6
|
@ -27,7 +27,6 @@ import org.eclipse.jetty.client.api.Connection;
|
|||
import org.eclipse.jetty.client.api.Destination;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.api.Response;
|
||||
import org.eclipse.jetty.client.api.Result;
|
||||
import org.eclipse.jetty.client.http.HttpConnectionOverHTTP;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
|
@ -173,24 +172,24 @@ public class HttpProxy extends ProxyConfiguration.Proxy
|
|||
connection.send(connect, result ->
|
||||
{
|
||||
// The EndPoint may have changed during the conversation, get the latest.
|
||||
EndPoint endPoint1 = (EndPoint)conversation.getAttribute(EndPoint.class.getName());
|
||||
EndPoint endPoint = (EndPoint)conversation.getAttribute(EndPoint.class.getName());
|
||||
if (result.isSucceeded())
|
||||
{
|
||||
Response response = result.getResponse();
|
||||
if (response.getStatus() == HttpStatus.OK_200)
|
||||
{
|
||||
tunnelSucceeded(endPoint1);
|
||||
tunnelSucceeded(endPoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpResponseException failure = new HttpResponseException("Unexpected " + response +
|
||||
" for " + result.getRequest(), response);
|
||||
tunnelFailed(endPoint1, failure);
|
||||
tunnelFailed(endPoint, failure);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tunnelFailed(endPoint1, result.getFailure());
|
||||
tunnelFailed(endPoint, result.getFailure());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -207,6 +206,9 @@ public class HttpProxy extends ProxyConfiguration.Proxy
|
|||
new SslClientConnectionFactory(client.getSslContextFactory(), client.getByteBufferPool(), client.getExecutor(), connectionFactory);
|
||||
HttpConnectionOverHTTP oldConnection = (HttpConnectionOverHTTP)endPoint.getConnection();
|
||||
org.eclipse.jetty.io.Connection newConnection = sslConnectionFactory.newConnection(endPoint, context);
|
||||
// Creating the connection will link the new Connection the EndPoint,
|
||||
// but we need the old Connection linked for the upgrade to do its job.
|
||||
endPoint.setConnection(oldConnection);
|
||||
endPoint.upgrade(newConnection);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("HTTP tunnel established: {} over {}", oldConnection, newConnection);
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.eclipse.jetty.client.HttpResponseException;
|
|||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
@ -165,7 +166,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
|
||||
protected void fillInterested()
|
||||
{
|
||||
getHttpChannel().getHttpConnection().fillInterested();
|
||||
getHttpConnection().fillInterested();
|
||||
}
|
||||
|
||||
private void shutdown()
|
||||
|
@ -265,7 +266,19 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
if (exchange == null)
|
||||
return false;
|
||||
|
||||
return !responseSuccess(exchange);
|
||||
boolean proceed = responseSuccess(exchange);
|
||||
if (!proceed)
|
||||
return true;
|
||||
|
||||
int status = exchange.getResponse().getStatus();
|
||||
if (status == HttpStatus.SWITCHING_PROTOCOLS_101)
|
||||
return true;
|
||||
|
||||
if (HttpMethod.CONNECT.is(exchange.getRequest().getMethod()) &&
|
||||
status == HttpStatus.OK_200)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -77,6 +77,7 @@ import org.eclipse.jetty.http.HttpHeader;
|
|||
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
|
@ -1509,6 +1510,11 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||
ContentResponse response = listener.get(5, TimeUnit.SECONDS);
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
|
||||
// Because the tunnel was successful, this connection will be
|
||||
// upgraded to an SslConnection, so it will not be fill interested.
|
||||
// This test doesn't upgrade, so it needs to restore the fill interest.
|
||||
((AbstractConnection)connection).fillInterested();
|
||||
|
||||
// Test that I can send another request on the same connection.
|
||||
request = client.newRequest(host, port);
|
||||
listener = new FutureResponseListener(request);
|
||||
|
|
|
@ -181,6 +181,7 @@ public class ForwardProxyTLSServerTest
|
|||
.scheme(HttpScheme.HTTPS.asString())
|
||||
.method(HttpMethod.GET)
|
||||
.path("/echo?body=" + URLEncoder.encode(body, "UTF-8"))
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
|
||||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
|
@ -210,6 +211,7 @@ public class ForwardProxyTLSServerTest
|
|||
.scheme(HttpScheme.HTTPS.asString())
|
||||
.method(HttpMethod.GET)
|
||||
.path("/echo?body=" + URLEncoder.encode(body, "UTF-8"))
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
|
||||
Assert.assertEquals(HttpStatus.OK_200, response1.getStatus());
|
||||
|
@ -224,6 +226,7 @@ public class ForwardProxyTLSServerTest
|
|||
.header(HttpHeader.CONTENT_TYPE, MimeTypes.Type.FORM_ENCODED.asString())
|
||||
.header(HttpHeader.CONTENT_LENGTH, String.valueOf(content.length()))
|
||||
.content(new StringContentProvider(content))
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
|
||||
Assert.assertEquals(HttpStatus.OK_200, response2.getStatus());
|
||||
|
@ -250,11 +253,11 @@ public class ForwardProxyTLSServerTest
|
|||
{
|
||||
final AtomicReference<Connection> connection = new AtomicReference<>();
|
||||
final CountDownLatch connectionLatch = new CountDownLatch(1);
|
||||
String body1 = "BODY";
|
||||
String content1 = "BODY";
|
||||
ContentResponse response1 = httpClient.newRequest("localhost", serverConnector.getLocalPort())
|
||||
.scheme(HttpScheme.HTTPS.asString())
|
||||
.method(HttpMethod.GET)
|
||||
.path("/echo?body=" + URLEncoder.encode(body1, "UTF-8"))
|
||||
.path("/echo?body=" + URLEncoder.encode(content1, "UTF-8"))
|
||||
.onRequestCommit(request ->
|
||||
{
|
||||
Destination destination = httpClient.getDestination(HttpScheme.HTTPS.asString(), "localhost", serverConnector.getLocalPort());
|
||||
|
@ -268,15 +271,16 @@ public class ForwardProxyTLSServerTest
|
|||
}
|
||||
});
|
||||
})
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
|
||||
Assert.assertEquals(HttpStatus.OK_200, response1.getStatus());
|
||||
String content = response1.getContentAsString();
|
||||
Assert.assertEquals(body1, content);
|
||||
Assert.assertEquals(content1, content);
|
||||
|
||||
Assert.assertTrue(connectionLatch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
String body2 = "body=" + body1;
|
||||
String body2 = "body=" + content1;
|
||||
org.eclipse.jetty.client.api.Request request2 = httpClient.newRequest("localhost", serverConnector.getLocalPort())
|
||||
.scheme(HttpScheme.HTTPS.asString())
|
||||
.method(HttpMethod.POST)
|
||||
|
@ -291,8 +295,8 @@ public class ForwardProxyTLSServerTest
|
|||
ContentResponse response2 = listener2.get(5, TimeUnit.SECONDS);
|
||||
|
||||
Assert.assertEquals(HttpStatus.OK_200, response2.getStatus());
|
||||
String content2 = response1.getContentAsString();
|
||||
Assert.assertEquals(body1, content2);
|
||||
String content2 = response2.getContentAsString();
|
||||
Assert.assertEquals(content1, content2);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -341,6 +345,7 @@ public class ForwardProxyTLSServerTest
|
|||
.path("/echo?body=" + URLEncoder.encode(body, "UTF-8"))
|
||||
// Long idle timeout for the request.
|
||||
.idleTimeout(10 * idleTimeout, TimeUnit.MILLISECONDS)
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
|
||||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
|
@ -372,6 +377,7 @@ public class ForwardProxyTLSServerTest
|
|||
.scheme(HttpScheme.HTTPS.asString())
|
||||
.method(HttpMethod.GET)
|
||||
.path("/echo?body=" + URLEncoder.encode(body, "UTF-8"))
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
Assert.fail();
|
||||
}
|
||||
|
@ -404,6 +410,7 @@ public class ForwardProxyTLSServerTest
|
|||
.scheme(HttpScheme.HTTPS.asString())
|
||||
.method(HttpMethod.GET)
|
||||
.path("/echo?body=" + URLEncoder.encode(body, "UTF-8"))
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
Assert.fail();
|
||||
}
|
||||
|
@ -438,6 +445,7 @@ public class ForwardProxyTLSServerTest
|
|||
{
|
||||
httpClient.newRequest("localhost", serverConnector.getLocalPort())
|
||||
.scheme(HttpScheme.HTTPS.asString())
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
Assert.fail();
|
||||
}
|
||||
|
@ -516,6 +524,7 @@ public class ForwardProxyTLSServerTest
|
|||
.scheme(HttpScheme.HTTPS.asString())
|
||||
.method(HttpMethod.GET)
|
||||
.path("/echo?body=" + URLEncoder.encode(body, "UTF-8"))
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
|
||||
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
<!-- =========================================================== -->
|
||||
<Set name="RequestLog">
|
||||
<New id="RequestLog" class="org.eclipse.jetty.server.AsyncNCSARequestLog">
|
||||
<Set name="filename"><Property name="jetty.base" default="." /><Property>
|
||||
<Set name="filename"><Property name="jetty.base" default="." />/<Property>
|
||||
<Name>jetty.requestlog.filePath</Name>
|
||||
<Deprecated>requestlog.filename</Deprecated>
|
||||
<Default><Property name="jetty.requestlog.dir" default="/logs"/>/yyyy_mm_dd.request.log</Default>
|
||||
<Default><Property name="jetty.requestlog.dir" default="logs"/>/yyyy_mm_dd.request.log</Default>
|
||||
</Property>
|
||||
</Set>
|
||||
<Set name="filenameDateFormat"><Property name="jetty.requestlog.filenameDateFormat" deprecated="requestlog.filenameDateFormat" default="yyyy_MM_dd"/></Set>
|
||||
|
|
|
@ -320,7 +320,6 @@ public class HttpChannelState
|
|||
protected Action unhandle()
|
||||
{
|
||||
Action action;
|
||||
AsyncContextEvent schedule_event=null;
|
||||
boolean read_interested=false;
|
||||
|
||||
if(DEBUG)
|
||||
|
@ -378,15 +377,17 @@ public class HttpChannelState
|
|||
}
|
||||
else
|
||||
{
|
||||
schedule_event=_event;
|
||||
read_interested=_asyncReadUnready;
|
||||
_state=State.ASYNC_WAIT;
|
||||
action=Action.WAIT;
|
||||
if (_asyncReadUnready)
|
||||
_channel.asyncReadFillInterested();
|
||||
Scheduler scheduler = _channel.getScheduler();
|
||||
if (scheduler!=null && _timeoutMs>0)
|
||||
_event.setTimeoutTask(scheduler.schedule(_event,_timeoutMs,TimeUnit.MILLISECONDS));
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPIRING:
|
||||
schedule_event=_event;
|
||||
_state=State.ASYNC_WAIT;
|
||||
action=Action.WAIT;
|
||||
break;
|
||||
|
@ -414,10 +415,6 @@ public class HttpChannelState
|
|||
}
|
||||
}
|
||||
|
||||
if (schedule_event!=null)
|
||||
scheduleTimeout(schedule_event);
|
||||
if (read_interested)
|
||||
_channel.asyncReadFillInterested();
|
||||
return action;
|
||||
}
|
||||
|
||||
|
@ -751,13 +748,6 @@ public class HttpChannelState
|
|||
_channel.execute(_channel);
|
||||
}
|
||||
|
||||
protected void scheduleTimeout(AsyncContextEvent event)
|
||||
{
|
||||
Scheduler scheduler = _channel.getScheduler();
|
||||
if (scheduler!=null && _timeoutMs>0)
|
||||
event.setTimeoutTask(scheduler.schedule(event,_timeoutMs,TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
protected void cancelTimeout()
|
||||
{
|
||||
final AsyncContextEvent event;
|
||||
|
|
|
@ -172,5 +172,9 @@ public abstract class JsrCallable extends CallableMethod
|
|||
}
|
||||
}
|
||||
|
||||
public abstract void setDecoderClass(Class<? extends Decoder> decoderClass);
|
||||
/**
|
||||
* The Type of Class a {@link Decoder} should be created to produce.
|
||||
* @param decodingType the type of class a Decoder should be created to produce
|
||||
*/
|
||||
public abstract void setDecodingType(Class<?> decodingType);
|
||||
}
|
||||
|
|
|
@ -25,12 +25,9 @@ import javax.websocket.OnMessage;
|
|||
|
||||
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.ByteArrayDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.ByteBufferDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.InputStreamDecoder;
|
||||
|
||||
/**
|
||||
* Param handling for static Binary @{@link OnMessage} parameters.
|
||||
* Param handling for static Binary @{@link javax.websocket.OnMessage} parameters.
|
||||
*/
|
||||
public class JsrParamIdBinary extends JsrParamIdOnMessage implements IJsrParamId
|
||||
{
|
||||
|
@ -48,14 +45,14 @@ public class JsrParamIdBinary extends JsrParamIdOnMessage implements IJsrParamId
|
|||
if (param.type.isAssignableFrom(ByteBuffer.class))
|
||||
{
|
||||
param.bind(Role.MESSAGE_BINARY);
|
||||
callable.setDecoderClass(ByteBufferDecoder.class);
|
||||
callable.setDecodingType(ByteBuffer.class);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (param.type.isAssignableFrom(byte[].class))
|
||||
{
|
||||
param.bind(Role.MESSAGE_BINARY);
|
||||
callable.setDecoderClass(ByteArrayDecoder.class);
|
||||
callable.setDecodingType(byte[].class);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -64,7 +61,7 @@ public class JsrParamIdBinary extends JsrParamIdOnMessage implements IJsrParamId
|
|||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_BINARY_STREAM);
|
||||
callable.setDecoderClass(InputStreamDecoder.class);
|
||||
callable.setDecodingType(InputStream.class);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
|||
import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadata;
|
||||
|
||||
/**
|
||||
* Param handling for Text or Binary @{@link OnMessage} parameters declared as {@link javax.websocket.Decoder}s
|
||||
* Param handling for Text or Binary @{@link javax.websocket.OnMessage} parameters declared as {@link javax.websocket.Decoder}s
|
||||
*/
|
||||
public class JsrParamIdDecoder extends JsrParamIdOnMessage implements IJsrParamId
|
||||
{
|
||||
|
@ -69,7 +69,8 @@ public class JsrParamIdDecoder extends JsrParamIdOnMessage implements IJsrParamI
|
|||
param.bind(Role.MESSAGE_PONG);
|
||||
break;
|
||||
}
|
||||
callable.setDecoderClass(metadata.getCoderClass());
|
||||
|
||||
callable.setDecodingType(metadata.getObjectType());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -22,7 +22,6 @@ import javax.websocket.PongMessage;
|
|||
|
||||
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.PongMessageDecoder;
|
||||
|
||||
public class JsrParamIdPong extends JsrParamIdOnMessage implements IJsrParamId
|
||||
{
|
||||
|
@ -41,7 +40,7 @@ public class JsrParamIdPong extends JsrParamIdOnMessage implements IJsrParamId
|
|||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_PONG);
|
||||
callable.setDecoderClass(PongMessageDecoder.class);
|
||||
callable.setDecodingType(PongMessage.class);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -24,19 +24,9 @@ import javax.websocket.OnMessage;
|
|||
|
||||
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.BooleanDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.ByteDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.CharacterDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.DoubleDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.FloatDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.IntegerDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.LongDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.ReaderDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.ShortDecoder;
|
||||
import org.eclipse.jetty.websocket.jsr356.decoders.StringDecoder;
|
||||
|
||||
/**
|
||||
* Param handling for static Text @{@link OnMessage} parameters
|
||||
* Param handling for static Text @{@link javax.websocket.OnMessage} parameters
|
||||
*/
|
||||
public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId
|
||||
{
|
||||
|
@ -65,7 +55,7 @@ public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId
|
|||
if (param.type.isAssignableFrom(String.class))
|
||||
{
|
||||
param.bind(Role.MESSAGE_TEXT);
|
||||
callable.setDecoderClass(StringDecoder.class);
|
||||
callable.setDecodingType(String.class);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -74,56 +64,56 @@ public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId
|
|||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_TEXT);
|
||||
callable.setDecoderClass(BooleanDecoder.class);
|
||||
callable.setDecodingType(Boolean.class);
|
||||
return true;
|
||||
}
|
||||
if (param.type.isAssignableFrom(Byte.class) || (param.type == Byte.TYPE))
|
||||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_TEXT);
|
||||
callable.setDecoderClass(ByteDecoder.class);
|
||||
callable.setDecodingType(Byte.class);
|
||||
return true;
|
||||
}
|
||||
if (param.type.isAssignableFrom(Character.class) || (param.type == Character.TYPE))
|
||||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_TEXT);
|
||||
callable.setDecoderClass(CharacterDecoder.class);
|
||||
callable.setDecodingType(Character.class);
|
||||
return true;
|
||||
}
|
||||
if (param.type.isAssignableFrom(Double.class) || (param.type == Double.TYPE))
|
||||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_TEXT);
|
||||
callable.setDecoderClass(DoubleDecoder.class);
|
||||
callable.setDecodingType(Double.class);
|
||||
return true;
|
||||
}
|
||||
if (param.type.isAssignableFrom(Float.class) || (param.type == Float.TYPE))
|
||||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_TEXT);
|
||||
callable.setDecoderClass(FloatDecoder.class);
|
||||
callable.setDecodingType(Float.class);
|
||||
return true;
|
||||
}
|
||||
if (param.type.isAssignableFrom(Integer.class) || (param.type == Integer.TYPE))
|
||||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_TEXT);
|
||||
callable.setDecoderClass(IntegerDecoder.class);
|
||||
callable.setDecodingType(Integer.class);
|
||||
return true;
|
||||
}
|
||||
if (param.type.isAssignableFrom(Long.class) || (param.type == Long.TYPE))
|
||||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_TEXT);
|
||||
callable.setDecoderClass(LongDecoder.class);
|
||||
callable.setDecodingType(Long.class);
|
||||
return true;
|
||||
}
|
||||
if (param.type.isAssignableFrom(Short.class) || (param.type == Short.TYPE))
|
||||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_TEXT);
|
||||
callable.setDecoderClass(ShortDecoder.class);
|
||||
callable.setDecodingType(Short.class);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -132,7 +122,7 @@ public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId
|
|||
{
|
||||
assertPartialMessageSupportDisabled(param,callable);
|
||||
param.bind(Role.MESSAGE_TEXT_STREAM);
|
||||
callable.setDecoderClass(ReaderDecoder.class);
|
||||
callable.setDecodingType(Reader.class);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -150,7 +140,7 @@ public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId
|
|||
else
|
||||
{
|
||||
param.bind(Role.MESSAGE_TEXT);
|
||||
callable.setDecoderClass(BooleanDecoder.class);
|
||||
callable.setDecodingType(Boolean.class);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.lang.reflect.Method;
|
|||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.CloseReason.CloseCodes;
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.OnClose;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||
|
@ -30,7 +29,7 @@ import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
|||
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
||||
|
||||
/**
|
||||
* Callable for {@link OnClose} annotated methods
|
||||
* Callable for {@link javax.websocket.OnClose} annotated methods
|
||||
*/
|
||||
public class OnCloseCallable extends JsrCallable
|
||||
{
|
||||
|
@ -83,7 +82,7 @@ public class OnCloseCallable extends JsrCallable
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setDecoderClass(Class<? extends Decoder> decoderClass)
|
||||
public void setDecodingType(Class<?> decodingType)
|
||||
{
|
||||
/* ignore, not relevant for onClose */
|
||||
}
|
||||
|
|
|
@ -67,9 +67,8 @@ public class OnErrorCallable extends JsrCallable
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setDecoderClass(Class<? extends Decoder> decoderClass)
|
||||
public void setDecodingType(Class<?> decodingType)
|
||||
{
|
||||
/* ignore, not relevant for onClose */
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,9 +29,9 @@ import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
|||
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
||||
|
||||
/**
|
||||
* Callable for {@link OnMessage} annotated methods with a whole or partial binary messages.
|
||||
* Callable for {@link javax.websocket.OnMessage} annotated methods with a whole or partial binary messages.
|
||||
* <p>
|
||||
* Not for use with {@link java.io.InputStream} based {@link OnMessage} method objects.
|
||||
* Not for use with {@link java.io.InputStream} based {@link javax.websocket.OnMessage} method objects.
|
||||
*
|
||||
* @see javax.websocket.Decoder.Binary
|
||||
*/
|
||||
|
|
|
@ -26,7 +26,6 @@ import javax.websocket.Encoder;
|
|||
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
|
||||
import org.eclipse.jetty.websocket.common.util.ReflectUtils;
|
||||
import org.eclipse.jetty.websocket.jsr356.EncoderFactory;
|
||||
import org.eclipse.jetty.websocket.jsr356.InitException;
|
||||
import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
||||
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
||||
|
||||
|
@ -34,7 +33,7 @@ public class OnMessageCallable extends JsrCallable
|
|||
{
|
||||
protected final Class<?> returnType;
|
||||
protected Encoder returnEncoder;
|
||||
protected Class<? extends Decoder> decoderClass;
|
||||
protected Class<?> decodingType;
|
||||
protected Decoder decoder;
|
||||
protected int idxPartialMessageFlag = -1;
|
||||
protected int idxMessageObject = -1;
|
||||
|
@ -50,7 +49,7 @@ public class OnMessageCallable extends JsrCallable
|
|||
{
|
||||
super(copy);
|
||||
this.returnType = copy.returnType;
|
||||
this.decoderClass = copy.decoderClass;
|
||||
this.decodingType = copy.decodingType;
|
||||
this.decoder = copy.decoder;
|
||||
this.idxPartialMessageFlag = copy.idxPartialMessageFlag;
|
||||
this.idxMessageObject = copy.idxMessageObject;
|
||||
|
@ -93,11 +92,6 @@ public class OnMessageCallable extends JsrCallable
|
|||
return decoder;
|
||||
}
|
||||
|
||||
public Class<? extends Decoder> getDecoderClass()
|
||||
{
|
||||
return decoderClass;
|
||||
}
|
||||
|
||||
public Param getMessageObjectParam()
|
||||
{
|
||||
if (idxMessageObject < 0)
|
||||
|
@ -138,16 +132,9 @@ public class OnMessageCallable extends JsrCallable
|
|||
this.returnEncoder = encoderWrapper.getEncoder();
|
||||
}
|
||||
|
||||
if (decoderClass != null)
|
||||
if (decodingType != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.decoder = decoderClass.newInstance();
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException e)
|
||||
{
|
||||
throw new InitException("Unable to create decoder: " + decoderClass.getName(),e);
|
||||
}
|
||||
this.decoder = session.getDecoderFactory().getDecoderFor(decodingType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,9 +149,9 @@ public class OnMessageCallable extends JsrCallable
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setDecoderClass(Class<? extends Decoder> decoderClass)
|
||||
public void setDecodingType(Class<?> decodingType)
|
||||
{
|
||||
this.decoderClass = decoderClass;
|
||||
this.decodingType = decodingType;
|
||||
messageRoleAssigned = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@ import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
|||
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
||||
|
||||
/**
|
||||
* Callable for {@link OnMessage} annotated methods with a whole or partial text messages.
|
||||
* Callable for {@link javax.websocket.OnMessage} annotated methods with a whole or partial text messages.
|
||||
* <p>
|
||||
* Not for use with {@link Reader} based {@link OnMessage} method objects.
|
||||
* Not for use with {@link java.io.Reader} based {@link javax.websocket.OnMessage} method objects.
|
||||
*
|
||||
* @see javax.websocket.Decoder.Text
|
||||
*/
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.eclipse.jetty.websocket.jsr356.annotations;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.OnOpen;
|
||||
|
||||
|
@ -28,7 +27,7 @@ import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
|||
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
||||
|
||||
/**
|
||||
* Callable for {@link OnOpen} annotated methods
|
||||
* Callable for {@link javax.websocket.OnOpen} annotated methods
|
||||
*/
|
||||
public class OnOpenCallable extends JsrCallable
|
||||
{
|
||||
|
@ -63,7 +62,7 @@ public class OnOpenCallable extends JsrCallable
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setDecoderClass(Class<? extends Decoder> decoderClass)
|
||||
public void setDecodingType(Class<?> decodingType)
|
||||
{
|
||||
/* ignore, not relevant for onClose */
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ public class TimeDecoder implements Decoder.Text<Date>
|
|||
@Override
|
||||
public void init(EndpointConfig config)
|
||||
{
|
||||
System.out.println("#### INIT ####");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,13 +25,21 @@ import java.io.PrintWriter;
|
|||
import java.io.StringWriter;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.websocket.DecodeException;
|
||||
import javax.websocket.Decoder;
|
||||
import javax.websocket.EndpointConfig;
|
||||
import javax.websocket.Extension;
|
||||
import javax.websocket.HandshakeResponse;
|
||||
import javax.websocket.OnMessage;
|
||||
|
@ -178,11 +186,20 @@ public class ConfiguratorTest
|
|||
int upgradeNum = upgradeCount.addAndGet(1);
|
||||
LOG.debug("Upgrade Num: {}", upgradeNum);
|
||||
sec.getUserProperties().put("upgradeNum", Integer.toString(upgradeNum));
|
||||
switch(upgradeNum) {
|
||||
case 1: sec.getUserProperties().put("apple", "fruit from tree"); break;
|
||||
case 2: sec.getUserProperties().put("blueberry", "fruit from bush"); break;
|
||||
case 3: sec.getUserProperties().put("strawberry", "fruit from annual"); break;
|
||||
default: sec.getUserProperties().put("fruit"+upgradeNum, "placeholder"); break;
|
||||
switch (upgradeNum)
|
||||
{
|
||||
case 1:
|
||||
sec.getUserProperties().put("apple", "fruit from tree");
|
||||
break;
|
||||
case 2:
|
||||
sec.getUserProperties().put("blueberry", "fruit from bush");
|
||||
break;
|
||||
case 3:
|
||||
sec.getUserProperties().put("strawberry", "fruit from annual");
|
||||
break;
|
||||
default:
|
||||
sec.getUserProperties().put("fruit" + upgradeNum, "placeholder");
|
||||
break;
|
||||
}
|
||||
|
||||
super.modifyHandshake(sec, request, response);
|
||||
|
@ -249,6 +266,84 @@ public class ConfiguratorTest
|
|||
}
|
||||
}
|
||||
|
||||
public static class SelectedProtocolConfigurator extends ServerEndpointConfig.Configurator
|
||||
{
|
||||
@Override
|
||||
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response)
|
||||
{
|
||||
List<String> selectedProtocol = response.getHeaders().get("Sec-WebSocket-Protocol");
|
||||
String protocol = "<>";
|
||||
if (selectedProtocol != null || !selectedProtocol.isEmpty())
|
||||
protocol = selectedProtocol.get(0);
|
||||
config.getUserProperties().put("selected-subprotocol", protocol);
|
||||
}
|
||||
}
|
||||
|
||||
public static class GmtTimeDecoder implements Decoder.Text<Calendar>
|
||||
{
|
||||
private TimeZone TZ;
|
||||
|
||||
@Override
|
||||
public Calendar decode(String s) throws DecodeException
|
||||
{
|
||||
if (TZ == null)
|
||||
throw new DecodeException(s, ".init() not called");
|
||||
try
|
||||
{
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormat.setTimeZone(TZ);
|
||||
Date time = dateFormat.parse(s);
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTimeZone(TZ);
|
||||
cal.setTime(time);
|
||||
return cal;
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
throw new DecodeException(s, "Unable to decode Time", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(EndpointConfig config)
|
||||
{
|
||||
TZ = TimeZone.getTimeZone("GMT+0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willDecode(String s)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ServerEndpoint(value = "/timedecoder",
|
||||
subprotocols = { "time", "gmt" },
|
||||
configurator = SelectedProtocolConfigurator.class,
|
||||
decoders = {GmtTimeDecoder.class})
|
||||
public static class TimeDecoderSocket
|
||||
{
|
||||
private TimeZone TZ = TimeZone.getTimeZone("GMT+0");
|
||||
|
||||
@OnMessage
|
||||
public String onMessage(Calendar cal)
|
||||
{
|
||||
return String.format("cal=%s", newDateFormat().format(cal.getTime()));
|
||||
}
|
||||
|
||||
private SimpleDateFormat newDateFormat()
|
||||
{
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss Z");
|
||||
dateFormat.setTimeZone(TZ);
|
||||
return dateFormat;
|
||||
}
|
||||
}
|
||||
|
||||
private static Server server;
|
||||
private static URI baseServerUri;
|
||||
|
||||
|
@ -271,6 +366,7 @@ public class ConfiguratorTest
|
|||
container.addEndpoint(ProtocolsSocket.class);
|
||||
container.addEndpoint(UniqueUserPropsSocket.class);
|
||||
container.addEndpoint(AddressSocket.class);
|
||||
container.addEndpoint(TimeDecoderSocket.class);
|
||||
|
||||
server.start();
|
||||
String host = connector.getHost();
|
||||
|
@ -511,4 +607,26 @@ public class ConfiguratorTest
|
|||
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of Sec-WebSocket-Protocol, using non-spec case header
|
||||
*/
|
||||
@Test
|
||||
public void testDecoderWithProtocol() throws Exception
|
||||
{
|
||||
URI uri = baseServerUri.resolve("/timedecoder");
|
||||
|
||||
try (BlockheadClient client = new BlockheadClient(uri))
|
||||
{
|
||||
client.addHeader("Sec-Websocket-Protocol: gmt\r\n");
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
client.write(new TextFrame().setPayload("2016-06-20T14:27:44"));
|
||||
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
|
||||
WebSocketFrame frame = frames.poll();
|
||||
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("cal=2016.06.20 AD at 14:27:44 +0000"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue