Merged branch 'jetty-10.0.x' into 'jetty-10.0.x-4400-review_httpclient_content'.
This commit is contained in:
commit
e215d071c8
|
@ -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']]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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'};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,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();
|
||||
}
|
||||
}
|
|
@ -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 ?
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue