Merged branch 'jetty-10.0.x' into 'jetty-10.0.x-4400-review_httpclient_content'.

This commit is contained in:
Simone Bordet 2020-03-23 16:24:04 +01:00
commit e215d071c8
186 changed files with 2884 additions and 1552 deletions

2
Jenkinsfile vendored
View File

@ -55,7 +55,7 @@ pipeline {
agent { node { label 'linux' } }
steps {
timeout(time: 30, unit: 'MINUTES') {
mavenBuild("jdk11", "install javadoc:javadoc -DskipTests -Dpmd.skip=true -Dcheckstyle.skip=true", "maven3", true)
mavenBuild("jdk11", "package source:jar javadoc:jar javadoc:aggregate-jar -Peclipse-release -DskipTests -Dpmd.skip=true -Dcheckstyle.skip=true", "maven3", true)
warnings consoleParsers: [[parserName: 'Maven'], [parserName: 'JavaDoc'], [parserName: 'Java']]
}
}

View File

@ -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>

View File

@ -20,6 +20,18 @@
<targetPath>META-INF</targetPath>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<!-- No point building javadoc for this project -->
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -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>

View File

@ -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>

View File

@ -58,7 +58,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -40,7 +40,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -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>

View File

@ -54,7 +54,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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()

View File

@ -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>

View File

@ -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 ->
{

View File

@ -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(),

View File

@ -50,6 +50,11 @@ public class HttpExchange
conversation.updateResponseListeners(null);
}
public HttpDestination getHttpDestination()
{
return destination;
}
public HttpConversation getConversation()
{
return request.getConversation();

View File

@ -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);

View File

@ -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)
{

View File

@ -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));
}
}

View File

@ -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,7 +130,10 @@ public class HttpClientTransportDynamic extends AbstractConnectorHttpClientTrans
}
else
{
// Preserve the order of protocols chosen by the application.
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.
@ -141,6 +141,12 @@ public class HttpClientTransportDynamic extends AbstractConnectorHttpClientTrans
.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())
protocol = new Origin.Protocol(protocols, ssl && protocols.contains(http2));
@ -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

View File

@ -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();

View File

@ -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);
}
HttpRequest httpRequest = (HttpRequest)request;
HttpConversation conversation = httpRequest.getConversation();
HttpUpgrader upgrader = (HttpUpgrader)conversation.getAttribute(HttpUpgrader.class.getName());
if (upgrader == null)
{
if (request instanceof HttpUpgrader.Factory)
{
HttpUpgrader upgrader = ((HttpUpgrader.Factory)request).newHttpUpgrader(HttpVersion.HTTP_1_1);
((HttpRequest)request).getConversation().setAttribute(HttpUpgrader.class.getName(), upgrader);
upgrader.prepare((HttpRequest)request);
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);
}
}
}
}

View File

@ -1,26 +0,0 @@
//
// ========================================================================
// 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 org.eclipse.jetty.client.HttpResponse;
public interface HttpConnectionUpgrader
{
public void upgrade(HttpResponse response, HttpConnectionOverHTTP connection);
}

View File

@ -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.
// Store the EndPoint is case of upgrades, tunnels, etc.
exchange.getRequest().getConversation().setAttribute(EndPoint.class.getName(), getHttpConnection().getEndPoint());
}
return !responseHeaders(exchange);
}

View File

@ -34,12 +34,12 @@ 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.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HttpSenderOverHTTP extends HttpSender
{
private static final Logger LOG = Log.getLogger(HttpSenderOverHTTP.class);
private static final Logger LOG = LoggerFactory.getLogger(HttpSenderOverHTTP.class);
private final IteratingCallback headersCallback = new HeadersCallback();
private final IteratingCallback contentCallback = new ContentCallback();

View File

@ -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));
}
}
}

View File

@ -29,16 +29,16 @@ import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.AutoLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>Implements the conversion from {@link ContentProvider} to {@link Request.Content}.</p>
*/
public class RequestContentAdapter implements Request.Content, Request.Content.Subscription, AsyncContentProvider.Listener, Callback
{
private static final Logger LOG = Log.getLogger(RequestContentAdapter.class);
private static final Logger LOG = LoggerFactory.getLogger(RequestContentAdapter.class);
private final AutoLock lock = new AutoLock();
private final ContentProvider provider;
@ -310,7 +310,7 @@ public class RequestContentAdapter implements Request.Content, Request.Content.S
}
catch (Exception x)
{
LOG.ignore(x);
LOG.trace("Failure while notifying content failure {}", failure, x);
}
}

View File

@ -24,13 +24,13 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.AutoLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AbstractRequestContent implements Request.Content
{
private static final Logger LOG = Log.getLogger(AbstractRequestContent.class);
private static final Logger LOG = LoggerFactory.getLogger(AbstractRequestContent.class);
private final AutoLock lock = new AutoLock();
private final String contentType;
@ -223,7 +223,7 @@ public abstract class AbstractRequestContent implements Request.Content
}
catch (Exception x)
{
LOG.ignore(x);
LOG.trace("Failure while notifying content failure {}", failure, x);
}
}

View File

@ -34,13 +34,13 @@ import java.util.stream.Stream;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.AutoLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AsyncRequestContent implements Request.Content, Request.Content.Subscription, Closeable
{
private static final Logger LOG = Log.getLogger(AsyncRequestContent.class);
private static final Logger LOG = LoggerFactory.getLogger(AsyncRequestContent.class);
private final AutoLock lock = new AutoLock();
private final Condition flush = lock.newCondition();
@ -287,7 +287,7 @@ public class AsyncRequestContent implements Request.Content, Request.Content.Sub
}
catch (Throwable x)
{
LOG.ignore(x);
LOG.trace("Failure while notifying content failure {}", failure, x);
}
}

View File

@ -34,8 +34,8 @@ import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>A {@link Request.Content} for form uploads with the {@code "multipart/form-data"}
@ -61,7 +61,7 @@ import org.eclipse.jetty.util.log.Logger;
*/
public class MultiPartRequestContent extends AbstractRequestContent implements Closeable
{
private static final Logger LOG = Log.getLogger(MultiPartRequestContent.class);
private static final Logger LOG = LoggerFactory.getLogger(MultiPartRequestContent.class);
private static final byte[] COLON_SPACE_BYTES = new byte[]{':', ' '};
private static final byte[] CR_LF_BYTES = new byte[]{'\r', '\n'};

View File

@ -33,8 +33,8 @@ import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>A {@link Request.Content} for files using JDK 7's {@code java.nio.file} APIs.</p>
@ -46,7 +46,7 @@ import org.eclipse.jetty.util.log.Logger;
*/
public class PathRequestContent extends AbstractRequestContent
{
private static final Logger LOG = Log.getLogger(PathRequestContent.class);
private static final Logger LOG = LoggerFactory.getLogger(PathRequestContent.class);
private final Path filePath;
private final long fileSize;

View File

@ -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);

View File

@ -55,15 +55,9 @@
<version>${project.version}</version>
<optional>true</optional>
</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>

View File

@ -42,7 +42,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -39,15 +39,9 @@
<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>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -16,23 +16,19 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.common.endpoints.annotated;
package org.eclipse.jetty.http.spi;
import org.eclipse.jetty.websocket.api.Frame;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
@WebSocket
public class FrameSocket
public final class LoggingUtil
{
/**
* A frame
*
* @param frame the frame
* 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).
*/
@OnWebSocketFrame
public void frameMe(Frame frame)
public static void init()
{
/* ignore */
// Wire up java.util.logging (used by javax.xml.soap others) to slf4j.
org.slf4j.bridge.SLF4JBridgeHandler.removeHandlersForRootLogger();
org.slf4j.bridge.SLF4JBridgeHandler.install();
}
}

View File

@ -44,6 +44,11 @@ import static org.hamcrest.Matchers.is;
public class SPIServerTest
{
static
{
LoggingUtil.init();
}
String host = "localhost";
HttpServer server;
int port;

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -47,7 +47,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -30,7 +30,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -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);
}

View File

@ -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);

View File

@ -62,7 +62,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -44,7 +44,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -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);
}
}
}
}

View File

@ -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;
}
}

View File

@ -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)
{

View File

@ -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 ?

View File

@ -38,12 +38,12 @@ import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HttpSenderOverHTTP2 extends HttpSender
{
private static final Logger LOG = Log.getLogger(HttpSenderOverHTTP2.class);
private static final Logger LOG = LoggerFactory.getLogger(HttpSenderOverHTTP2.class);
public HttpSenderOverHTTP2(HttpChannelOverHTTP2 channel)
{

View File

@ -80,7 +80,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -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;
}

View File

@ -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;

View File

@ -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>

View File

@ -0,0 +1,145 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.session.infinispan;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
/**
* BoundDelegatingInputStream
*
* An InputStream that delegates methods to an ObjectInput. The ObjectInput must start
* with an integer containing the length of the data.
*/
public class BoundDelegatingInputStream extends InputStream
{
protected final ObjectInput objectInput;
private final int length;
private int position = 0;
public BoundDelegatingInputStream(ObjectInput objectInput) throws IOException
{
this.objectInput = objectInput;
this.length = objectInput.readInt();
}
@Override
public int read() throws IOException
{
if (position < length)
{
position++;
return objectInput.read();
}
return -1;
}
@Override
public int read(byte[] b) throws IOException
{
int available = length - position;
int read = -1;
if (position == length)
{
return read;
}
if (b.length > available)
{
read = objectInput.read(b, 0, available);
}
else
{
read = objectInput.read(b);
}
if (read != -1)
{
position += read;
}
return read;
}
@Override
public int read(byte[] b, int off, int len) throws IOException
{
int read = -1;
if (position == length)
{
return read;
}
if (position + len > length)
{
read = objectInput.read(b, off, length - position);
}
else
{
read = objectInput.read(b, off, len);
}
if (read != -1)
{
position += read;
}
return read;
}
@Override
public long skip(long n) throws IOException
{
long skip = 0;
if (position + n < length)
{
skip = objectInput.skip(length - position);
}
else
{
skip = objectInput.skip(n);
}
if (skip > 0)
{
position += skip;
}
return skip;
}
@Override
public int available() throws IOException
{
if (position < length)
{
int available = objectInput.available();
if (position + available > length)
{
return length - position;
}
else
{
return available;
}
}
return 0;
}
@Override
public void close() throws IOException
{
objectInput.close();
}
}

View File

@ -26,6 +26,7 @@ import java.util.Map;
import org.eclipse.jetty.server.session.SessionData;
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
import org.infinispan.commons.marshall.SerializeWith;
/**
* InfinispanSessionData
@ -37,6 +38,7 @@ import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
* pool and thus these threads have no knowledge of the correct classloader to
* use.
*/
@SerializeWith(SessionDataMarshaller.class)
public class InfinispanSessionData extends SessionData
{
protected byte[] _serializedAttributes;

View File

@ -19,8 +19,14 @@
package org.eclipse.jetty.session.infinispan;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import org.infinispan.commons.marshall.Externalizer;
import org.infinispan.protostream.FileDescriptorSource;
import org.infinispan.protostream.MessageMarshaller;
import org.infinispan.protostream.ProtobufUtil;
import org.infinispan.protostream.SerializationContext;
/**
* SessionDataMarshaller
@ -30,13 +36,30 @@ import org.infinispan.protostream.MessageMarshaller;
* control to ensure that session attributes can be deserialized using either
* the container class loader or the webapp classloader, as appropriate.
*/
public class SessionDataMarshaller implements MessageMarshaller<InfinispanSessionData>
public class SessionDataMarshaller
implements MessageMarshaller<InfinispanSessionData>, Externalizer<InfinispanSessionData>
{
/**
* The version of the serializer.
*/
private static final int VERSION = 0;
private static SerializationContext serializationContext;
private static synchronized void initSerializationContext() throws IOException
{
if (serializationContext != null)
{
return;
}
FileDescriptorSource fds = new FileDescriptorSource();
fds.addProtoFiles("/session.proto");
SerializationContext sCtx = ProtobufUtil.newSerializationContext();
sCtx.registerProtoFiles(fds);
sCtx.registerMarshaller(new SessionDataMarshaller());
serializationContext = sCtx;
}
@Override
public Class<? extends InfinispanSessionData> getJavaClass()
{
@ -49,6 +72,39 @@ public class SessionDataMarshaller implements MessageMarshaller<InfinispanSessio
return "org_eclipse_jetty_session_infinispan.InfinispanSessionData";
}
@Override
public InfinispanSessionData readObject(ObjectInput input) throws IOException, ClassNotFoundException
{
if (serializationContext == null)
{
initSerializationContext();
}
// invokes readFrom(ProtoStreamReader)
InfinispanSessionData data = ProtobufUtil.readFrom(serializationContext, new BoundDelegatingInputStream(input),
InfinispanSessionData.class);
if (data != null)
{
data.deserializeAttributes();
}
return data;
}
@Override
public void writeObject(ObjectOutput output, InfinispanSessionData object) throws IOException
{
if (serializationContext == null)
{
initSerializationContext();
}
// invokes writeTo(ProtoStreamWriter, InfinispanSessionData)
byte[] data = ProtobufUtil.toByteArray(serializationContext, object);
int length = data.length;
output.writeInt(length);
output.write(data);
}
@Override
public InfinispanSessionData readFrom(ProtoStreamReader in) throws IOException
{
@ -67,7 +123,8 @@ public class SessionDataMarshaller implements MessageMarshaller<InfinispanSessio
final long expiry = in.readLong("expiry");
final long maxInactiveMs = in.readLong("maxInactiveMs");
InfinispanSessionData sd = new InfinispanSessionData(id, cpath, vhost, created, accessed, lastAccessed, maxInactiveMs);
InfinispanSessionData sd = new InfinispanSessionData(id, cpath, vhost, created, accessed, lastAccessed,
maxInactiveMs);
sd.setCookieSet(cookieSet);
sd.setLastNode(lastNode);
sd.setExpiry(expiry);
@ -103,4 +160,5 @@ public class SessionDataMarshaller implements MessageMarshaller<InfinispanSessio
sdata.serializeAttributes();
out.writeBytes("attributes", sdata.getSerializedAttributes());
}
}

View File

@ -25,7 +25,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -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()
{

View File

@ -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;

View File

@ -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>

View File

@ -0,0 +1,3 @@
# Jetty Logging using jetty-slf4j-impl
org.eclipse.jetty.LEVEL=INFO
org.apache.directory.LEVEL=ERROR

View File

@ -1 +0,0 @@
org.slf4j.simpleLogger.log.org.apache.directory=error

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -93,6 +93,18 @@
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.4.0-b180830.0359</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>javax.activation-api</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
@ -121,40 +133,7 @@
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jdk9+</id>
<activation>
<jdk>[1.9,)</jdk>
</activation>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.4.0-b180830.0359</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>javax.activation-api</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
</project>

View File

@ -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>

View File

@ -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>

View File

@ -39,7 +39,18 @@
<directory>src/main/context</directory>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<!-- No point building javadoc on testing projects -->
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -19,7 +19,18 @@
<directory>src/main/resources</directory>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<!-- No point building javadoc on testing projects -->
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -31,6 +31,18 @@
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<!-- No point building javadoc on testing projects -->
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -36,7 +36,18 @@
<directory>src/main/resources</directory>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<!-- No point building javadoc on testing projects -->
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -477,6 +477,14 @@
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<!-- No point building javadoc on testing projects -->
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>

View File

@ -53,11 +53,6 @@
<artifactId>derby</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</groupId>
<artifactId>jetty-jndi</artifactId>
@ -68,11 +63,13 @@
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.1.2.1</version>
<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>

View File

@ -57,11 +57,6 @@
<artifactId>jetty-alpn-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-util-ajax</artifactId>
@ -77,7 +72,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1,2 @@
# Jetty Logging using jetty-slf4j-impl
org.eclipse.jetty.LEVEL=INFO

View File

@ -58,7 +58,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -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>

View File

@ -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)
{

View File

@ -693,8 +693,16 @@ public class DetectorConnectionTest
start(detector, http);
String request = "AAAA".repeat(32768);
String response = getResponse(request);
try
{
String response = getResponse(request);
assertThat(response, Matchers.nullValue());
}
catch (SocketException expected)
{
// The test may fail writing the "request"
// bytes as the server sends back a TCP RST.
}
}
}

View File

@ -60,7 +60,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -71,7 +71,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -57,11 +57,11 @@ public class StdErrAppender implements JettyAppender
/**
* The stream to write logging events to.
*/
private PrintStream stderr;
private PrintStream stream;
public StdErrAppender(JettyLoggerConfiguration config)
{
this(config, System.err);
this(config, null);
}
public StdErrAppender(JettyLoggerConfiguration config, PrintStream stream)
@ -72,7 +72,7 @@ public class StdErrAppender implements JettyAppender
public StdErrAppender(JettyLoggerConfiguration config, PrintStream stream, TimeZone timeZone)
{
Objects.requireNonNull(config, "JettyLoggerConfiguration");
this.stderr = Objects.requireNonNull(stream, "PrintStream");
this.stream = stream;
TimeZone tzone = timeZone;
if (tzone == null)
@ -96,7 +96,14 @@ public class StdErrAppender implements JettyAppender
{
StringBuilder builder = new StringBuilder(64);
format(builder, logger, level, timestamp, threadName, throwable, message, argumentArray);
stderr.println(builder);
if (stream != null)
{
stream.println(builder);
}
else
{
System.err.println(builder);
}
}
public boolean isCondensedNames()
@ -116,12 +123,12 @@ public class StdErrAppender implements JettyAppender
public PrintStream getStream()
{
return stderr;
return stream;
}
public void setStream(PrintStream stream)
{
this.stderr = stream;
this.stream = stream;
}
private void format(StringBuilder builder, JettyLogger logger, Level level, long timestamp, String threadName, Throwable throwable, String message, Object... argumentArray)

View File

@ -65,7 +65,14 @@ public class Slf4jEffort
AtomicInteger countPomSlf4jImpls = new AtomicInteger(0);
AtomicInteger countOldLogClassProps = new AtomicInteger(0);
getProjectsStream(root).forEach((pom) ->
getProjectsStream(root)
.filter(pom ->
{
String fullpath = pom.toString();
return !((fullpath.contains("/jetty-osgi") ||
fullpath.contains("/jetty-slf4j-impl/")));
})
.forEach((pom) ->
{
Path project = pom.getParent();
try
@ -77,6 +84,12 @@ public class Slf4jEffort
if (isMainSrcUsingLogging || isTestSrcUsingLogging)
{
if (!isSlf4jImplDepPresent(pom))
{
System.err.printf("[Missing: Dep: jetty-slf4j-impl] %s%n", pom);
countPomSlf4jImpls.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))
@ -87,16 +100,10 @@ public class Slf4jEffort
if (!isSlf4jDepPresent(pom))
{
// System.err.printf("[Missing: Dep: slf4j-api] %s%n", pom);
System.err.printf("[Missing: Dep: slf4j-api] %s%n", pom);
countPomSlf4jApis.incrementAndGet();
}
if (isTestSrcUsingLogging && !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);
@ -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;
}

View File

@ -70,7 +70,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-slf4j-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -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>

View File

@ -92,8 +92,8 @@ public class Modules implements Iterable<Module>
_modules.stream()
.filter(m ->
{
boolean included = all || m.getTags().stream().anyMatch(t -> include.contains(t));
boolean excluded = m.getTags().stream().anyMatch(t -> exclude.contains(t));
boolean included = all || m.getTags().stream().anyMatch(include::contains);
boolean excluded = m.getTags().stream().anyMatch(exclude::contains);
return included && !excluded;
})
.sorted()
@ -274,7 +274,7 @@ public class Modules implements Iterable<Module>
public List<Module> getEnabled()
{
List<Module> enabled = _modules.stream().filter(m -> m.isEnabled()).collect(Collectors.toList());
List<Module> enabled = _modules.stream().filter(Module::isEnabled).collect(Collectors.toList());
TopologicalSort<Module> sort = new TopologicalSort<>();
for (Module module : enabled)
@ -303,7 +303,7 @@ public class Modules implements Iterable<Module>
public List<Module> getSortedAll()
{
List<Module> all = new ArrayList(_modules);
List<Module> all = new ArrayList<>(_modules);
TopologicalSort<Module> sort = new TopologicalSort<>();
for (Module module : all)
@ -569,10 +569,12 @@ public class Modules implements Iterable<Module>
_modules.stream().filter(Module::isEnabled).forEach(m ->
{
// Check dependencies
m.getDepends().forEach(d ->
m.getDepends().stream()
.filter(Module::isRequiredDependency)
.forEach(d ->
{
Set<Module> providers = getAvailableProviders(d);
if (providers.stream().filter(Module::isEnabled).count() == 0)
if (providers.stream().noneMatch(Module::isEnabled))
{
if (unsatisfied.length() > 0)
unsatisfied.append(',');

Some files were not shown because too many files have changed in this diff Show More