Merged branch 'cowwoc-jetty-12.0.x-8723-provide-a-thread-safe-way-to-modify-proxies-at-runtime' into 'jetty-12.0.x'.
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
commit
67c36207c2
|
@ -40,16 +40,6 @@ public class ProxyConfiguration
|
|||
{
|
||||
private final List<Proxy> proxies = new BlockingArrayQueue<>();
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #addProxy(Proxy)} and {@link #removeProxy(Proxy)} instead
|
||||
* @return the forward proxies to use
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public List<Proxy> getProxies()
|
||||
{
|
||||
return proxies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a proxy.
|
||||
*
|
||||
|
|
|
@ -480,7 +480,7 @@ public abstract class ProxyHandler extends Handler.Processor
|
|||
* <p>Forward proxies are configured in client applications that use
|
||||
* {@link HttpClient} in this way:</p>
|
||||
* <pre>{@code
|
||||
* httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort));
|
||||
* httpClient.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort));
|
||||
* }</pre>
|
||||
*
|
||||
* @see org.eclipse.jetty.client.ProxyConfiguration
|
||||
|
|
|
@ -78,83 +78,81 @@ public interface ConnectionMetaData extends Attributes
|
|||
|
||||
class Wrapper extends Attributes.Wrapper implements ConnectionMetaData
|
||||
{
|
||||
private final ConnectionMetaData _wrapped;
|
||||
|
||||
public Wrapper(ConnectionMetaData wrapped)
|
||||
{
|
||||
super(wrapped);
|
||||
_wrapped = wrapped;
|
||||
}
|
||||
|
||||
protected ConnectionMetaData getWrappedConnectionMetaData()
|
||||
@Override
|
||||
public ConnectionMetaData getWrapped()
|
||||
{
|
||||
return _wrapped;
|
||||
return (ConnectionMetaData)super.getWrapped();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId()
|
||||
{
|
||||
return _wrapped.getId();
|
||||
return getWrapped().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpConfiguration getHttpConfiguration()
|
||||
{
|
||||
return _wrapped.getHttpConfiguration();
|
||||
return getWrapped().getHttpConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpVersion getHttpVersion()
|
||||
{
|
||||
return _wrapped.getHttpVersion();
|
||||
return getWrapped().getHttpVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return _wrapped.getProtocol();
|
||||
return getWrapped().getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection()
|
||||
{
|
||||
return _wrapped.getConnection();
|
||||
return getWrapped().getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connector getConnector()
|
||||
{
|
||||
return _wrapped.getConnector();
|
||||
return getWrapped().getConnector();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent()
|
||||
{
|
||||
return _wrapped.isPersistent();
|
||||
return getWrapped().isPersistent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure()
|
||||
{
|
||||
return _wrapped.isSecure();
|
||||
return getWrapped().isSecure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketAddress getRemoteSocketAddress()
|
||||
{
|
||||
return _wrapped.getRemoteSocketAddress();
|
||||
return getWrapped().getRemoteSocketAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketAddress getLocalSocketAddress()
|
||||
{
|
||||
return _wrapped.getLocalSocketAddress();
|
||||
return getWrapped().getLocalSocketAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostPort getServerAuthority()
|
||||
{
|
||||
return _wrapped.getServerAuthority();
|
||||
return getWrapped().getServerAuthority();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -597,7 +597,7 @@ public class ForwardedRequestCustomizer implements HttpConfiguration.Customizer
|
|||
getId(),
|
||||
remote,
|
||||
authority,
|
||||
getWrappedConnectionMetaData()
|
||||
getWrapped()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.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.server;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
||||
/**
|
||||
* Abstraction of the outbound HTTP transport.
|
||||
*/
|
||||
public interface HttpTransport
|
||||
{
|
||||
String UPGRADE_CONNECTION_ATTRIBUTE = HttpTransport.class.getName() + ".UPGRADE";
|
||||
|
||||
/**
|
||||
* Asynchronous call to send a response (or part) over the transport
|
||||
*
|
||||
* @param request True if the response if for a HEAD request (and the data should not be sent).
|
||||
* @param response The header info to send, or null if just sending more data.
|
||||
* The first call to send for a response must have a non null info.
|
||||
* @param content A buffer of content to be sent.
|
||||
* @param lastContent True if the content is the last content for the current response.
|
||||
* @param callback The Callback instance that success or failure of the send is notified on
|
||||
*/
|
||||
void send(MetaData.Request request, MetaData.Response response, ByteBuffer content, boolean lastContent, Callback callback);
|
||||
|
||||
/**
|
||||
* @return true if responses can be pushed over this transport
|
||||
*/
|
||||
boolean isPushSupported();
|
||||
|
||||
/**
|
||||
* @param request A request to use as the basis for generating a pushed response.
|
||||
*/
|
||||
void push(MetaData.Request request);
|
||||
|
||||
/**
|
||||
* Called to indicated the end of the current request/response cycle (which may be
|
||||
* some time after the last content is sent).
|
||||
*/
|
||||
void onCompleted();
|
||||
|
||||
/**
|
||||
* Aborts this transport.
|
||||
* <p>
|
||||
* This method should terminate the transport in a way that
|
||||
* can indicate an abnormal response to the client, for example
|
||||
* by abruptly close the connection.
|
||||
* <p>
|
||||
* This method is called when an error response needs to be sent,
|
||||
* but the response is already committed, or when a write failure
|
||||
* is detected. If abort is called, {@link #onCompleted()} is not
|
||||
* called
|
||||
*
|
||||
* @param failure the failure that caused the abort.
|
||||
*/
|
||||
void abort(Throwable failure);
|
||||
}
|
|
@ -110,7 +110,7 @@ public class ErrorProcessor implements Request.Processor
|
|||
|
||||
try
|
||||
{
|
||||
generateAcceptableResponse(request, response, code, message, cause, callback);
|
||||
generateResponse(request, response, code, message, cause, callback);
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
|
@ -120,7 +120,7 @@ public class ErrorProcessor implements Request.Processor
|
|||
}
|
||||
}
|
||||
|
||||
protected void generateAcceptableResponse(Request request, Response response, int code, String message, Throwable cause, Callback callback) throws IOException
|
||||
protected void generateResponse(Request request, Response response, int code, String message, Throwable cause, Callback callback) throws IOException
|
||||
{
|
||||
List<String> acceptable = request.getHeaders().getQualityCSV(HttpHeader.ACCEPT, QuotedQualityCSV.MOST_SPECIFIC_MIME_ORDERING);
|
||||
if (acceptable.isEmpty())
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.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.server.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.ExceptionUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* An ErrorProcessor that can re-handle a request at an error page location.
|
||||
*/
|
||||
public abstract class ReHandlingErrorProcessor extends ErrorProcessor
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ReHandlingErrorProcessor.class);
|
||||
|
||||
private final Handler _handler;
|
||||
|
||||
protected ReHandlingErrorProcessor(Handler handler)
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvocationType getInvocationType()
|
||||
{
|
||||
return _handler.getInvocationType();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateResponse(Request request, Response response, int code, String message, Throwable cause, Callback callback) throws IOException
|
||||
{
|
||||
if (request.getAttribute(ReHandlingErrorProcessor.class.getName()) == null)
|
||||
{
|
||||
String pathInContext = getReHandlePathInContext(request, code, cause);
|
||||
|
||||
if (pathInContext != null)
|
||||
{
|
||||
request.setAttribute(ReHandlingErrorProcessor.class.getName(), pathInContext);
|
||||
HttpURI uri = HttpURI.build(request.getHttpURI()).path(URIUtil.addPaths(request.getContext().getContextPath(), pathInContext)).asImmutable();
|
||||
Request.Wrapper wrapper = new ReHandleRequestWrapper(request, uri, uri.getCanonicalPath());
|
||||
|
||||
try
|
||||
{
|
||||
Request.Processor processor = _handler.handle(wrapper);
|
||||
if (processor != null)
|
||||
{
|
||||
response.setStatus(200);
|
||||
processor.process(wrapper, response, callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Unable to process error {}", wrapper, e);
|
||||
if (cause != null && ExceptionUtil.areNotAssociated(cause, e))
|
||||
cause.addSuppressed(e);
|
||||
response.setStatus(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.generateResponse(request, response, code, message, cause, callback);
|
||||
}
|
||||
|
||||
protected abstract String getReHandlePathInContext(Request request, int code, Throwable cause);
|
||||
|
||||
/**
|
||||
* An ErrorPageErrorProcessor that uses a map of error codes to select a page.
|
||||
*/
|
||||
public static class ByHttpStatus extends ReHandlingErrorProcessor
|
||||
{
|
||||
private final Map<Integer, String> _statusMap = new ConcurrentHashMap<>();
|
||||
|
||||
public ByHttpStatus(Handler handler)
|
||||
{
|
||||
super(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getReHandlePathInContext(Request request, int code, Throwable cause)
|
||||
{
|
||||
return get(code);
|
||||
}
|
||||
|
||||
public String put(int code, String pathInContext)
|
||||
{
|
||||
return _statusMap.put(code, pathInContext);
|
||||
}
|
||||
|
||||
public String get(int code)
|
||||
{
|
||||
return _statusMap.get(code);
|
||||
}
|
||||
|
||||
public String remove(int code)
|
||||
{
|
||||
return _statusMap.remove(code);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ReHandleRequestWrapper extends Request.Wrapper
|
||||
{
|
||||
private final HttpURI _uri;
|
||||
private final String _pathInContext;
|
||||
|
||||
public ReHandleRequestWrapper(Request request, HttpURI uri, String pathInContext)
|
||||
{
|
||||
super(request);
|
||||
_uri = uri;
|
||||
_pathInContext = pathInContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpURI getHttpURI()
|
||||
{
|
||||
return _uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathInContext()
|
||||
{
|
||||
return _pathInContext;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -796,7 +796,7 @@ public class HttpChannelState implements HttpChannel, Components
|
|||
return _loggedRequest == null ? this : _loggedRequest;
|
||||
}
|
||||
|
||||
HttpStream getStream()
|
||||
HttpStream getHttpStream()
|
||||
{
|
||||
return getHttpChannel()._stream;
|
||||
}
|
||||
|
@ -1013,7 +1013,7 @@ public class HttpChannelState implements HttpChannel, Components
|
|||
@Override
|
||||
public void push(MetaData.Request request)
|
||||
{
|
||||
getStream().push(request);
|
||||
getHttpStream().push(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1047,7 +1047,7 @@ public class HttpChannelState implements HttpChannel, Components
|
|||
@Override
|
||||
public TunnelSupport getTunnelSupport()
|
||||
{
|
||||
return getStream().getTunnelSupport();
|
||||
return getHttpStream().getTunnelSupport();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1468,7 +1468,7 @@ public class HttpChannelState implements HttpChannel, Components
|
|||
public InvocationType getInvocationType()
|
||||
{
|
||||
// TODO review this as it is probably not correct
|
||||
return _request.getStream().getInvocationType();
|
||||
return _request.getHttpStream().getInvocationType();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,11 +25,13 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.io.QuietException;
|
||||
import org.eclipse.jetty.logging.StacklessLogging;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.server.handler.ErrorProcessor;
|
||||
import org.eclipse.jetty.server.handler.ReHandlingErrorProcessor;
|
||||
import org.eclipse.jetty.server.internal.HttpChannelState;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
@ -111,6 +113,17 @@ public class ErrorProcessorTest
|
|||
throw new TestException(message);
|
||||
}
|
||||
|
||||
// 200 response
|
||||
if (request.getPathInContext().startsWith("/ok/"))
|
||||
{
|
||||
Content.Sink.write(
|
||||
response,
|
||||
true,
|
||||
"%s Error %s : %s%n".formatted(request.getPathInContext(), request.getAttribute(ErrorProcessor.ERROR_STATUS), request.getAttribute(ErrorProcessor.ERROR_MESSAGE)),
|
||||
callback);
|
||||
return;
|
||||
}
|
||||
|
||||
Response.writeError(request, response, callback, 404);
|
||||
}
|
||||
});
|
||||
|
@ -689,6 +702,104 @@ public class ErrorProcessorTest
|
|||
assertThat(response, containsString("Server Error"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRootReHandlingErrorProcessor() throws Exception
|
||||
{
|
||||
ReHandlingErrorProcessor.ByHttpStatus errorProcessor = new ReHandlingErrorProcessor.ByHttpStatus(server);
|
||||
errorProcessor.put(400, "/ok/badMessage");
|
||||
server.setErrorProcessor(errorProcessor);
|
||||
|
||||
String rawResponse = connector.getResponse("""
|
||||
GET /no/host HTTP/1.1
|
||||
|
||||
""");
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||
|
||||
assertThat(response.getStatus(), is(200));
|
||||
assertThat(response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0));
|
||||
assertThat(response.getContent(), containsString("/ok/badMessage Error 400 : No Host"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRootReHandlingErrorProcessorLoop() throws Exception
|
||||
{
|
||||
ReHandlingErrorProcessor.ByHttpStatus errorProcessor = new ReHandlingErrorProcessor.ByHttpStatus(server);
|
||||
errorProcessor.put(404, "/not/found");
|
||||
server.setErrorProcessor(errorProcessor);
|
||||
|
||||
String rawResponse = connector.getResponse("""
|
||||
GET /not/found HTTP/1.1
|
||||
Host: localhost
|
||||
|
||||
""");
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||
|
||||
assertThat(response.getStatus(), is(404));
|
||||
assertThat(response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0));
|
||||
assertThat(response.getContent(), containsString("<title>Error 404 Not Found</title>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRootReHandlingErrorProcessorExceptionLoop() throws Exception
|
||||
{
|
||||
ReHandlingErrorProcessor.ByHttpStatus errorProcessor = new ReHandlingErrorProcessor.ByHttpStatus(server);
|
||||
errorProcessor.put(444, "/badmessage/444");
|
||||
server.setErrorProcessor(errorProcessor);
|
||||
|
||||
String rawResponse = connector.getResponse("""
|
||||
GET /badmessage/444 HTTP/1.1
|
||||
Host: localhost
|
||||
|
||||
""");
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||
|
||||
assertThat(response.getStatus(), is(444));
|
||||
assertThat(response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0));
|
||||
assertThat(response.getContent(), containsString("<title>Error 444</title>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContextReHandlingErrorProcessor() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
|
||||
ContextHandler context = new ContextHandler("/ctx");
|
||||
context.setHandler(server.getHandler());
|
||||
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
contexts.addHandler(context);
|
||||
server.setHandler(contexts);
|
||||
|
||||
server.setErrorProcessor(new ErrorProcessor()
|
||||
{
|
||||
@Override
|
||||
public void process(Request request, Response response, Callback callback)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
});
|
||||
|
||||
server.start();
|
||||
ReHandlingErrorProcessor.ByHttpStatus errorProcessor = new ReHandlingErrorProcessor.ByHttpStatus(context);
|
||||
errorProcessor.put(444, "/ok/badMessage");
|
||||
context.setErrorProcessor(errorProcessor);
|
||||
|
||||
String rawResponse = connector.getResponse("""
|
||||
GET /ctx/badmessage/444 HTTP/1.1
|
||||
Host: localhost
|
||||
|
||||
""");
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||
|
||||
assertThat(response.getStatus(), is(200));
|
||||
assertThat(response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0));
|
||||
assertThat(response.getContent(), containsString("/ok/badMessage Error 444"));
|
||||
}
|
||||
|
||||
static class TestException extends RuntimeException implements QuietException
|
||||
{
|
||||
public TestException(String message)
|
||||
|
|
|
@ -261,7 +261,7 @@ public class ForwardProxyWithDynamicTransportTest
|
|||
int proxyPort = proxySecure ? proxyTLSConnector.getLocalPort() : proxyConnector.getLocalPort();
|
||||
Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort);
|
||||
HttpProxy proxy = new HttpProxy(proxyAddress, proxySecure, proxyProtocol);
|
||||
client.getProxyConfiguration().getProxies().add(proxy);
|
||||
client.getProxyConfiguration().addProxy(proxy);
|
||||
|
||||
String scheme = serverSecure ? "https" : "http";
|
||||
int serverPort = serverSecure ? serverTLSConnector.getLocalPort() : serverConnector.getLocalPort();
|
||||
|
@ -298,7 +298,7 @@ public class ForwardProxyWithDynamicTransportTest
|
|||
int proxyPort = proxyConnector.getLocalPort();
|
||||
Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort);
|
||||
HttpProxy proxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false));
|
||||
client.getProxyConfiguration().getProxies().add(proxy);
|
||||
client.getProxyConfiguration().addProxy(proxy);
|
||||
|
||||
long idleTimeout = 1000;
|
||||
http2Client.setStreamIdleTimeout(idleTimeout);
|
||||
|
@ -339,7 +339,7 @@ public class ForwardProxyWithDynamicTransportTest
|
|||
int proxyPort = proxyConnector.getLocalPort();
|
||||
Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort);
|
||||
HttpProxy httpProxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false));
|
||||
client.getProxyConfiguration().getProxies().add(httpProxy);
|
||||
client.getProxyConfiguration().addProxy(httpProxy);
|
||||
proxy.stop();
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
|
@ -376,7 +376,7 @@ public class ForwardProxyWithDynamicTransportTest
|
|||
int proxyPort = proxyConnector.getLocalPort();
|
||||
Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort);
|
||||
HttpProxy httpProxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false));
|
||||
client.getProxyConfiguration().getProxies().add(httpProxy);
|
||||
client.getProxyConfiguration().addProxy(httpProxy);
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
client.newRequest("localhost", serverConnector.getLocalPort())
|
||||
|
|
|
@ -42,7 +42,7 @@ public class ProxyServerTest extends AbstractEmbeddedTest
|
|||
server.start();
|
||||
|
||||
URI uri = server.getURI();
|
||||
client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", uri.getPort()));
|
||||
client.getProxyConfiguration().addProxy(new HttpProxy("localhost", uri.getPort()));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
|
|
@ -153,7 +153,7 @@ public class AsyncMiddleManServletTest
|
|||
clientPool.setName("client");
|
||||
client = new HttpClient();
|
||||
client.setExecutor(clientPool);
|
||||
client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort()));
|
||||
client.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort()));
|
||||
client.start();
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ public class ProxyServletFailureTest
|
|||
QueuedThreadPool executor = new QueuedThreadPool();
|
||||
executor.setName("client");
|
||||
result.setExecutor(executor);
|
||||
result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort()));
|
||||
result.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort()));
|
||||
result.start();
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ public class ProxyServletLoadTest
|
|||
clientPool.setName("client");
|
||||
HttpClient result = new HttpClient();
|
||||
result.setExecutor(clientPool);
|
||||
result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort()));
|
||||
result.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort()));
|
||||
result.start();
|
||||
client = result;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ import org.eclipse.jetty.client.ConnectionPool;
|
|||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.HttpDestination;
|
||||
import org.eclipse.jetty.client.HttpProxy;
|
||||
import org.eclipse.jetty.client.ProxyConfiguration.Proxy;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.api.Response;
|
||||
|
@ -124,6 +125,7 @@ public class ProxyServletTest
|
|||
}
|
||||
|
||||
private HttpClient client;
|
||||
private Proxy clientProxy;
|
||||
private Server proxy;
|
||||
private ServerConnector proxyConnector;
|
||||
private ServletContextHandler proxyContext;
|
||||
|
@ -198,6 +200,7 @@ public class ProxyServletTest
|
|||
|
||||
private void startClient(Consumer<HttpClient> consumer) throws Exception
|
||||
{
|
||||
clientProxy = new HttpProxy("localhost", proxyConnector.getLocalPort());
|
||||
client = prepareClient(consumer);
|
||||
}
|
||||
|
||||
|
@ -207,7 +210,7 @@ public class ProxyServletTest
|
|||
clientPool.setName("client");
|
||||
HttpClient result = new HttpClient();
|
||||
result.setExecutor(clientPool);
|
||||
result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort()));
|
||||
result.getProxyConfiguration().addProxy(clientProxy);
|
||||
if (consumer != null)
|
||||
consumer.accept(result);
|
||||
result.start();
|
||||
|
@ -730,7 +733,7 @@ public class ProxyServletTest
|
|||
startProxy(proxyServletClass);
|
||||
startClient();
|
||||
int port = serverConnector.getLocalPort();
|
||||
client.getProxyConfiguration().getProxies().get(0).getExcludedAddresses().add("127.0.0.1:" + port);
|
||||
clientProxy.getExcludedAddresses().add("127.0.0.1:" + port);
|
||||
|
||||
// Try with a proxied host
|
||||
ContentResponse response = client.newRequest("localhost", port)
|
||||
|
|
|
@ -52,20 +52,13 @@ import org.eclipse.jetty.http.HttpFields;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.io.ByteBufferInputStream;
|
||||
import org.eclipse.jetty.io.Content;
|
||||
import org.eclipse.jetty.server.Components;
|
||||
import org.eclipse.jetty.server.ConnectionMetaData;
|
||||
import org.eclipse.jetty.server.Context;
|
||||
import org.eclipse.jetty.server.HttpStream;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.ResourceContentFactory;
|
||||
import org.eclipse.jetty.server.ResourceService;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
import org.eclipse.jetty.server.TunnelSupport;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.Blocker;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
@ -372,7 +365,7 @@ public class DefaultServlet extends HttpServlet
|
|||
if (coreResponse.isCommitted())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Response already committed for {}", coreRequest._request.getHttpURI());
|
||||
LOG.debug("Response already committed for {}", coreRequest.getHttpURI());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -419,19 +412,18 @@ public class DefaultServlet extends HttpServlet
|
|||
doGet(req, resp);
|
||||
}
|
||||
|
||||
private static class ServletCoreRequest implements Request
|
||||
private static class ServletCoreRequest extends Request.Wrapper
|
||||
{
|
||||
// TODO fully implement this class and move it to the top level
|
||||
// TODO Some methods are directed to core that probably should be intercepted
|
||||
|
||||
private final HttpServletRequest _servletRequest;
|
||||
private final Request _request;
|
||||
private final HttpFields _httpFields;
|
||||
|
||||
ServletCoreRequest(HttpServletRequest request)
|
||||
{
|
||||
super(ServletContextRequest.getServletContextRequest(request));
|
||||
_servletRequest = request;
|
||||
_request = ServletContextRequest.getServletContextRequest(request);
|
||||
|
||||
HttpFields.Mutable fields = HttpFields.build();
|
||||
|
||||
|
@ -455,108 +447,36 @@ public class DefaultServlet extends HttpServlet
|
|||
return _httpFields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpFields getTrailers()
|
||||
{
|
||||
return _request.getTrailers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpURI getHttpURI()
|
||||
{
|
||||
return _request.getHttpURI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathInContext()
|
||||
{
|
||||
return URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void demand(Runnable demandCallback)
|
||||
{
|
||||
_request.demand(demandCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(Throwable failure)
|
||||
{
|
||||
_request.fail(failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId()
|
||||
{
|
||||
return _servletRequest.getRequestId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Components getComponents()
|
||||
{
|
||||
return _request.getComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionMetaData getConnectionMetaData()
|
||||
{
|
||||
return _request.getConnectionMetaData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod()
|
||||
{
|
||||
return _servletRequest.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getContext()
|
||||
{
|
||||
return _request.getContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeStamp()
|
||||
{
|
||||
return _request.getTimeStamp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure()
|
||||
{
|
||||
return _servletRequest.isSecure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Content.Chunk read()
|
||||
{
|
||||
return _request.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPushSupported()
|
||||
{
|
||||
return _request.isPushSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(MetaData.Request request)
|
||||
{
|
||||
this._request.push(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addErrorListener(Predicate<Throwable> onError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunnelSupport getTunnelSupport()
|
||||
{
|
||||
return _request.getTunnelSupport();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHttpStreamWrapper(Function<HttpStream, HttpStream.Wrapper> wrapper)
|
||||
{
|
||||
|
|
|
@ -838,8 +838,6 @@ public class ServletChannel implements Runnable
|
|||
/**
|
||||
* If a write or similar operation to this channel fails,
|
||||
* then this method should be called.
|
||||
* <p>
|
||||
* The standard implementation calls {@code HttpTransport#abort(Throwable)}.
|
||||
*
|
||||
* @param failure the failure that caused the abort.
|
||||
*/
|
||||
|
|
|
@ -65,13 +65,8 @@ import org.slf4j.LoggerFactory;
|
|||
import static org.eclipse.jetty.util.thread.Invocable.InvocationType.NON_BLOCKING;
|
||||
|
||||
/**
|
||||
* HttpChannel represents a single endpoint for HTTP semantic processing.
|
||||
* The HttpChannel is both an HttpParser.RequestHandler, where it passively receives events from
|
||||
* an incoming HTTP request, and a Runnable, where it actively takes control of the request/response
|
||||
* life cycle and calls the application (perhaps suspending and resuming with multiple calls to run).
|
||||
* The HttpChannel signals the switch from passive mode to active mode by returning true to one of the
|
||||
* HttpParser.RequestHandler callbacks. The completion of the active phase is signalled by a call to
|
||||
* HttpTransport.completed().
|
||||
* <p>The state machine that processes a request/response
|
||||
* cycle interpreting the HTTP and Servlet semantic.</p>
|
||||
*/
|
||||
public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
||||
{
|
||||
|
|
|
@ -35,15 +35,15 @@ import org.slf4j.LoggerFactory;
|
|||
public class PushBuilderImpl implements PushBuilder
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PushBuilderImpl.class);
|
||||
|
||||
private static final HttpField JETTY_PUSH = new HttpField("x-http2-push", "PushBuilder");
|
||||
private static EnumSet<HttpMethod> UNSAFE_METHODS = EnumSet.of(
|
||||
private static final EnumSet<HttpMethod> UNSAFE_METHODS = EnumSet.of(
|
||||
HttpMethod.POST,
|
||||
HttpMethod.PUT,
|
||||
HttpMethod.DELETE,
|
||||
HttpMethod.CONNECT,
|
||||
HttpMethod.OPTIONS,
|
||||
HttpMethod.TRACE);
|
||||
HttpMethod.TRACE
|
||||
);
|
||||
|
||||
private final Request _request;
|
||||
private final HttpFields.Mutable _fields;
|
||||
|
@ -51,7 +51,6 @@ public class PushBuilderImpl implements PushBuilder
|
|||
private String _queryString;
|
||||
private String _sessionId;
|
||||
private String _path;
|
||||
private String _lastModified;
|
||||
|
||||
public PushBuilderImpl(Request request, HttpFields fields, String method, String queryString, String sessionId)
|
||||
{
|
||||
|
@ -190,6 +189,5 @@ public class PushBuilderImpl implements PushBuilder
|
|||
|
||||
_request.getHttpChannel().getCoreRequest().push(push);
|
||||
_path = null;
|
||||
_lastModified = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,7 +205,7 @@ public class ForwardProxyServerTest
|
|||
ClientConnector clientConnector = new ClientConnector();
|
||||
clientConnector.setSslContextFactory(clientTLS);
|
||||
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
httpClient.start();
|
||||
|
||||
try
|
||||
|
@ -253,7 +253,7 @@ public class ForwardProxyServerTest
|
|||
});
|
||||
|
||||
HttpClient httpClient = new HttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
httpClient.start();
|
||||
|
||||
ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort())
|
||||
|
@ -291,7 +291,7 @@ public class ForwardProxyServerTest
|
|||
});
|
||||
|
||||
HttpClient httpClient = new HttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
httpClient.start();
|
||||
|
||||
ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort())
|
||||
|
|
|
@ -196,7 +196,7 @@ public class ForwardProxyTLSServerTest
|
|||
startProxy(proxyTLS);
|
||||
|
||||
HttpClient httpClient = newHttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
httpClient.start();
|
||||
|
||||
try
|
||||
|
@ -231,7 +231,7 @@ public class ForwardProxyTLSServerTest
|
|||
startProxy(proxyTLS);
|
||||
|
||||
HttpClient httpClient = newHttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
httpClient.start();
|
||||
|
||||
try
|
||||
|
@ -278,7 +278,7 @@ public class ForwardProxyTLSServerTest
|
|||
startProxy(proxyTLS);
|
||||
|
||||
HttpClient httpClient = newHttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
httpClient.start();
|
||||
|
||||
try
|
||||
|
@ -363,7 +363,7 @@ public class ForwardProxyTLSServerTest
|
|||
});
|
||||
|
||||
HttpClient httpClient = newHttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
// Short idle timeout for HttpClient.
|
||||
httpClient.setIdleTimeout(idleTimeout);
|
||||
httpClient.start();
|
||||
|
@ -401,7 +401,7 @@ public class ForwardProxyTLSServerTest
|
|||
stopProxy();
|
||||
|
||||
HttpClient httpClient = newHttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(new Origin.Address("localhost", proxyPort), proxySslContextFactory != null));
|
||||
httpClient.getProxyConfiguration().addProxy(new HttpProxy(new Origin.Address("localhost", proxyPort), proxySslContextFactory != null));
|
||||
httpClient.start();
|
||||
|
||||
ExecutionException x = assertThrows(ExecutionException.class, () ->
|
||||
|
@ -429,7 +429,7 @@ public class ForwardProxyTLSServerTest
|
|||
startProxy(proxyTLS);
|
||||
|
||||
HttpClient httpClient = newHttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
httpClient.start();
|
||||
|
||||
assertThrows(ExecutionException.class, () ->
|
||||
|
@ -461,7 +461,7 @@ public class ForwardProxyTLSServerTest
|
|||
});
|
||||
|
||||
HttpClient httpClient = newHttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
httpClient.start();
|
||||
|
||||
assertThrows(ExecutionException.class, () ->
|
||||
|
@ -484,7 +484,7 @@ public class ForwardProxyTLSServerTest
|
|||
|
||||
HttpClient httpClient = newHttpClient();
|
||||
HttpProxy httpProxy = new HttpProxy(new Origin.Address("[::1]", proxyConnector.getLocalPort()), proxyTLS != null);
|
||||
httpClient.getProxyConfiguration().getProxies().add(httpProxy);
|
||||
httpClient.getProxyConfiguration().addProxy(httpProxy);
|
||||
httpClient.start();
|
||||
|
||||
try
|
||||
|
@ -617,7 +617,7 @@ public class ForwardProxyTLSServerTest
|
|||
HttpProxy httpProxy = newHttpProxy();
|
||||
if (includeAddress)
|
||||
httpProxy.getIncludedAddresses().add("localhost:" + serverConnector.getLocalPort());
|
||||
httpClient.getProxyConfiguration().getProxies().add(httpProxy);
|
||||
httpClient.getProxyConfiguration().addProxy(httpProxy);
|
||||
URI uri = URI.create((proxySslContextFactory == null ? "http" : "https") + "://localhost:" + proxyConnector.getLocalPort());
|
||||
httpClient.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "proxyUser", "proxyPassword"));
|
||||
httpClient.start();
|
||||
|
@ -698,7 +698,7 @@ public class ForwardProxyTLSServerTest
|
|||
clientConnector.setSelectors(1);
|
||||
clientConnector.setSslContextFactory(clientSslContextFactory);
|
||||
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
httpClient.start();
|
||||
|
||||
try
|
||||
|
@ -769,7 +769,7 @@ public class ForwardProxyTLSServerTest
|
|||
proxyClientTLS.setEndpointIdentificationAlgorithm(null);
|
||||
proxyClientTLS.start();
|
||||
HttpProxy httpProxy = new HttpProxy(new Origin.Address("localhost", proxyConnector.getLocalPort()), proxyClientTLS);
|
||||
httpClient.getProxyConfiguration().getProxies().add(httpProxy);
|
||||
httpClient.getProxyConfiguration().addProxy(httpProxy);
|
||||
httpClient.start();
|
||||
|
||||
try
|
||||
|
@ -800,7 +800,7 @@ public class ForwardProxyTLSServerTest
|
|||
startProxy(proxyTLS);
|
||||
|
||||
HttpClient httpClient = newHttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||
httpClient.getProxyConfiguration().addProxy(newHttpProxy());
|
||||
httpClient.start();
|
||||
|
||||
try
|
||||
|
@ -851,7 +851,7 @@ public class ForwardProxyTLSServerTest
|
|||
}
|
||||
|
||||
HttpClient httpClient = newHttpClient();
|
||||
httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort));
|
||||
httpClient.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort));
|
||||
httpClient.start();
|
||||
|
||||
try
|
||||
|
|
|
@ -26,7 +26,9 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
|
|
Loading…
Reference in New Issue