Merge branch 'jetty-10.0.x' into jetty-11.0.x
This commit is contained in:
commit
27e431ce41
|
@ -85,10 +85,6 @@
|
|||
<artifactId>jetty-annotations</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
|
@ -112,7 +108,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -16,6 +16,15 @@
|
|||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.example-async-rest</groupId>
|
||||
<artifactId>example-async-rest-jar</artifactId>
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -30,7 +30,15 @@
|
|||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-server</artifactId>
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -51,6 +51,15 @@
|
|||
<artifactId>jetty-alpn-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-server</artifactId>
|
||||
|
|
|
@ -44,6 +44,15 @@
|
|||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -69,6 +69,10 @@
|
|||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-commons</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.transaction</groupId>
|
||||
|
@ -86,5 +90,10 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -78,5 +78,14 @@
|
|||
<artifactId>jetty-annotations</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -32,6 +32,15 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
|
|
@ -146,6 +146,19 @@ public abstract class AbstractConnectionPool implements ConnectionPool, Dumpable
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(Connection connection)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int count = connections.getLo();
|
||||
if (count >= maxConnections)
|
||||
return false;
|
||||
if (connections.compareAndSetLo(count, count + 1))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void onCreated(Connection connection);
|
||||
|
||||
protected void proceed()
|
||||
|
|
|
@ -52,6 +52,14 @@ public interface ConnectionPool extends Closeable
|
|||
*/
|
||||
Connection acquire();
|
||||
|
||||
/**
|
||||
* <p>Accepts the given connection to be managed by this ConnectionPool.</p>
|
||||
*
|
||||
* @param connection the connection to accept
|
||||
* @return whether the connection has been accepted
|
||||
*/
|
||||
boolean accept(Connection connection);
|
||||
|
||||
/**
|
||||
* <p>Returns the given connection, previously obtained via {@link #acquire()},
|
||||
* back to this ConnectionPool.</p>
|
||||
|
|
|
@ -216,6 +216,7 @@ public class HttpClient extends ContainerLifeCycle
|
|||
handlers.put(new RedirectProtocolHandler(this));
|
||||
handlers.put(new WWWAuthenticationProtocolHandler(this));
|
||||
handlers.put(new ProxyAuthenticationProtocolHandler(this));
|
||||
handlers.put(new UpgradeProtocolHandler());
|
||||
|
||||
decoderFactories.add(new GZIPContentDecoder.Factory(byteBufferPool));
|
||||
|
||||
|
@ -523,7 +524,7 @@ public class HttpClient extends ContainerLifeCycle
|
|||
return new Origin(scheme, host, port, request.getTag(), protocol);
|
||||
}
|
||||
|
||||
HttpDestination resolveDestination(Origin origin)
|
||||
public HttpDestination resolveDestination(Origin origin)
|
||||
{
|
||||
return destinations.computeIfAbsent(origin, o ->
|
||||
{
|
||||
|
|
|
@ -80,6 +80,11 @@ public abstract class HttpDestination extends ContainerLifeCycle implements Dest
|
|||
|
||||
this.timeout = new TimeoutTask(client.getScheduler());
|
||||
|
||||
String host = HostPort.normalizeHost(getHost());
|
||||
if (!client.isDefaultPort(getScheme(), getPort()))
|
||||
host += ":" + getPort();
|
||||
hostField = new HttpField(HttpHeader.HOST, host);
|
||||
|
||||
ProxyConfiguration proxyConfig = client.getProxyConfiguration();
|
||||
proxy = proxyConfig.match(origin);
|
||||
ClientConnectionFactory connectionFactory = client.getTransport();
|
||||
|
@ -98,11 +103,11 @@ public abstract class HttpDestination extends ContainerLifeCycle implements Dest
|
|||
if (tag instanceof ClientConnectionFactory.Decorator)
|
||||
connectionFactory = ((ClientConnectionFactory.Decorator)tag).apply(connectionFactory);
|
||||
this.connectionFactory = connectionFactory;
|
||||
}
|
||||
|
||||
String host = HostPort.normalizeHost(getHost());
|
||||
if (!client.isDefaultPort(getScheme(), getPort()))
|
||||
host += ":" + getPort();
|
||||
hostField = new HttpField(HttpHeader.HOST, host);
|
||||
public void accept(Connection connection)
|
||||
{
|
||||
connectionPool.accept(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -497,7 +502,7 @@ public abstract class HttpDestination extends ContainerLifeCycle implements Dest
|
|||
{
|
||||
return String.format("%s[%s]@%x%s,queue=%d,pool=%s",
|
||||
HttpDestination.class.getSimpleName(),
|
||||
asString(),
|
||||
getOrigin(),
|
||||
hashCode(),
|
||||
proxy == null ? "" : "(via " + proxy + ")",
|
||||
exchanges.size(),
|
||||
|
|
|
@ -50,6 +50,11 @@ public class HttpExchange
|
|||
conversation.updateResponseListeners(null);
|
||||
}
|
||||
|
||||
public HttpDestination getHttpDestination()
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
|
||||
public HttpConversation getConversation()
|
||||
{
|
||||
return request.getConversation();
|
||||
|
|
|
@ -59,7 +59,7 @@ import org.slf4j.LoggerFactory;
|
|||
*/
|
||||
public abstract class HttpSender implements AsyncContentProvider.Listener
|
||||
{
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(HttpSender.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HttpSender.class);
|
||||
|
||||
private final AtomicReference<RequestState> requestState = new AtomicReference<>(RequestState.QUEUED);
|
||||
private final AtomicReference<SenderState> senderState = new AtomicReference<>(SenderState.IDLE);
|
||||
|
@ -363,11 +363,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
|
|||
catch (RejectedExecutionException x)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
if (x != failure)
|
||||
x.addSuppressed(failure);
|
||||
LOG.debug("Exchange aborted {}", exchange, x);
|
||||
}
|
||||
abort(exchange, failure);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,15 +18,48 @@
|
|||
|
||||
package org.eclipse.jetty.client;
|
||||
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
||||
/**
|
||||
* <p>HttpUpgrader prepares a HTTP request to upgrade from one protocol to another,
|
||||
* and implements the upgrade mechanism.</p>
|
||||
* <p>The upgrade mechanism can be the
|
||||
* <a href="https://tools.ietf.org/html/rfc7230#section-6.7">HTTP/1.1 upgrade mechanism</a>
|
||||
* or the
|
||||
* <a href="https://tools.ietf.org/html/rfc8441#section-4">HTTP/2 extended CONNECT mechanism</a>.</p>
|
||||
* <p>Given the differences among mechanism implementations, a request needs to be
|
||||
* prepared before being sent to comply with the mechanism requirements (for example,
|
||||
* add required headers, etc.).</p>
|
||||
*/
|
||||
public interface HttpUpgrader
|
||||
{
|
||||
/**
|
||||
* <p>Prepares the request for the upgrade, for example by setting the HTTP method
|
||||
* or by setting HTTP headers required for the upgrade.</p>
|
||||
*
|
||||
* @param request the request to prepare
|
||||
*/
|
||||
public void prepare(HttpRequest request);
|
||||
|
||||
public void upgrade(HttpResponse response, EndPoint endPoint);
|
||||
/**
|
||||
* <p>Upgrades the given {@code endPoint} to a different protocol.</p>
|
||||
* <p>The success or failure of the upgrade should be communicated via the given {@code callback}.</p>
|
||||
* <p>An exception thrown by this method is equivalent to failing the callback.</p>
|
||||
*
|
||||
* @param response the response with the information about the upgrade
|
||||
* @param endPoint the EndPoint to upgrade
|
||||
* @param callback a callback to notify of the success or failure of the upgrade
|
||||
*/
|
||||
public void upgrade(HttpResponse response, EndPoint endPoint, Callback callback);
|
||||
|
||||
/**
|
||||
* <p>A factory for {@link HttpUpgrader}s.</p>
|
||||
* <p>A {@link Request} subclass should implement this interface
|
||||
* if it wants to create a specific HttpUpgrader.</p>
|
||||
*/
|
||||
public interface Factory
|
||||
{
|
||||
public HttpUpgrader newHttpUpgrader(HttpVersion version);
|
||||
|
|
|
@ -85,6 +85,25 @@ public class MultiplexConnectionPool extends AbstractConnectionPool implements C
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(Connection connection)
|
||||
{
|
||||
boolean accepted = super.accept(connection);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Accepted {} {}", accepted, connection);
|
||||
if (accepted)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
Holder holder = new Holder(connection);
|
||||
activeConnections.put(connection, holder);
|
||||
++holder.count;
|
||||
}
|
||||
active(connection);
|
||||
}
|
||||
return accepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive(Connection connection)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
||||
/**
|
||||
* <p>A protocol handler that handles HTTP 101 responses.</p>
|
||||
*/
|
||||
public class UpgradeProtocolHandler implements ProtocolHandler
|
||||
{
|
||||
private final List<String> protocols = List.of("websocket", "h2c");
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "upgrade";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(Request request, Response response)
|
||||
{
|
||||
boolean upgraded = HttpStatus.SWITCHING_PROTOCOLS_101 == response.getStatus();
|
||||
boolean accepted = false;
|
||||
if (upgraded)
|
||||
accepted = acceptHeaders(request, response);
|
||||
return upgraded && accepted;
|
||||
}
|
||||
|
||||
protected boolean acceptHeaders(Request request, Response response)
|
||||
{
|
||||
HttpField responseUpgrade = response.getHeaders().getField(HttpHeader.UPGRADE);
|
||||
if (responseUpgrade != null && protocols.stream().anyMatch(responseUpgrade::contains))
|
||||
return true;
|
||||
// The response may not contain the Upgrade header, so check the request.
|
||||
HttpField requestUpgrade = request.getHeaders().getField(HttpHeader.UPGRADE);
|
||||
return requestUpgrade != null && protocols.stream().anyMatch(requestUpgrade::contains);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response.Listener getResponseListener()
|
||||
{
|
||||
return new Response.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onComplete(Result result)
|
||||
{
|
||||
HttpResponse response = (HttpResponse)result.getResponse();
|
||||
HttpRequest request = (HttpRequest)response.getRequest();
|
||||
if (result.isSucceeded())
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpConversation conversation = request.getConversation();
|
||||
HttpUpgrader upgrader = (HttpUpgrader)conversation.getAttribute(HttpUpgrader.class.getName());
|
||||
if (upgrader == null)
|
||||
throw new HttpResponseException("101 response without " + HttpUpgrader.class.getSimpleName(), response);
|
||||
EndPoint endPoint = (EndPoint)conversation.getAttribute(EndPoint.class.getName());
|
||||
if (endPoint == null)
|
||||
throw new HttpResponseException("Upgrade without " + EndPoint.class.getSimpleName(), response);
|
||||
upgrader.upgrade(response, endPoint, Callback.from(Callback.NOOP::succeeded, x -> forwardFailureComplete(request, null, response, x)));
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
forwardFailureComplete(request, null, response, x);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardFailureComplete(request, result.getRequestFailure(), response, result.getResponseFailure());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void forwardFailureComplete(HttpRequest request, Throwable requestFailure, Response response, Throwable responseFailure)
|
||||
{
|
||||
HttpConversation conversation = request.getConversation();
|
||||
conversation.updateResponseListeners(null);
|
||||
List<Response.ResponseListener> responseListeners = conversation.getResponseListeners();
|
||||
ResponseNotifier notifier = new ResponseNotifier();
|
||||
notifier.forwardFailure(responseListeners, response, responseFailure);
|
||||
notifier.notifyComplete(responseListeners, new Result(request, requestFailure, response, responseFailure));
|
||||
}
|
||||
}
|
|
@ -109,10 +109,7 @@ public class HttpClientTransportDynamic extends AbstractConnectorHttpClientTrans
|
|||
.distinct()
|
||||
.map(p -> p.toLowerCase(Locale.ENGLISH))
|
||||
.collect(Collectors.toList());
|
||||
for (ClientConnectionFactory.Info factoryInfo : factoryInfos)
|
||||
{
|
||||
addBean(factoryInfo);
|
||||
}
|
||||
Arrays.stream(factoryInfos).forEach(this::addBean);
|
||||
setConnectionPoolFactory(destination ->
|
||||
new MultiplexConnectionPool(destination, destination.getHttpClient().getMaxConnectionsPerDestination(), destination, 1));
|
||||
}
|
||||
|
@ -133,13 +130,22 @@ public class HttpClientTransportDynamic extends AbstractConnectorHttpClientTrans
|
|||
}
|
||||
else
|
||||
{
|
||||
// Preserve the order of protocols chosen by the application.
|
||||
// We need to keep multiple protocols in case the protocol
|
||||
// is negotiated: e.g. [http/1.1, h2] negotiates [h2], but
|
||||
// here we don't know yet what will be negotiated.
|
||||
protocols = this.protocols.stream()
|
||||
.filter(p -> p.equals(http1) || p.equals(http2))
|
||||
.collect(Collectors.toList());
|
||||
if (ssl)
|
||||
{
|
||||
// There may be protocol negotiation, so preserve the order
|
||||
// of protocols chosen by the application.
|
||||
// We need to keep multiple protocols in case the protocol
|
||||
// is negotiated: e.g. [http/1.1, h2] negotiates [h2], but
|
||||
// here we don't know yet what will be negotiated.
|
||||
protocols = this.protocols.stream()
|
||||
.filter(p -> p.equals(http1) || p.equals(http2))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pick the first.
|
||||
protocols = List.of(this.protocols.get(0));
|
||||
}
|
||||
}
|
||||
Origin.Protocol protocol = null;
|
||||
if (!protocols.isEmpty())
|
||||
|
@ -179,6 +185,15 @@ public class HttpClientTransportDynamic extends AbstractConnectorHttpClientTrans
|
|||
return factoryInfo.getClientConnectionFactory().newConnection(endPoint, context);
|
||||
}
|
||||
|
||||
public void upgrade(EndPoint endPoint, Map<String, Object> context)
|
||||
{
|
||||
HttpDestination destination = (HttpDestination)context.get(HTTP_DESTINATION_CONTEXT_KEY);
|
||||
Origin.Protocol protocol = destination.getOrigin().getProtocol();
|
||||
Info info = findClientConnectionFactoryInfo(protocol.getProtocols())
|
||||
.orElseThrow(() -> new IllegalStateException("Cannot find " + ClientConnectionFactory.class.getSimpleName() + " to upgrade to " + protocol));
|
||||
info.upgrade(endPoint, context);
|
||||
}
|
||||
|
||||
protected Connection newNegotiatedConnection(EndPoint endPoint, Map<String, Object> context) throws IOException
|
||||
{
|
||||
try
|
||||
|
|
|
@ -18,15 +18,10 @@
|
|||
|
||||
package org.eclipse.jetty.client.http;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
import org.eclipse.jetty.client.HttpChannel;
|
||||
import org.eclipse.jetty.client.HttpExchange;
|
||||
import org.eclipse.jetty.client.HttpRequest;
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
import org.eclipse.jetty.client.HttpResponseException;
|
||||
import org.eclipse.jetty.client.HttpUpgrader;
|
||||
import org.eclipse.jetty.client.api.Response;
|
||||
import org.eclipse.jetty.client.api.Result;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
|
@ -92,37 +87,6 @@ public class HttpChannelOverHTTP extends HttpChannel
|
|||
connection.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result exchangeTerminating(HttpExchange exchange, Result result)
|
||||
{
|
||||
if (result.isFailed())
|
||||
return result;
|
||||
|
||||
HttpResponse response = exchange.getResponse();
|
||||
if (response.getVersion() == HttpVersion.HTTP_1_1 && response.getStatus() == HttpStatus.SWITCHING_PROTOCOLS_101)
|
||||
{
|
||||
String header = response.getHeaders().get(HttpHeader.CONNECTION);
|
||||
if (header == null || !header.toLowerCase(Locale.US).contains("upgrade"))
|
||||
return new Result(result, new HttpResponseException("101 response without 'Connection: Upgrade'", response));
|
||||
|
||||
HttpRequest request = exchange.getRequest();
|
||||
HttpUpgrader upgrader = (HttpUpgrader)request.getConversation().getAttribute(HttpUpgrader.class.getName());
|
||||
if (upgrader == null)
|
||||
return new Result(result, new HttpResponseException("101 response without " + HttpUpgrader.class.getSimpleName(), response));
|
||||
|
||||
try
|
||||
{
|
||||
upgrader.upgrade(response, getHttpConnection().getEndPoint());
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
return new Result(result, new HttpResponseException("Could not upgrade to WebSocket", response, x));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void receive()
|
||||
{
|
||||
inMessages.increment();
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.concurrent.atomic.LongAdder;
|
|||
|
||||
import org.eclipse.jetty.client.HttpClientTransport;
|
||||
import org.eclipse.jetty.client.HttpConnection;
|
||||
import org.eclipse.jetty.client.HttpConversation;
|
||||
import org.eclipse.jetty.client.HttpDestination;
|
||||
import org.eclipse.jetty.client.HttpExchange;
|
||||
import org.eclipse.jetty.client.HttpProxy;
|
||||
|
@ -39,6 +40,7 @@ import org.eclipse.jetty.client.SendFailure;
|
|||
import org.eclipse.jetty.client.api.Connection;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.api.Response;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
@ -277,17 +279,35 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements IConne
|
|||
protected void normalizeRequest(Request request)
|
||||
{
|
||||
super.normalizeRequest(request);
|
||||
|
||||
if (request instanceof HttpProxy.TunnelRequest)
|
||||
{
|
||||
long connectTimeout = getHttpClient().getConnectTimeout();
|
||||
request.timeout(connectTimeout, TimeUnit.MILLISECONDS)
|
||||
.idleTimeout(2 * connectTimeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
if (request instanceof HttpUpgrader.Factory)
|
||||
|
||||
HttpRequest httpRequest = (HttpRequest)request;
|
||||
HttpConversation conversation = httpRequest.getConversation();
|
||||
HttpUpgrader upgrader = (HttpUpgrader)conversation.getAttribute(HttpUpgrader.class.getName());
|
||||
if (upgrader == null)
|
||||
{
|
||||
HttpUpgrader upgrader = ((HttpUpgrader.Factory)request).newHttpUpgrader(HttpVersion.HTTP_1_1);
|
||||
((HttpRequest)request).getConversation().setAttribute(HttpUpgrader.class.getName(), upgrader);
|
||||
upgrader.prepare((HttpRequest)request);
|
||||
if (request instanceof HttpUpgrader.Factory)
|
||||
{
|
||||
upgrader = ((HttpUpgrader.Factory)request).newHttpUpgrader(HttpVersion.HTTP_1_1);
|
||||
conversation.setAttribute(HttpUpgrader.class.getName(), upgrader);
|
||||
upgrader.prepare(httpRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
String protocol = request.getHeaders().get(HttpHeader.UPGRADE);
|
||||
if (protocol != null)
|
||||
{
|
||||
upgrader = new ProtocolHttpUpgrader(getHttpDestination(), protocol);
|
||||
conversation.setAttribute(HttpUpgrader.class.getName(), upgrader);
|
||||
upgrader.prepare(httpRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -285,12 +285,8 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
|||
if (exchange == null)
|
||||
return false;
|
||||
|
||||
if (HttpMethod.CONNECT.is(exchange.getRequest().getMethod()))
|
||||
{
|
||||
// Store the EndPoint even in case of non-200 responses.
|
||||
exchange.getRequest().getConversation().setAttribute(EndPoint.class.getName(), getHttpConnection().getEndPoint());
|
||||
}
|
||||
|
||||
// Store the EndPoint is case of upgrades, tunnels, etc.
|
||||
exchange.getRequest().getConversation().setAttribute(EndPoint.class.getName(), getHttpConnection().getEndPoint());
|
||||
return !responseHeaders(exchange);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,9 +35,13 @@ import org.eclipse.jetty.io.EndPoint;
|
|||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.IteratingCallback;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class HttpSenderOverHTTP extends HttpSender
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HttpSenderOverHTTP.class);
|
||||
|
||||
private final HttpGenerator generator = new HttpGenerator();
|
||||
private boolean shutdown;
|
||||
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.client.http;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.HttpClientTransport;
|
||||
import org.eclipse.jetty.client.HttpDestination;
|
||||
import org.eclipse.jetty.client.HttpRequest;
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
import org.eclipse.jetty.client.HttpResponseException;
|
||||
import org.eclipse.jetty.client.HttpUpgrader;
|
||||
import org.eclipse.jetty.client.Origin;
|
||||
import org.eclipse.jetty.client.dynamic.HttpClientTransportDynamic;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>A HttpUpgrader that upgrades to a given protocol.</p>
|
||||
* <p>Works in conjunction with {@link HttpClientTransportDynamic}
|
||||
* so that the protocol to upgrade to must be one of the application
|
||||
* protocols supported by HttpClientTransportDynamic.</p>
|
||||
* <p></p>
|
||||
*/
|
||||
public class ProtocolHttpUpgrader implements HttpUpgrader
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ProtocolHttpUpgrader.class);
|
||||
|
||||
private final HttpDestination destination;
|
||||
private final String protocol;
|
||||
|
||||
public ProtocolHttpUpgrader(HttpDestination destination, String protocol)
|
||||
{
|
||||
this.destination = destination;
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare(HttpRequest request)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(HttpResponse response, EndPoint endPoint, Callback callback)
|
||||
{
|
||||
if (response.getHeaders().contains(HttpHeader.UPGRADE, protocol))
|
||||
{
|
||||
HttpClient httpClient = destination.getHttpClient();
|
||||
HttpClientTransport transport = httpClient.getTransport();
|
||||
if (transport instanceof HttpClientTransportDynamic)
|
||||
{
|
||||
HttpClientTransportDynamic dynamicTransport = (HttpClientTransportDynamic)transport;
|
||||
|
||||
Origin origin = destination.getOrigin();
|
||||
Origin newOrigin = new Origin(origin.getScheme(), origin.getAddress(), origin.getTag(), new Origin.Protocol(List.of(protocol), false));
|
||||
HttpDestination newDestination = httpClient.resolveDestination(newOrigin);
|
||||
|
||||
Map<String, Object> context = new HashMap<>();
|
||||
context.put(HttpClientTransport.HTTP_DESTINATION_CONTEXT_KEY, newDestination);
|
||||
context.put(HttpResponse.class.getName(), response);
|
||||
context.put(HttpClientTransport.HTTP_CONNECTION_PROMISE_CONTEXT_KEY, Promise.from(y -> callback.succeeded(), callback::failed));
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Upgrading {} on {}", response.getRequest(), endPoint);
|
||||
|
||||
dynamicTransport.upgrade(endPoint, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback.failed(new HttpResponseException(HttpClientTransportDynamic.class.getName() + " required to upgrade to: " + protocol, response));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
callback.failed(new HttpResponseException("Not an upgrade to: " + protocol, response));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ package org.eclipse.jetty.client.http;
|
|||
|
||||
import java.io.EOFException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
@ -96,7 +96,7 @@ public class HttpReceiverOverHTTPTest
|
|||
{
|
||||
HttpRequest request = (HttpRequest)client.newRequest("http://localhost");
|
||||
FutureResponseListener listener = new FutureResponseListener(request);
|
||||
HttpExchange exchange = new HttpExchange(destination, request, Collections.<Response.ResponseListener>singletonList(listener));
|
||||
HttpExchange exchange = new HttpExchange(destination, request, List.of(listener));
|
||||
boolean associated = connection.getHttpChannel().associate(exchange);
|
||||
assertTrue(associated);
|
||||
exchange.requestComplete(null);
|
||||
|
|
|
@ -63,7 +63,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.cloud</groupId>
|
||||
<artifactId>google-cloud-datastore</artifactId>
|
||||
|
@ -80,6 +84,11 @@
|
|||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
|
|
@ -38,6 +38,15 @@
|
|||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
|
|
|
@ -633,7 +633,7 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
|
|
|
@ -35,6 +35,22 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jul-to-slf4j</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.xml</groupId>
|
||||
<artifactId>jaxws-api</artifactId>
|
||||
|
|
|
@ -16,11 +16,19 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.client.http;
|
||||
package org.eclipse.jetty.http.spi;
|
||||
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
|
||||
public interface HttpConnectionUpgrader
|
||||
public final class LoggingUtil
|
||||
{
|
||||
public void upgrade(HttpResponse response, HttpConnectionOverHTTP connection);
|
||||
/**
|
||||
* It's easier to setup logging in code for this test project,
|
||||
* then it is to setup the various system properties and files for every test
|
||||
* execution (maven, CI, and IDE).
|
||||
*/
|
||||
public static void init()
|
||||
{
|
||||
// Wire up java.util.logging (used by javax.xml.soap others) to slf4j.
|
||||
org.slf4j.bridge.SLF4JBridgeHandler.removeHandlersForRootLogger();
|
||||
org.slf4j.bridge.SLF4JBridgeHandler.install();
|
||||
}
|
||||
}
|
|
@ -44,6 +44,11 @@ import static org.hamcrest.Matchers.is;
|
|||
|
||||
public class SPIServerTest
|
||||
{
|
||||
static
|
||||
{
|
||||
LoggingUtil.init();
|
||||
}
|
||||
|
||||
String host = "localhost";
|
||||
HttpServer server;
|
||||
int port;
|
||||
|
|
|
@ -41,6 +41,10 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
public class TestEndpointMultiplePublishProblem
|
||||
{
|
||||
static
|
||||
{
|
||||
LoggingUtil.init();
|
||||
}
|
||||
|
||||
private static String default_impl = System.getProperty("com.sun.net.httpserver.HttpServerProvider");
|
||||
|
||||
|
|
|
@ -42,6 +42,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||
|
||||
public class TestSPIServer
|
||||
{
|
||||
static
|
||||
{
|
||||
LoggingUtil.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a server that has a null InetSocketAddress, then
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# Jetty Logging using jetty-slf4j-impl
|
||||
org.eclipse.jetty.logging.appender.NAME_CONDENSE=false
|
||||
org.eclipse.jetty.logging.appender.MESSAGE_ESCAPE=false
|
||||
# org.eclipse.jetty.LEVEL=WARN
|
||||
log.LEVEL=INFO
|
|
@ -25,11 +25,14 @@
|
|||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.eclipse.jetty.http2.frames.DataFrame;
|
|||
import org.eclipse.jetty.http2.parser.Parser;
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.RetainableByteBuffer;
|
||||
import org.eclipse.jetty.io.WriteFlusher;
|
||||
|
@ -41,7 +42,7 @@ import org.eclipse.jetty.util.thread.strategy.EatWhatYouKill;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class HTTP2Connection extends AbstractConnection implements WriteFlusher.Listener
|
||||
public class HTTP2Connection extends AbstractConnection implements WriteFlusher.Listener, Connection.UpgradeTo
|
||||
{
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(HTTP2Connection.class);
|
||||
|
||||
|
@ -95,8 +96,11 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher.
|
|||
return parser;
|
||||
}
|
||||
|
||||
protected void setInputBuffer(ByteBuffer buffer)
|
||||
@Override
|
||||
public void onUpgradeTo(ByteBuffer buffer)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("HTTP2 onUpgradeTo {} {}", this, BufferUtil.toDetailString(buffer));
|
||||
if (buffer != null)
|
||||
producer.setInputBuffer(buffer);
|
||||
}
|
||||
|
|
|
@ -540,19 +540,10 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
boolean queued;
|
||||
synchronized (this)
|
||||
{
|
||||
int streamId = frame.getStreamId();
|
||||
if (streamId <= 0)
|
||||
{
|
||||
streamId = localStreamIds.getAndAdd(2);
|
||||
PriorityFrame priority = frame.getPriority();
|
||||
priority = priority == null ? null : new PriorityFrame(streamId, priority.getParentStreamId(),
|
||||
priority.getWeight(), priority.isExclusive());
|
||||
frame = new HeadersFrame(streamId, frame.getMetaData(), priority, frame.isEndStream());
|
||||
}
|
||||
stream = createLocalStream(streamId, (MetaData.Request)frame.getMetaData());
|
||||
HeadersFrame[] frameOut = new HeadersFrame[1];
|
||||
stream = newStream(frame, frameOut);
|
||||
stream.setListener(listener);
|
||||
|
||||
ControlEntry entry = new ControlEntry(frame, stream, new StreamPromiseCallback(promise, stream));
|
||||
ControlEntry entry = new ControlEntry(frameOut[0], stream, new StreamPromiseCallback(promise, stream));
|
||||
queued = flusher.append(entry);
|
||||
}
|
||||
stream.process(new PrefaceFrame(), Callback.NOOP);
|
||||
|
@ -566,6 +557,33 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a new stream allocating a stream id if the given HEADERS frame does not have one.</p>
|
||||
* <p>The new HEADERS frame with the newly allocated stream id is returned as the first element
|
||||
* of the array parameter.</p>
|
||||
*
|
||||
* @param frameIn the HEADERS frame that triggered the stream creation
|
||||
* @param frameOut an array of size 1 to return the HEADERS frame with the newly
|
||||
* allocated stream id, or null if not interested in the modified headers frame
|
||||
* @return a new stream
|
||||
*/
|
||||
public IStream newStream(HeadersFrame frameIn, HeadersFrame[] frameOut)
|
||||
{
|
||||
HeadersFrame frame = frameIn;
|
||||
int streamId = frameIn.getStreamId();
|
||||
if (streamId <= 0)
|
||||
{
|
||||
streamId = localStreamIds.getAndAdd(2);
|
||||
PriorityFrame priority = frameIn.getPriority();
|
||||
priority = priority == null ? null : new PriorityFrame(streamId, priority.getParentStreamId(),
|
||||
priority.getWeight(), priority.isExclusive());
|
||||
frame = new HeadersFrame(streamId, frameIn.getMetaData(), priority, frameIn.isEndStream());
|
||||
}
|
||||
if (frameOut != null)
|
||||
frameOut[0] = frame;
|
||||
return createLocalStream(streamId, (MetaData.Request)frame.getMetaData());
|
||||
}
|
||||
|
||||
protected IStream newStream(int streamId, MetaData.Request request, boolean local)
|
||||
{
|
||||
return new HTTP2Stream(scheduler, this, streamId, request, local);
|
||||
|
|
|
@ -62,7 +62,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -19,16 +19,23 @@
|
|||
package org.eclipse.jetty.http2.client.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClientTransport;
|
||||
import org.eclipse.jetty.client.HttpDestination;
|
||||
import org.eclipse.jetty.client.api.Connection;
|
||||
import org.eclipse.jetty.http2.client.HTTP2Client;
|
||||
import org.eclipse.jetty.http2.client.HTTP2ClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ssl.SslConnection;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
|
||||
public class ClientConnectionFactoryOverHTTP2 implements ClientConnectionFactory
|
||||
public class ClientConnectionFactoryOverHTTP2 extends ContainerLifeCycle implements ClientConnectionFactory
|
||||
{
|
||||
private final ClientConnectionFactory factory = new HTTP2ClientConnectionFactory();
|
||||
private final HTTP2Client client;
|
||||
|
@ -36,10 +43,11 @@ public class ClientConnectionFactoryOverHTTP2 implements ClientConnectionFactory
|
|||
public ClientConnectionFactoryOverHTTP2(HTTP2Client client)
|
||||
{
|
||||
this.client = client;
|
||||
addBean(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException
|
||||
public org.eclipse.jetty.io.Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException
|
||||
{
|
||||
HTTPSessionListenerPromise listenerPromise = new HTTPSessionListenerPromise(context);
|
||||
context.put(HTTP2ClientConnectionFactory.CLIENT_CONTEXT_KEY, client);
|
||||
|
@ -62,5 +70,54 @@ public class ClientConnectionFactoryOverHTTP2 implements ClientConnectionFactory
|
|||
{
|
||||
super(List.of("h2c"), new ClientConnectionFactoryOverHTTP2(client));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(EndPoint endPoint, Map<String, Object> context)
|
||||
{
|
||||
HttpDestination destination = (HttpDestination)context.get(HttpClientTransport.HTTP_DESTINATION_CONTEXT_KEY);
|
||||
@SuppressWarnings("unchecked")
|
||||
Promise<Connection> promise = (Promise<Connection>)context.get(HttpClientTransport.HTTP_CONNECTION_PROMISE_CONTEXT_KEY);
|
||||
context.put(HttpClientTransport.HTTP_CONNECTION_PROMISE_CONTEXT_KEY, new Promise<HttpConnectionOverHTTP2>()
|
||||
{
|
||||
@Override
|
||||
public void succeeded(HttpConnectionOverHTTP2 connection)
|
||||
{
|
||||
// This code is run when the client receives the server preface reply.
|
||||
// Upgrade the connection to setup HTTP/2 frame listeners that will
|
||||
// handle the HTTP/2 response to the upgrade request.
|
||||
promise.succeeded(connection);
|
||||
connection.upgrade(context);
|
||||
// The connection can be used only after the upgrade that
|
||||
// creates stream #1 corresponding to the HTTP/1.1 upgrade
|
||||
// request, otherwise other requests can steal id #1.
|
||||
destination.accept(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
promise.failed(x);
|
||||
}
|
||||
});
|
||||
upgrade(destination.getClientConnectionFactory(), endPoint, context);
|
||||
}
|
||||
|
||||
private void upgrade(ClientConnectionFactory factory, EndPoint endPoint, Map<String, Object> context)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Avoid double TLS wrapping. We want to keep the existing
|
||||
// SslConnection that has already performed the TLS handshake,
|
||||
// and just upgrade the nested connection.
|
||||
if (factory instanceof SslClientConnectionFactory && endPoint instanceof SslConnection.DecryptedEndPoint)
|
||||
factory = ((SslClientConnectionFactory)factory).getClientConnectionFactory();
|
||||
var newConnection = factory.newConnection(endPoint, context);
|
||||
endPoint.upgrade(newConnection);
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
throw new UncheckedIOException(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ class HTTPSessionListenerPromise extends Session.Listener.Adapter implements Pro
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Promise<Connection> connectionPromise()
|
||||
private Promise<Connection> httpConnectionPromise()
|
||||
{
|
||||
return (Promise<Connection>)context.get(HttpClientTransport.HTTP_CONNECTION_PROMISE_CONTEXT_KEY);
|
||||
}
|
||||
|
@ -77,6 +77,7 @@ class HTTPSessionListenerPromise extends Session.Listener.Adapter implements Pro
|
|||
if (destination instanceof HttpDestination.Multiplexed)
|
||||
((HttpDestination.Multiplexed)destination).setMaxRequestsPerConnection(settings.get(SettingsFrame.MAX_CONCURRENT_STREAMS));
|
||||
}
|
||||
// The first SETTINGS frame is the server preface reply.
|
||||
if (!connection.isMarked())
|
||||
onServerPreface(session);
|
||||
}
|
||||
|
@ -85,7 +86,7 @@ class HTTPSessionListenerPromise extends Session.Listener.Adapter implements Pro
|
|||
{
|
||||
HttpConnectionOverHTTP2 connection = newHttpConnection(destination(), session);
|
||||
if (this.connection.compareAndSet(null, connection, false, true))
|
||||
connectionPromise().succeeded(connection);
|
||||
httpConnectionPromise().succeeded(connection);
|
||||
}
|
||||
|
||||
protected HttpConnectionOverHTTP2 newHttpConnection(HttpDestination destination, Session session)
|
||||
|
@ -105,6 +106,7 @@ class HTTPSessionListenerPromise extends Session.Listener.Adapter implements Pro
|
|||
|
||||
void onClose(HttpConnectionOverHTTP2 connection, GoAwayFrame frame)
|
||||
{
|
||||
connection.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -133,7 +135,7 @@ class HTTPSessionListenerPromise extends Session.Listener.Adapter implements Pro
|
|||
{
|
||||
boolean result = connection.compareAndSet(null, null, false, true);
|
||||
if (result)
|
||||
connectionPromise().failed(failure);
|
||||
httpConnectionPromise().failed(failure);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
package org.eclipse.jetty.http2.client.http;
|
||||
|
||||
import java.nio.channels.AsynchronousCloseException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
@ -32,13 +34,19 @@ import org.eclipse.jetty.client.HttpConnection;
|
|||
import org.eclipse.jetty.client.HttpDestination;
|
||||
import org.eclipse.jetty.client.HttpExchange;
|
||||
import org.eclipse.jetty.client.HttpRequest;
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
import org.eclipse.jetty.client.HttpUpgrader;
|
||||
import org.eclipse.jetty.client.SendFailure;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.CloseState;
|
||||
import org.eclipse.jetty.http2.ErrorCode;
|
||||
import org.eclipse.jetty.http2.HTTP2Session;
|
||||
import org.eclipse.jetty.http2.IStream;
|
||||
import org.eclipse.jetty.http2.api.Session;
|
||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.thread.Sweeper;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -90,6 +98,33 @@ public class HttpConnectionOverHTTP2 extends HttpConnection implements Sweeper.S
|
|||
return send(channel, exchange);
|
||||
}
|
||||
|
||||
public void upgrade(Map<String, Object> context)
|
||||
{
|
||||
HttpResponse response = (HttpResponse)context.get(HttpResponse.class.getName());
|
||||
HttpRequest request = (HttpRequest)response.getRequest();
|
||||
// In case of HTTP/1.1 upgrade to HTTP/2, the request is HTTP/1.1
|
||||
// (with upgrade) for a resource, and the response is HTTP/2.
|
||||
// Create the implicit stream#1 so that it can receive the HTTP/2 response.
|
||||
MetaData.Request metaData = new MetaData.Request(request.getMethod(), new HttpURI(request.getURI()), HttpVersion.HTTP_2, request.getHeaders());
|
||||
// We do not support upgrade requests with content, so endStream=true.
|
||||
HeadersFrame frame = new HeadersFrame(metaData, null, true);
|
||||
IStream stream = ((HTTP2Session)session).newStream(frame, null);
|
||||
stream.updateClose(frame.isEndStream(), CloseState.Event.AFTER_SEND);
|
||||
|
||||
HttpExchange exchange = request.getConversation().getExchanges().peekLast();
|
||||
HttpChannelOverHTTP2 http2Channel = acquireHttpChannel();
|
||||
activeChannels.add(http2Channel);
|
||||
HttpExchange newExchange = new HttpExchange(exchange.getHttpDestination(), exchange.getRequest(), List.of());
|
||||
http2Channel.associate(newExchange);
|
||||
stream.setListener(http2Channel.getStreamListener());
|
||||
http2Channel.setStream(stream);
|
||||
newExchange.requestComplete(null);
|
||||
newExchange.terminateRequest();
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Upgrade completed for {}", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void normalizeRequest(Request request)
|
||||
{
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.eclipse.jetty.http2.client.http;
|
|||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.function.BiFunction;
|
||||
|
@ -116,7 +115,7 @@ public class HttpReceiverOverHTTP2 extends HttpReceiver implements HTTP2Channel.
|
|||
conversation.setAttribute(EndPoint.class.getName(), endPoint);
|
||||
HttpUpgrader upgrader = (HttpUpgrader)conversation.getAttribute(HttpUpgrader.class.getName());
|
||||
if (upgrader != null)
|
||||
upgrader.upgrade(httpResponse, endPoint);
|
||||
upgrade(upgrader, httpResponse, endPoint);
|
||||
}
|
||||
|
||||
if (responseHeaders(exchange))
|
||||
|
@ -148,6 +147,18 @@ public class HttpReceiverOverHTTP2 extends HttpReceiver implements HTTP2Channel.
|
|||
}
|
||||
}
|
||||
|
||||
private void upgrade(HttpUpgrader upgrader, HttpResponse response, EndPoint endPoint)
|
||||
{
|
||||
try
|
||||
{
|
||||
upgrader.upgrade(response, endPoint, Callback.from(Callback.NOOP::succeeded, this::responseFailure));
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
responseFailure(x);
|
||||
}
|
||||
}
|
||||
|
||||
Stream.Listener onPush(Stream stream, PushPromiseFrame frame)
|
||||
{
|
||||
HttpExchange exchange = getHttpExchange();
|
||||
|
@ -166,8 +177,7 @@ public class HttpReceiverOverHTTP2 extends HttpReceiver implements HTTP2Channel.
|
|||
if (listener != null)
|
||||
{
|
||||
HttpChannelOverHTTP2 pushChannel = getHttpChannel().getHttpConnection().acquireHttpChannel();
|
||||
List<Response.ResponseListener> listeners = Collections.singletonList(listener);
|
||||
HttpExchange pushExchange = new HttpExchange(getHttpDestination(), pushRequest, listeners);
|
||||
HttpExchange pushExchange = new HttpExchange(getHttpDestination(), pushRequest, List.of(listener));
|
||||
pushChannel.associate(pushExchange);
|
||||
pushChannel.setStream(stream);
|
||||
// TODO: idle timeout ?
|
||||
|
|
|
@ -37,9 +37,13 @@ import org.eclipse.jetty.http2.frames.DataFrame;
|
|||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class HttpSenderOverHTTP2 extends HttpSender
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HttpSenderOverHTTP2.class);
|
||||
|
||||
public HttpSenderOverHTTP2(HttpChannelOverHTTP2 channel)
|
||||
{
|
||||
super(channel);
|
||||
|
|
|
@ -80,7 +80,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -74,13 +74,13 @@ public class HTTP2CServerConnectionFactory extends HTTP2ServerConnectionFactory
|
|||
public Connection upgradeConnection(Connector connector, EndPoint endPoint, Request request, HttpFields response101) throws BadMessageException
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} upgraded {}{}", this, request.toString(), request.getFields());
|
||||
LOG.debug("{} upgrading {}{}{}", this, request, System.lineSeparator(), request.getFields());
|
||||
|
||||
if (request.getContentLength() > 0)
|
||||
return null;
|
||||
|
||||
HTTP2ServerConnection connection = (HTTP2ServerConnection)newConnection(connector, endPoint);
|
||||
if (connection.upgrade(request))
|
||||
if (connection.upgrade(request, response101))
|
||||
return connection;
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.eclipse.jetty.http2.server;
|
|||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
|
@ -33,6 +32,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
|
@ -54,7 +54,6 @@ import org.eclipse.jetty.http2.frames.SettingsFrame;
|
|||
import org.eclipse.jetty.http2.parser.ServerParser;
|
||||
import org.eclipse.jetty.http2.parser.SettingsBodyParser;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
|
@ -63,7 +62,7 @@ import org.eclipse.jetty.util.Callback;
|
|||
import org.eclipse.jetty.util.CountingCallback;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
|
||||
public class HTTP2ServerConnection extends HTTP2Connection implements Connection.UpgradeTo
|
||||
public class HTTP2ServerConnection extends HTTP2Connection
|
||||
{
|
||||
/**
|
||||
* @param protocol An HTTP2 protocol variant
|
||||
|
@ -132,21 +131,14 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
this.recycleHttpChannels = recycleHttpChannels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgradeTo(ByteBuffer buffer)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("HTTP2 onUpgradeTo {} {}", this, BufferUtil.toDetailString(buffer));
|
||||
setInputBuffer(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen()
|
||||
{
|
||||
notifyAccept(getSession());
|
||||
ISession session = getSession();
|
||||
notifyAccept(session);
|
||||
for (Frame frame : upgradeFrames)
|
||||
{
|
||||
getSession().onFrame(frame);
|
||||
session.onFrame(frame);
|
||||
}
|
||||
super.onOpen();
|
||||
produce();
|
||||
|
@ -328,7 +320,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
}
|
||||
}
|
||||
|
||||
public boolean upgrade(Request request)
|
||||
public boolean upgrade(Request request, HttpFields responseFields)
|
||||
{
|
||||
if (HttpMethod.PRI.is(request.getMethod()))
|
||||
{
|
||||
|
@ -343,7 +335,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
final byte[] settings = Base64.getUrlDecoder().decode(value == null ? "" : value);
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} settings {}", this, TypeUtil.toHexString(settings));
|
||||
LOG.debug("{} {}: {}", this, HttpHeader.HTTP2_SETTINGS, TypeUtil.toHexString(settings));
|
||||
|
||||
SettingsFrame settingsFrame = SettingsBodyParser.parseBody(BufferUtil.toBuffer(settings));
|
||||
if (settingsFrame == null)
|
||||
|
@ -352,11 +344,18 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
throw new BadMessageException();
|
||||
}
|
||||
|
||||
responseFields.put(HttpHeader.UPGRADE, "h2c");
|
||||
responseFields.put(HttpHeader.CONNECTION, "Upgrade");
|
||||
|
||||
getParser().standardUpgrade();
|
||||
|
||||
// We fake that we received a client preface, so that we can send the
|
||||
// server preface as the first HTTP/2 frame as required by the spec.
|
||||
// When the client sends the real preface, the parser won't notify it.
|
||||
upgradeFrames.add(new PrefaceFrame());
|
||||
// This is the settings from the HTTP2-Settings header.
|
||||
upgradeFrames.add(settingsFrame);
|
||||
// Remember the request to send a response from onOpen().
|
||||
// Remember the request to send a response.
|
||||
upgradeFrames.add(new HeadersFrame(1, new Request(request), null, true));
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -53,6 +53,15 @@
|
|||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.infinispan</groupId>
|
||||
<artifactId>infinispan-client-hotrod</artifactId>
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -70,7 +70,7 @@ public interface ClientConnectionFactory
|
|||
* (for example {@code ["h2", "h2-17", "h2-16"]}) and a {@link ClientConnectionFactory}
|
||||
* that creates connections that speak that network protocol.</p>
|
||||
*/
|
||||
public static class Info
|
||||
public static class Info extends ContainerLifeCycle
|
||||
{
|
||||
private final List<String> protocols;
|
||||
private final ClientConnectionFactory factory;
|
||||
|
@ -79,6 +79,7 @@ public interface ClientConnectionFactory
|
|||
{
|
||||
this.protocols = protocols;
|
||||
this.factory = factory;
|
||||
addBean(factory);
|
||||
}
|
||||
|
||||
public List<String> getProtocols()
|
||||
|
@ -102,6 +103,11 @@ public interface ClientConnectionFactory
|
|||
return protocols.stream().anyMatch(p -> candidates.stream().anyMatch(c -> c.equalsIgnoreCase(p)));
|
||||
}
|
||||
|
||||
public void upgrade(EndPoint endPoint, Map<String, Object> context)
|
||||
{
|
||||
throw new UnsupportedOperationException(this + " does not support upgrade to another protocol");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
|
|
@ -56,6 +56,11 @@ public class SslClientConnectionFactory implements ClientConnectionFactory
|
|||
this.connectionFactory = connectionFactory;
|
||||
}
|
||||
|
||||
public ClientConnectionFactory getClientConnectionFactory()
|
||||
{
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
public void setDirectBuffersForEncryption(boolean useDirectBuffers)
|
||||
{
|
||||
this._directBuffersForEncryption = useDirectBuffers;
|
||||
|
|
|
@ -42,13 +42,17 @@
|
|||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# Jetty Logging using jetty-slf4j-impl
|
||||
org.eclipse.jetty.LEVEL=INFO
|
||||
org.apache.directory.LEVEL=ERROR
|
|
@ -1 +0,0 @@
|
|||
org.slf4j.simpleLogger.log.org.apache.directory=error
|
|
@ -50,6 +50,15 @@
|
|||
<artifactId>jetty-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -32,24 +32,25 @@
|
|||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.openpojo</groupId>
|
||||
<artifactId>openpojo</artifactId>
|
||||
|
|
|
@ -51,7 +51,15 @@
|
|||
<artifactId>jetty-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -21,11 +21,6 @@
|
|||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jmx</artifactId>
|
||||
|
@ -39,6 +34,20 @@
|
|||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-sessions-common</artifactId>
|
||||
|
|
|
@ -66,6 +66,15 @@
|
|||
<artifactId>jetty-util-ajax</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
|
|
|
@ -68,7 +68,15 @@
|
|||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derby</artifactId>
|
||||
|
|
|
@ -77,7 +77,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -30,7 +30,15 @@
|
|||
<artifactId>jetty-annotations</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -36,7 +36,15 @@
|
|||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-servlet-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>jetty-http-tools</artifactId>
|
||||
|
|
|
@ -131,5 +131,14 @@
|
|||
<artifactId>apache-jstl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# Jetty Logging using jetty-slf4j-impl
|
||||
org.eclipse.jetty.LEVEL=INFO
|
|
@ -58,7 +58,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -89,6 +89,11 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -441,18 +441,12 @@ public class HttpChannelOverHttp extends HttpChannel implements HttpParser.Reque
|
|||
throw new BadMessageException(HttpStatus.BAD_REQUEST_400);
|
||||
|
||||
// Find the upgrade factory
|
||||
ConnectionFactory.Upgrading factory = null;
|
||||
for (ConnectionFactory f : getConnector().getConnectionFactories())
|
||||
{
|
||||
if (f instanceof ConnectionFactory.Upgrading)
|
||||
{
|
||||
if (f.getProtocols().contains(_upgrade.getValue()))
|
||||
{
|
||||
factory = (ConnectionFactory.Upgrading)f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ConnectionFactory.Upgrading factory = getConnector().getConnectionFactories().stream()
|
||||
.filter(f -> f instanceof ConnectionFactory.Upgrading)
|
||||
.map(ConnectionFactory.Upgrading.class::cast)
|
||||
.filter(f -> f.getProtocols().contains(_upgrade.getValue()))
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
|
||||
if (factory == null)
|
||||
{
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -71,7 +71,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -65,50 +65,57 @@ public class Slf4jEffort
|
|||
AtomicInteger countPomSlf4jImpls = new AtomicInteger(0);
|
||||
AtomicInteger countOldLogClassProps = new AtomicInteger(0);
|
||||
|
||||
getProjectsStream(root).forEach((pom) ->
|
||||
{
|
||||
Path project = pom.getParent();
|
||||
try
|
||||
getProjectsStream(root)
|
||||
.filter(pom ->
|
||||
{
|
||||
Path testLoggingProps = project.resolve("src/test/resources/jetty-logging.properties");
|
||||
|
||||
boolean isMainSrcUsingLogging = getSources(project.resolve("src/main/java")).anyMatch(Slf4jEffort::isUsingLogging);
|
||||
boolean isTestSrcUsingLogging = getSources(project.resolve("src/test/java")).anyMatch(Slf4jEffort::isUsingLogging);
|
||||
|
||||
if (isMainSrcUsingLogging || isTestSrcUsingLogging)
|
||||
String fullpath = pom.toString();
|
||||
return !((fullpath.contains("/jetty-osgi") ||
|
||||
fullpath.contains("/jetty-slf4j-impl/")));
|
||||
})
|
||||
.forEach((pom) ->
|
||||
{
|
||||
Path project = pom.getParent();
|
||||
try
|
||||
{
|
||||
// Must include slf4j in module-info and pom
|
||||
Path moduleInfo = project.resolve("src/main/java/module-info.java");
|
||||
if (Files.exists(moduleInfo) && isMainSrcUsingLogging && !isLoggingJpmsPresent(moduleInfo))
|
||||
{
|
||||
System.err.printf("[Missing: JPMS] %s%n", moduleInfo);
|
||||
countJpms.incrementAndGet();
|
||||
}
|
||||
Path testLoggingProps = project.resolve("src/test/resources/jetty-logging.properties");
|
||||
|
||||
if (!isSlf4jDepPresent(pom))
|
||||
{
|
||||
// System.err.printf("[Missing: Dep: slf4j-api] %s%n", pom);
|
||||
countPomSlf4jApis.incrementAndGet();
|
||||
}
|
||||
boolean isMainSrcUsingLogging = getSources(project.resolve("src/main/java")).anyMatch(Slf4jEffort::isUsingLogging);
|
||||
boolean isTestSrcUsingLogging = getSources(project.resolve("src/test/java")).anyMatch(Slf4jEffort::isUsingLogging);
|
||||
|
||||
if (isTestSrcUsingLogging && !isSlf4jImplDepPresent(pom))
|
||||
if (isMainSrcUsingLogging || isTestSrcUsingLogging)
|
||||
{
|
||||
// System.err.printf("[Missing: Dep: jetty-slf4j-impl] %s%n", pom);
|
||||
countPomSlf4jImpls.incrementAndGet();
|
||||
}
|
||||
if (!isSlf4jImplDepPresent(pom))
|
||||
{
|
||||
System.err.printf("[Missing: Dep: jetty-slf4j-impl] %s%n", pom);
|
||||
countPomSlf4jImpls.incrementAndGet();
|
||||
}
|
||||
|
||||
if (Files.exists(testLoggingProps) && isOldLogClassPropPresent(testLoggingProps))
|
||||
{
|
||||
System.err.printf("[Deprecated: log.class=LogImpl] %s%n", testLoggingProps);
|
||||
countOldLogClassProps.incrementAndGet();
|
||||
// Must include slf4j in module-info and pom
|
||||
Path moduleInfo = project.resolve("src/main/java/module-info.java");
|
||||
if (Files.exists(moduleInfo) && isMainSrcUsingLogging && !isLoggingJpmsPresent(moduleInfo))
|
||||
{
|
||||
System.err.printf("[Missing: JPMS] %s%n", moduleInfo);
|
||||
countJpms.incrementAndGet();
|
||||
}
|
||||
|
||||
if (!isSlf4jDepPresent(pom))
|
||||
{
|
||||
System.err.printf("[Missing: Dep: slf4j-api] %s%n", pom);
|
||||
countPomSlf4jApis.incrementAndGet();
|
||||
}
|
||||
|
||||
if (Files.exists(testLoggingProps) && isOldLogClassPropPresent(testLoggingProps))
|
||||
{
|
||||
System.err.printf("[Deprecated: log.class=LogImpl] %s%n", testLoggingProps);
|
||||
countOldLogClassProps.incrementAndGet();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
System.out.printf("JPMS (module-info.java) to fix: %d%n", countJpms.get());
|
||||
System.out.printf("POMS (pom.xml) - slf4j-api to fix: %d%n", countPomSlf4jApis.get());
|
||||
|
@ -184,7 +191,9 @@ public class Slf4jEffort
|
|||
String line;
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
if (line.contains("requires org.slf4j;"))
|
||||
if (line.contains("requires org.slf4j;") ||
|
||||
line.contains("requires transitive org.slf4j;") ||
|
||||
line.contains("requires static org.slf4j;"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -70,7 +70,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -77,10 +77,6 @@
|
|||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -25,6 +25,15 @@
|
|||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -61,9 +61,6 @@
|
|||
<systemPropertyVariables>
|
||||
<mavenRepoPath>${settings.localRepository}</mavenRepoPath>
|
||||
</systemPropertyVariables>
|
||||
<argLine>
|
||||
@{argLine} ${jetty.surefire.argLine} --add-modules org.slf4j
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
@ -86,6 +83,7 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.util;
|
|||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -63,6 +64,32 @@ public interface Promise<C>
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a Promise from the given success and failure consumers.</p>
|
||||
*
|
||||
* @param success the consumer invoked when the promise is succeeded
|
||||
* @param failure the consumer invoked when the promise is failed
|
||||
* @param <T> the type of the result
|
||||
* @return a new Promise wrapping the success and failure consumers.
|
||||
*/
|
||||
static <T> Promise<T> from(Consumer<T> success, Consumer<Throwable> failure)
|
||||
{
|
||||
return new Promise<>()
|
||||
{
|
||||
@Override
|
||||
public void succeeded(T result)
|
||||
{
|
||||
success.accept(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
failure.accept(x);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a promise from the given incomplete CompletableFuture.</p>
|
||||
* <p>When the promise completes, either succeeding or failing, the
|
||||
|
|
|
@ -36,9 +36,9 @@ import java.util.Arrays;
|
|||
*/
|
||||
public class SearchPattern
|
||||
{
|
||||
static final int alphabetSize = 256;
|
||||
private int[] table;
|
||||
private byte[] pattern;
|
||||
private static final int ALPHABET_SIZE = 256;
|
||||
private final int[] table = new int[ALPHABET_SIZE];
|
||||
private final byte[] pattern;
|
||||
|
||||
/**
|
||||
* Produces a SearchPattern instance which can be used
|
||||
|
@ -70,16 +70,11 @@ public class SearchPattern
|
|||
private SearchPattern(byte[] pattern)
|
||||
{
|
||||
this.pattern = pattern;
|
||||
|
||||
if (pattern.length == 0)
|
||||
throw new IllegalArgumentException("Empty Pattern");
|
||||
|
||||
//Build up the pre-processed table for this pattern.
|
||||
table = new int[alphabetSize];
|
||||
for (int i = 0; i < table.length; ++i)
|
||||
{
|
||||
table[i] = pattern.length;
|
||||
}
|
||||
Arrays.fill(table, pattern.length);
|
||||
for (int i = 0; i < pattern.length - 1; ++i)
|
||||
{
|
||||
table[0xff & pattern[i]] = pattern.length - 1 - i;
|
||||
|
@ -97,7 +92,7 @@ public class SearchPattern
|
|||
*/
|
||||
public int match(byte[] data, int offset, int length)
|
||||
{
|
||||
validate(data, offset, length);
|
||||
validateArgs(data, offset, length);
|
||||
|
||||
int skip = offset;
|
||||
while (skip <= offset + length - pattern.length)
|
||||
|
@ -125,7 +120,7 @@ public class SearchPattern
|
|||
*/
|
||||
public int endsWith(byte[] data, int offset, int length)
|
||||
{
|
||||
validate(data, offset, length);
|
||||
validateArgs(data, offset, length);
|
||||
|
||||
int skip = (pattern.length <= length) ? (offset + length - pattern.length) : offset;
|
||||
while (skip < offset + length)
|
||||
|
@ -136,10 +131,8 @@ public class SearchPattern
|
|||
return (offset + length - skip);
|
||||
}
|
||||
|
||||
if (skip + pattern.length - 1 < data.length)
|
||||
skip += table[0xff & data[skip + pattern.length - 1]];
|
||||
else
|
||||
skip++;
|
||||
// We can't use the pre-processed table as we are not matching on the full pattern.
|
||||
skip++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -157,10 +150,9 @@ public class SearchPattern
|
|||
*/
|
||||
public int startsWith(byte[] data, int offset, int length, int matched)
|
||||
{
|
||||
validate(data, offset, length);
|
||||
validateArgs(data, offset, length);
|
||||
|
||||
int matchedCount = 0;
|
||||
|
||||
for (int i = 0; i < pattern.length - matched && i < length; i++)
|
||||
{
|
||||
if (data[offset + i] == pattern[i + matched])
|
||||
|
@ -180,7 +172,7 @@ public class SearchPattern
|
|||
* @param offset The offset within the data to start the search
|
||||
* @param length The length of the data to search
|
||||
*/
|
||||
private void validate(byte[] data, int offset, int length)
|
||||
private void validateArgs(byte[] data, int offset, int length)
|
||||
{
|
||||
if (offset < 0)
|
||||
throw new IllegalArgumentException("offset was negative");
|
||||
|
|
|
@ -32,10 +32,10 @@ public class SearchPatternTest
|
|||
@Test
|
||||
public void testBasicSearch()
|
||||
{
|
||||
byte[] p1 = new String("truth").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] p2 = new String("evident").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] p3 = new String("we").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = new String("we hold these truths to be self evident").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] p1 = "truth".getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] p2 = "evident".getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] p3 = "we".getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = "we hold these truths to be self evident".getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
// Testing Compiled Pattern p1 "truth"
|
||||
SearchPattern sp1 = SearchPattern.compile(p1);
|
||||
|
@ -65,8 +65,8 @@ public class SearchPatternTest
|
|||
@Test
|
||||
public void testDoubleMatch()
|
||||
{
|
||||
byte[] p = new String("violent").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = new String("These violent delights have violent ends.").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] p = "violent".getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = "These violent delights have violent ends.".getBytes(StandardCharsets.US_ASCII);
|
||||
SearchPattern sp = SearchPattern.compile(p);
|
||||
assertEquals(6, sp.match(d, 0, d.length));
|
||||
assertEquals(-1, sp.match(d, 6, p.length - 1));
|
||||
|
@ -113,8 +113,8 @@ public class SearchPatternTest
|
|||
@Test
|
||||
public void testAlmostMatch()
|
||||
{
|
||||
byte[] p = new String("violent").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = new String("vio lent violen v iolent violin vioviolenlent viiolent").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] p = "violent".getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = "vio lent violen v iolent violin vioviolenlent viiolent".getBytes(StandardCharsets.US_ASCII);
|
||||
SearchPattern sp = SearchPattern.compile(p);
|
||||
assertEquals(-1, sp.match(d, 0, d.length));
|
||||
}
|
||||
|
@ -123,14 +123,14 @@ public class SearchPatternTest
|
|||
public void testOddSizedPatterns()
|
||||
{
|
||||
// Test Large Pattern
|
||||
byte[] p = new String("pneumonoultramicroscopicsilicovolcanoconiosis").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = new String("pneumon").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] p = "pneumonoultramicroscopicsilicovolcanoconiosis".getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = "pneumon".getBytes(StandardCharsets.US_ASCII);
|
||||
SearchPattern sp = SearchPattern.compile(p);
|
||||
assertEquals(-1, sp.match(d, 0, d.length));
|
||||
|
||||
// Test Single Character Pattern
|
||||
p = new String("s").getBytes(StandardCharsets.US_ASCII);
|
||||
d = new String("the cake is a lie").getBytes(StandardCharsets.US_ASCII);
|
||||
p = "s".getBytes(StandardCharsets.US_ASCII);
|
||||
d = "the cake is a lie".getBytes(StandardCharsets.US_ASCII);
|
||||
sp = SearchPattern.compile(p);
|
||||
assertEquals(10, sp.match(d, 0, d.length));
|
||||
}
|
||||
|
@ -138,30 +138,36 @@ public class SearchPatternTest
|
|||
@Test
|
||||
public void testEndsWith()
|
||||
{
|
||||
byte[] p = new String("pneumonoultramicroscopicsilicovolcanoconiosis").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = new String("pneumonoultrami").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] p = "pneumonoultramicroscopicsilicovolcanoconiosis".getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = "pneumonoultrami".getBytes(StandardCharsets.US_ASCII);
|
||||
SearchPattern sp = SearchPattern.compile(p);
|
||||
assertEquals(15, sp.endsWith(d, 0, d.length));
|
||||
|
||||
p = new String("abcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
d = new String("abcdefghijklmnopqrstuvwxyzabcdefghijklmno").getBytes(StandardCharsets.US_ASCII);
|
||||
p = "abcdefghijklmnopqrstuvwxyz".getBytes(StandardCharsets.US_ASCII);
|
||||
d = "abcdefghijklmnopqrstuvwxyzabcdefghijklmno".getBytes(StandardCharsets.US_ASCII);
|
||||
sp = SearchPattern.compile(p);
|
||||
assertEquals(0, sp.match(d, 0, d.length));
|
||||
assertEquals(-1, sp.match(d, 1, d.length - 1));
|
||||
assertEquals(15, sp.endsWith(d, 0, d.length));
|
||||
|
||||
p = new String("abcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
d = new String("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
p = "abcdefghijklmnopqrstuvwxyz".getBytes(StandardCharsets.US_ASCII);
|
||||
d = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz".getBytes(StandardCharsets.US_ASCII);
|
||||
sp = SearchPattern.compile(p);
|
||||
assertEquals(0, sp.match(d, 0, d.length));
|
||||
assertEquals(26, sp.match(d, 1, d.length - 1));
|
||||
assertEquals(26, sp.endsWith(d, 0, d.length));
|
||||
|
||||
//test no match
|
||||
p = new String("hello world").getBytes(StandardCharsets.US_ASCII);
|
||||
d = new String("there is definitely no match in here").getBytes(StandardCharsets.US_ASCII);
|
||||
p = "hello world".getBytes(StandardCharsets.US_ASCII);
|
||||
d = "there is definitely no match in here".getBytes(StandardCharsets.US_ASCII);
|
||||
sp = SearchPattern.compile(p);
|
||||
assertEquals(0, sp.endsWith(d, 0, d.length));
|
||||
|
||||
//Test with range on array.
|
||||
p = "abcde".getBytes(StandardCharsets.US_ASCII);
|
||||
d = "?abc00000".getBytes(StandardCharsets.US_ASCII);
|
||||
sp = SearchPattern.compile(p);
|
||||
assertEquals(3, sp.endsWith(d, 0, 4));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -178,39 +184,54 @@ public class SearchPatternTest
|
|||
|
||||
private void testStartsWith(String offset)
|
||||
{
|
||||
byte[] p = new String("abcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = new String(offset + "ijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] p = "abcdefghijklmnopqrstuvwxyz".getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] d = (offset + "ijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
SearchPattern sp = SearchPattern.compile(p);
|
||||
assertEquals(18 + offset.length(), sp.match(d, offset.length(), d.length - offset.length()));
|
||||
assertEquals(-1, sp.match(d, offset.length() + 19, d.length - 19 - offset.length()));
|
||||
assertEquals(26, sp.startsWith(d, offset.length(), d.length - offset.length(), 8));
|
||||
|
||||
p = new String("abcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
d = new String(offset + "ijklmnopqrstuvwxyNOMATCH").getBytes(StandardCharsets.US_ASCII);
|
||||
p = "abcdefghijklmnopqrstuvwxyz".getBytes(StandardCharsets.US_ASCII);
|
||||
d = (offset + "ijklmnopqrstuvwxyNOMATCH").getBytes(StandardCharsets.US_ASCII);
|
||||
sp = SearchPattern.compile(p);
|
||||
assertEquals(0, sp.startsWith(d, offset.length(), d.length - offset.length(), 8));
|
||||
|
||||
p = new String("abcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
d = new String(offset + "abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
p = "abcdefghijklmnopqrstuvwxyz".getBytes(StandardCharsets.US_ASCII);
|
||||
d = (offset + "abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
sp = SearchPattern.compile(p);
|
||||
assertEquals(26, sp.startsWith(d, offset.length(), d.length - offset.length(), 0));
|
||||
|
||||
//test no match
|
||||
p = new String("hello world").getBytes(StandardCharsets.US_ASCII);
|
||||
d = new String(offset + "there is definitely no match in here").getBytes(StandardCharsets.US_ASCII);
|
||||
p = "hello world".getBytes(StandardCharsets.US_ASCII);
|
||||
d = (offset + "there is definitely no match in here").getBytes(StandardCharsets.US_ASCII);
|
||||
sp = SearchPattern.compile(p);
|
||||
assertEquals(0, sp.startsWith(d, offset.length(), d.length - offset.length(), 0));
|
||||
|
||||
//test large pattern small buffer
|
||||
p = new String("abcdefghijklmnopqrstuvwxyz").getBytes(StandardCharsets.US_ASCII);
|
||||
d = new String(offset + "mnopqrs").getBytes(StandardCharsets.US_ASCII);
|
||||
p = "abcdefghijklmnopqrstuvwxyz".getBytes(StandardCharsets.US_ASCII);
|
||||
d = (offset + "mnopqrs").getBytes(StandardCharsets.US_ASCII);
|
||||
sp = SearchPattern.compile(p);
|
||||
assertEquals(19, sp.startsWith(d, offset.length(), d.length - offset.length(), 12));
|
||||
|
||||
//partial pattern
|
||||
p = new String("abcdef").getBytes(StandardCharsets.US_ASCII);
|
||||
d = new String(offset + "cde").getBytes(StandardCharsets.US_ASCII);
|
||||
p = "abcdef".getBytes(StandardCharsets.US_ASCII);
|
||||
d = (offset + "cde").getBytes(StandardCharsets.US_ASCII);
|
||||
sp = SearchPattern.compile(p);
|
||||
assertEquals(5, sp.startsWith(d, offset.length(), d.length - offset.length(), 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExampleFrom4673()
|
||||
{
|
||||
SearchPattern pattern = SearchPattern.compile("\r\n------WebKitFormBoundaryhXfFAMfUnUKhmqT8".getBytes(StandardCharsets.US_ASCII));
|
||||
byte[] data = new byte[]{118,97,108,117,101,49,
|
||||
'\r','\n','-','-','-','-',
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0};
|
||||
int length = 12;
|
||||
|
||||
int partialMatch = pattern.endsWith(data, 0, length);
|
||||
System.err.println("match1: " + partialMatch);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.eclipse.jetty.http.HttpHeader;
|
|||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketConstants;
|
||||
import org.eclipse.jetty.websocket.core.internal.WebSocketCore;
|
||||
|
||||
|
@ -71,20 +72,35 @@ public class HttpUpgraderOverHTTP implements HttpUpgrader
|
|||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(HttpResponse response, EndPoint endPoint)
|
||||
public void upgrade(HttpResponse response, EndPoint endPoint, Callback callback)
|
||||
{
|
||||
HttpRequest request = (HttpRequest)response.getRequest();
|
||||
HttpFields requestHeaders = request.getHeaders();
|
||||
if (!requestHeaders.get(HttpHeader.UPGRADE).equalsIgnoreCase("websocket"))
|
||||
throw new HttpResponseException("Not a WebSocket Upgrade", response);
|
||||
|
||||
// Check the Accept hash
|
||||
String reqKey = requestHeaders.get(HttpHeader.SEC_WEBSOCKET_KEY);
|
||||
String expectedHash = WebSocketCore.hashKey(reqKey);
|
||||
String respHash = response.getHeaders().get(HttpHeader.SEC_WEBSOCKET_ACCEPT);
|
||||
if (!expectedHash.equalsIgnoreCase(respHash))
|
||||
throw new HttpResponseException("Invalid Sec-WebSocket-Accept hash (was:" + respHash + ", expected:" + expectedHash + ")", response);
|
||||
|
||||
clientUpgradeRequest.upgrade(response, endPoint);
|
||||
if (requestHeaders.contains(HttpHeader.UPGRADE, "websocket"))
|
||||
{
|
||||
HttpFields responseHeaders = response.getHeaders();
|
||||
if (responseHeaders.contains(HttpHeader.CONNECTION, "upgrade"))
|
||||
{
|
||||
// Check the Accept hash
|
||||
String reqKey = requestHeaders.get(HttpHeader.SEC_WEBSOCKET_KEY);
|
||||
String expectedHash = WebSocketCore.hashKey(reqKey);
|
||||
String respHash = responseHeaders.get(HttpHeader.SEC_WEBSOCKET_ACCEPT);
|
||||
if (expectedHash.equalsIgnoreCase(respHash))
|
||||
{
|
||||
clientUpgradeRequest.upgrade(response, endPoint);
|
||||
callback.succeeded();
|
||||
}
|
||||
else
|
||||
callback.failed(new HttpResponseException("Invalid Sec-WebSocket-Accept hash (was: " + respHash + " expected: " + expectedHash + ")", response));
|
||||
}
|
||||
else
|
||||
{
|
||||
callback.failed(new HttpResponseException("WebSocket upgrade missing 'Connection: Upgrade' header", response));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
callback.failed(new HttpResponseException("Not a WebSocket upgrade", response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.eclipse.jetty.client.HttpUpgrader;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketConstants;
|
||||
|
||||
public class HttpUpgraderOverHTTP2 implements HttpUpgrader
|
||||
|
@ -47,8 +48,16 @@ public class HttpUpgraderOverHTTP2 implements HttpUpgrader
|
|||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(HttpResponse response, EndPoint endPoint)
|
||||
public void upgrade(HttpResponse response, EndPoint endPoint, Callback callback)
|
||||
{
|
||||
clientUpgradeRequest.upgrade(response, endPoint);
|
||||
try
|
||||
{
|
||||
clientUpgradeRequest.upgrade(response, endPoint);
|
||||
callback.succeeded();
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
callback.failed(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,4 +12,4 @@
|
|||
# org.eclipse.jetty.io.ManagedSelector.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.LEVEL=INFO
|
||||
# org.eclipse.jetty.websocket.core.LEVEL=DEBUG
|
||||
# org.eclipse.jetty.websocket.core.LEVEL=DEBUG
|
||||
|
|
|
@ -80,7 +80,15 @@
|
|||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-javax-websocket-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -34,6 +34,15 @@
|
|||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-javax-websocket-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-javax-client</artifactId>
|
||||
|
@ -37,7 +41,7 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
|
@ -51,6 +55,14 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<!-- No point deploying testing projects -->
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
|
|
|
@ -30,7 +30,15 @@
|
|||
<artifactId>jetty-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -71,7 +71,15 @@
|
|||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
|
@ -55,6 +55,15 @@
|
|||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-servlet-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-test-helper</artifactId>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue