summaryrefslogtreecommitdiffstats
path: root/container-core/src/main/java/com/yahoo/jdisc/http/server
diff options
context:
space:
mode:
Diffstat (limited to 'container-core/src/main/java/com/yahoo/jdisc/http/server')
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java7
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvoker.java28
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingPrintWriter.java266
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingServletOutputStream.java165
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterResolver.java7
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactory.java3
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscFilterInvokerFilter.java302
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java2
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java31
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/OneTimeRunnable.java23
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestUtils.java5
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/TlsClientAuthenticationEnforcer.java3
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/UnsupportedFilterInvoker.java32
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/testutils/ServletModule.java23
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/testutils/TestDriver.java3
15 files changed, 17 insertions, 883 deletions
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java
index 2eea7f155ee..b41c80a471c 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java
@@ -8,7 +8,6 @@ import com.yahoo.container.logging.RequestLog;
import com.yahoo.container.logging.RequestLogEntry;
import com.yahoo.jdisc.http.HttpRequest;
import com.yahoo.jdisc.http.ServerConfig;
-import com.yahoo.jdisc.http.servlet.ServletRequest;
import org.eclipse.jetty.http2.HTTP2Stream;
import org.eclipse.jetty.http2.server.HttpTransportOverHTTP2;
import org.eclipse.jetty.server.HttpChannel;
@@ -86,10 +85,10 @@ class AccessLogRequestLog extends AbstractLifeCycle implements org.eclipse.jetty
addNonNullValue(builder, jdiscRequest.getUserPrincipal(), RequestLogEntry.Builder::userPrincipal);
}
- String requestFilterId = (String) request.getAttribute(ServletRequest.JDISC_REQUEST_CHAIN);
+ String requestFilterId = (String) request.getAttribute(RequestUtils.JDISC_REQUEST_CHAIN);
addNonNullValue(builder, requestFilterId, (b, chain) -> b.addExtraAttribute("request-chain", chain));
- String responseFilterId = (String) request.getAttribute(ServletRequest.JDISC_RESPONSE_CHAIN);
+ String responseFilterId = (String) request.getAttribute(RequestUtils.JDISC_RESPONSE_CHAIN);
addNonNullValue(builder, responseFilterId, (b, chain) -> b.addExtraAttribute("response-chain", chain));
UUID connectionId = (UUID) request.getAttribute(JettyConnectionLogger.CONNECTION_ID_REQUEST_ATTRIBUTE);
@@ -109,7 +108,7 @@ class AccessLogRequestLog extends AbstractLifeCycle implements org.eclipse.jetty
builder.addExtraAttribute(header, value);
}
});
- X509Certificate[] clientCert = (X509Certificate[]) request.getAttribute(ServletRequest.SERVLET_REQUEST_X509CERT);
+ X509Certificate[] clientCert = (X509Certificate[]) request.getAttribute(RequestUtils.SERVLET_REQUEST_X509CERT);
if (clientCert != null && clientCert.length > 0) {
builder.sslPrincipal(clientCert[0].getSubjectX500Principal());
}
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvoker.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvoker.java
deleted file mode 100644
index 3c329bbf13b..00000000000
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvoker.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-import com.google.inject.ImplementedBy;
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.filter.RequestFilter;
-import com.yahoo.jdisc.http.filter.ResponseFilter;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.net.URI;
-
-/**
- * Separate interface since DiscFilterRequest/Response and Security filter chains are not accessible in this bundle
- */
-@ImplementedBy(UnsupportedFilterInvoker.class)
-public interface FilterInvoker {
- HttpServletRequest invokeRequestFilterChain(RequestFilter requestFilterChain,
- URI uri,
- HttpServletRequest httpRequest,
- ResponseHandler responseHandler);
-
- void invokeResponseFilterChain(
- ResponseFilter responseFilterChain,
- URI uri,
- HttpServletRequest request,
- HttpServletResponse response);
-}
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingPrintWriter.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingPrintWriter.java
deleted file mode 100644
index 90b12e64a55..00000000000
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingPrintWriter.java
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.Writer;
-import java.util.Locale;
-
-/**
- * Invokes the response filter the first time anything is output to the underlying PrintWriter.
- * The filter must be invoked before the first output call since this might cause the response
- * to be committed, i.e. locked and potentially put on the wire.
- * Any changes to the response after it has been committed might be ignored or cause exceptions.
- * @author Tony Vaagenes
- */
-final class FilterInvokingPrintWriter extends PrintWriter {
- private final PrintWriter delegate;
- private final OneTimeRunnable filterInvoker;
-
- public FilterInvokingPrintWriter(PrintWriter delegate, OneTimeRunnable filterInvoker) {
- /* The PrintWriter class both
- * 1) exposes new methods, the PrintWriter "interface"
- * 2) implements PrintWriter and Writer methods that does some extra things before calling down to the writer methods.
- * If super was invoked with the delegate PrintWriter, the superclass would behave as a PrintWriter(PrintWriter),
- * i.e. the extra things in 2. would be done twice.
- * To avoid this, all the methods of PrintWriter are overridden with versions that forward directly to the underlying delegate
- * instead of going through super.
- * The super class is initialized with a non-functioning writer to catch mistakenly non-overridden methods.
- */
- super(new Writer() {
- @Override
- public void write(char[] cbuf, int off, int len) throws IOException {
- throwAssertionError();
- }
-
- private void throwAssertionError() {
- throw new AssertionError(FilterInvokingPrintWriter.class.getName() + " failed to delegate to the underlying writer");
- }
-
- @Override
- public void flush() throws IOException {
- throwAssertionError();
- }
-
- @Override
- public void close() throws IOException {
- throwAssertionError();
- }
- });
-
- this.delegate = delegate;
- this.filterInvoker = filterInvoker;
- }
-
- @Override
- public String toString() {
- return getClass().getName() + " (" + super.toString() + ")";
- }
-
- private void runFilterIfFirstInvocation() {
- filterInvoker.runIfFirstInvocation();
- }
-
- @Override
- public void flush() {
- runFilterIfFirstInvocation();
- delegate.flush();
- }
-
- @Override
- public void close() {
- runFilterIfFirstInvocation();
- delegate.close();
- }
-
- @Override
- public boolean checkError() {
- return delegate.checkError();
- }
-
- @Override
- public void write(int c) {
- runFilterIfFirstInvocation();
- delegate.write(c);
- }
-
- @Override
- public void write(char[] buf, int off, int len) {
- runFilterIfFirstInvocation();
- delegate.write(buf, off, len);
- }
-
- @Override
- public void write(char[] buf) {
- runFilterIfFirstInvocation();
- delegate.write(buf);
- }
-
- @Override
- public void write(String s, int off, int len) {
- runFilterIfFirstInvocation();
- delegate.write(s, off, len);
- }
-
- @Override
- public void write(String s) {
- runFilterIfFirstInvocation();
- delegate.write(s);
- }
-
- @Override
- public void print(boolean b) {
- runFilterIfFirstInvocation();
- delegate.print(b);
- }
-
- @Override
- public void print(char c) {
- runFilterIfFirstInvocation();
- delegate.print(c);
- }
-
- @Override
- public void print(int i) {
- runFilterIfFirstInvocation();
- delegate.print(i);
- }
-
- @Override
- public void print(long l) {
- runFilterIfFirstInvocation();
- delegate.print(l);
- }
-
- @Override
- public void print(float f) {
- runFilterIfFirstInvocation();
- delegate.print(f);
- }
-
- @Override
- public void print(double d) {
- runFilterIfFirstInvocation();
- delegate.print(d);
- }
-
- @Override
- public void print(char[] s) {
- runFilterIfFirstInvocation();
- delegate.print(s);
- }
-
- @Override
- public void print(String s) {
- runFilterIfFirstInvocation();
- delegate.print(s);
- }
-
- @Override
- public void print(Object obj) {
- runFilterIfFirstInvocation();
- delegate.print(obj);
- }
-
- @Override
- public void println() {
- runFilterIfFirstInvocation();
- delegate.println();
- }
-
- @Override
- public void println(boolean x) {
- runFilterIfFirstInvocation();
- delegate.println(x);
- }
-
- @Override
- public void println(char x) {
- runFilterIfFirstInvocation();
- delegate.println(x);
- }
-
- @Override
- public void println(int x) {
- runFilterIfFirstInvocation();
- delegate.println(x);
- }
-
- @Override
- public void println(long x) {
- runFilterIfFirstInvocation();
- delegate.println(x);
- }
-
- @Override
- public void println(float x) {
- runFilterIfFirstInvocation();
- delegate.println(x);
- }
-
- @Override
- public void println(double x) {
- runFilterIfFirstInvocation();
- delegate.println(x);
- }
-
- @Override
- public void println(char[] x) {
- runFilterIfFirstInvocation();
- delegate.println(x);
- }
-
- @Override
- public void println(String x) {
- runFilterIfFirstInvocation();
- delegate.println(x);
- }
-
- @Override
- public void println(Object x) {
- runFilterIfFirstInvocation();
- delegate.println(x);
- }
-
- @Override
- public PrintWriter printf(String format, Object... args) {
- runFilterIfFirstInvocation();
- return delegate.printf(format, args);
- }
-
- @Override
- public PrintWriter printf(Locale l, String format, Object... args) {
- runFilterIfFirstInvocation();
- return delegate.printf(l, format, args);
- }
-
- @Override
- public PrintWriter format(String format, Object... args) {
- runFilterIfFirstInvocation();
- return delegate.format(format, args);
- }
-
- @Override
- public PrintWriter format(Locale l, String format, Object... args) {
- runFilterIfFirstInvocation();
- return delegate.format(l, format, args);
- }
-
- @Override
- public PrintWriter append(CharSequence csq) {
- runFilterIfFirstInvocation();
- return delegate.append(csq);
- }
-
- @Override
- public PrintWriter append(CharSequence csq, int start, int end) {
- runFilterIfFirstInvocation();
- return delegate.append(csq, start, end);
- }
-
- @Override
- public PrintWriter append(char c) {
- runFilterIfFirstInvocation();
- return delegate.append(c);
- }
-}
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingServletOutputStream.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingServletOutputStream.java
deleted file mode 100644
index d2be107ef86..00000000000
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingServletOutputStream.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-import javax.servlet.ServletOutputStream;
-import javax.servlet.WriteListener;
-import java.io.IOException;
-
-/**
- * Invokes the response filter the first time anything is output to the underlying ServletOutputStream.
- * The filter must be invoked before the first output call since this might cause the response
- * to be committed, i.e. locked and potentially put on the wire.
- * Any changes to the response after it has been committed might be ignored or cause exceptions.
- *
- * @author Tony Vaagenes
- */
-class FilterInvokingServletOutputStream extends ServletOutputStream {
- private final ServletOutputStream delegate;
- private final OneTimeRunnable filterInvoker;
-
- public FilterInvokingServletOutputStream(ServletOutputStream delegate, OneTimeRunnable filterInvoker) {
- this.delegate = delegate;
- this.filterInvoker = filterInvoker;
- }
-
- @Override
- public boolean isReady() {
- return delegate.isReady();
- }
-
- @Override
- public void setWriteListener(WriteListener writeListener) {
- delegate.setWriteListener(writeListener);
- }
-
-
- private void runFilterIfFirstInvocation() {
- filterInvoker.runIfFirstInvocation();
- }
-
- @Override
- public void write(int b) throws IOException {
- runFilterIfFirstInvocation();
- delegate.write(b);
- }
-
-
- @Override
- public void write(byte[] b) throws IOException {
- runFilterIfFirstInvocation();
- delegate.write(b);
- }
-
- @Override
- public void print(String s) throws IOException {
- runFilterIfFirstInvocation();
- delegate.print(s);
- }
-
- @Override
- public void write(byte[] b, int off, int len) throws IOException {
- runFilterIfFirstInvocation();
- delegate.write(b, off, len);
- }
-
- @Override
- public void print(boolean b) throws IOException {
- runFilterIfFirstInvocation();
- delegate.print(b);
- }
-
- @Override
- public void flush() throws IOException {
- runFilterIfFirstInvocation();
- delegate.flush();
- }
-
- @Override
- public void print(char c) throws IOException {
- runFilterIfFirstInvocation();
- delegate.print(c);
- }
-
- @Override
- public void close() throws IOException {
- runFilterIfFirstInvocation();
- delegate.close();
- }
-
- @Override
- public void print(int i) throws IOException {
- runFilterIfFirstInvocation();
- delegate.print(i);
- }
-
- @Override
- public void print(long l) throws IOException {
- runFilterIfFirstInvocation();
- delegate.print(l);
- }
-
- @Override
- public void print(float f) throws IOException {
- runFilterIfFirstInvocation();
- delegate.print(f);
- }
-
- @Override
- public void print(double d) throws IOException {
- runFilterIfFirstInvocation();
- delegate.print(d);
- }
-
- @Override
- public void println() throws IOException {
- runFilterIfFirstInvocation();
- delegate.println();
- }
-
- @Override
- public void println(String s) throws IOException {
- runFilterIfFirstInvocation();
- delegate.println(s);
- }
-
- @Override
- public void println(boolean b) throws IOException {
- runFilterIfFirstInvocation();
- delegate.println(b);
- }
-
- @Override
- public void println(char c) throws IOException {
- runFilterIfFirstInvocation();
- delegate.println(c);
- }
-
- @Override
- public void println(int i) throws IOException {
- runFilterIfFirstInvocation();
- delegate.println(i);
- }
-
- @Override
- public void println(long l) throws IOException {
- runFilterIfFirstInvocation();
- delegate.println(l);
- }
-
- @Override
- public void println(float f) throws IOException {
- runFilterIfFirstInvocation();
- delegate.println(f);
- }
-
- @Override
- public void println(double d) throws IOException {
- runFilterIfFirstInvocation();
- delegate.println(d);
- }
-
- @Override
- public String toString() {
- return getClass().getCanonicalName() + " (" + delegate.toString() + ")";
- }
-}
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterResolver.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterResolver.java
index 873f336f0c9..32def124131 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterResolver.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterResolver.java
@@ -10,7 +10,6 @@ import com.yahoo.jdisc.handler.ResponseHandler;
import com.yahoo.jdisc.http.HttpRequest;
import com.yahoo.jdisc.http.filter.RequestFilter;
import com.yahoo.jdisc.http.filter.ResponseFilter;
-import com.yahoo.jdisc.http.servlet.ServletRequest;
import org.eclipse.jetty.server.Request;
import java.net.URI;
@@ -40,13 +39,13 @@ class FilterResolver {
Optional<String> maybeFilterId = bindings.resolveRequestFilter(jdiscUri, getConnector(request).listenPort());
if (maybeFilterId.isPresent()) {
metric.add(MetricDefinitions.FILTERING_REQUEST_HANDLED, 1L, createMetricContext(request, maybeFilterId.get()));
- request.setAttribute(ServletRequest.JDISC_REQUEST_CHAIN, maybeFilterId.get());
+ request.setAttribute(RequestUtils.JDISC_REQUEST_CHAIN, maybeFilterId.get());
} else if (!strictFiltering) {
metric.add(MetricDefinitions.FILTERING_REQUEST_UNHANDLED, 1L, createMetricContext(request, null));
} else {
String syntheticFilterId = RejectingRequestFilter.SYNTHETIC_FILTER_CHAIN_ID;
metric.add(MetricDefinitions.FILTERING_REQUEST_HANDLED, 1L, createMetricContext(request, syntheticFilterId));
- request.setAttribute(ServletRequest.JDISC_REQUEST_CHAIN, syntheticFilterId);
+ request.setAttribute(RequestUtils.JDISC_REQUEST_CHAIN, syntheticFilterId);
return Optional.of(RejectingRequestFilter.INSTANCE);
}
return maybeFilterId.map(bindings::getRequestFilter);
@@ -56,7 +55,7 @@ class FilterResolver {
Optional<String> maybeFilterId = bindings.resolveResponseFilter(jdiscUri, getConnector(request).listenPort());
if (maybeFilterId.isPresent()) {
metric.add(MetricDefinitions.FILTERING_RESPONSE_HANDLED, 1L, createMetricContext(request, maybeFilterId.get()));
- request.setAttribute(ServletRequest.JDISC_RESPONSE_CHAIN, maybeFilterId.get());
+ request.setAttribute(RequestUtils.JDISC_RESPONSE_CHAIN, maybeFilterId.get());
} else {
metric.add(MetricDefinitions.FILTERING_RESPONSE_UNHANDLED, 1L, createMetricContext(request, null));
}
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactory.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactory.java
index 52c2a83563e..c54fa1cf1b9 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactory.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactory.java
@@ -2,7 +2,6 @@
package com.yahoo.jdisc.http.server.jetty;
import com.yahoo.jdisc.http.HttpRequest;
-import com.yahoo.jdisc.http.servlet.ServletRequest;
import com.yahoo.jdisc.service.CurrentContainer;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.Utf8Appendable;
@@ -32,7 +31,7 @@ class HttpRequestFactory {
HttpRequest.Version.fromString(servletRequest.getProtocol()),
new InetSocketAddress(servletRequest.getRemoteAddr(), servletRequest.getRemotePort()),
getConnection((Request) servletRequest).getCreatedTimeStamp());
- httpRequest.context().put(ServletRequest.JDISC_REQUEST_X509CERT, getCertChain(servletRequest));
+ httpRequest.context().put(RequestUtils.JDISC_REQUEST_X509CERT, getCertChain(servletRequest));
servletRequest.setAttribute(HttpRequest.class.getName(), httpRequest);
return httpRequest;
} catch (Utf8Appendable.NotUtf8Exception e) {
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscFilterInvokerFilter.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscFilterInvokerFilter.java
deleted file mode 100644
index 0fd4e8c42fb..00000000000
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscFilterInvokerFilter.java
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-import com.yahoo.container.logging.AccessLogEntry;
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.filter.RequestFilter;
-import org.eclipse.jetty.server.Request;
-
-import javax.servlet.AsyncContext;
-import javax.servlet.AsyncListener;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.URI;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static com.yahoo.jdisc.http.server.jetty.RequestUtils.getConnector;
-import static com.yahoo.yolean.Exceptions.throwUnchecked;
-
-/**
- * Runs JDisc security filters for Servlets
- * This component is split in two:
- * 1) JDiscFilterInvokerFilter, which uses package private methods to support JDisc APIs
- * 2) SecurityFilterInvoker, which is intended for use in a servlet context.
- *
- * @author Tony Vaagenes
- */
-class JDiscFilterInvokerFilter implements Filter {
- private final JDiscContext jDiscContext;
- private final FilterInvoker filterInvoker;
-
- public JDiscFilterInvokerFilter(JDiscContext jDiscContext,
- FilterInvoker filterInvoker) {
- this.jDiscContext = jDiscContext;
- this.filterInvoker = filterInvoker;
- }
-
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {}
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- HttpServletRequest httpRequest = (HttpServletRequest)request;
- HttpServletResponse httpResponse = (HttpServletResponse)response;
-
- URI uri;
- try {
- uri = HttpRequestFactory.getUri(httpRequest);
- } catch (RequestException e) {
- httpResponse.sendError(e.getResponseStatus(), e.getMessage());
- return;
- }
-
- AtomicReference<Boolean> responseReturned = new AtomicReference<>(null);
-
- HttpServletRequest newRequest = runRequestFilterWithMatchingBinding(responseReturned, uri, httpRequest, httpResponse);
- assert newRequest != null;
- responseReturned.compareAndSet(null, false);
-
- if (!responseReturned.get()) {
- runChainAndResponseFilters(uri, newRequest, httpResponse, chain);
- }
- }
-
- private void runChainAndResponseFilters(URI uri, HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
- Optional<OneTimeRunnable> responseFilterInvoker =
- jDiscContext.filterResolver.resolveResponseFilter(toJettyRequest(request), uri)
- .map(responseFilter ->
- new OneTimeRunnable(() ->
- filterInvoker.invokeResponseFilterChain(responseFilter, uri, request, response)));
-
-
- HttpServletResponse responseForServlet = responseFilterInvoker
- .<HttpServletResponse>map(invoker ->
- new FilterInvokingResponseWrapper(response, invoker))
- .orElse(response);
-
- HttpServletRequest requestForServlet = responseFilterInvoker
- .<HttpServletRequest>map(invoker ->
- new FilterInvokingRequestWrapper(request, invoker, responseForServlet))
- .orElse(request);
-
- chain.doFilter(requestForServlet, responseForServlet);
-
- responseFilterInvoker.ifPresent(invoker -> {
- boolean requestHandledSynchronously = !request.isAsyncStarted();
-
- if (requestHandledSynchronously) {
- invoker.runIfFirstInvocation();
- }
- // For async requests, response filters will be invoked on AsyncContext.complete().
- });
- }
-
- private HttpServletRequest runRequestFilterWithMatchingBinding(AtomicReference<Boolean> responseReturned, URI uri, HttpServletRequest request, HttpServletResponse response) throws IOException {
- try {
- RequestFilter requestFilter = jDiscContext.filterResolver.resolveRequestFilter(toJettyRequest(request), uri).orElse(null);
- if (requestFilter == null)
- return request;
-
- ResponseHandler responseHandler = createResponseHandler(responseReturned, request, response);
- return filterInvoker.invokeRequestFilterChain(requestFilter, uri, request, responseHandler);
- } catch (Exception e) {
- throw new RuntimeException("Failed running request filter chain for uri " + uri, e);
- }
- }
-
- private ResponseHandler createResponseHandler(AtomicReference<Boolean> responseReturned, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
- return jdiscResponse -> {
- boolean oldValueWasNull = responseReturned.compareAndSet(null, true);
- if (!oldValueWasNull)
- throw new RuntimeException("Can't return response from filter asynchronously");
-
- HttpRequestDispatch requestDispatch = createRequestDispatch(httpRequest, httpResponse);
- return requestDispatch.dispatchFilterRequest(jdiscResponse);
- };
- }
-
- private HttpRequestDispatch createRequestDispatch(HttpServletRequest request, HttpServletResponse response) {
- try {
- final AccessLogEntry accessLogEntry = null; // Not used in this context.
- return new HttpRequestDispatch(jDiscContext,
- accessLogEntry,
- getConnector(toJettyRequest(request)).createRequestMetricContext(request, Map.of()),
- request, response);
- } catch (IOException e) {
- throw throwUnchecked(e);
- }
- }
-
- private static Request toJettyRequest(HttpServletRequest request) {
- if (request instanceof com.yahoo.jdisc.http.servlet.ServletRequest) {
- return (Request) ((com.yahoo.jdisc.http.servlet.ServletRequest)request).getRequest();
- }
- return (Request) request;
- }
-
- @Override
- public void destroy() {}
-
- // ServletRequest wrapper that is necessary because we need to wrap AsyncContext.
- private static class FilterInvokingRequestWrapper extends HttpServletRequestWrapper {
- private final OneTimeRunnable filterInvoker;
- private final HttpServletResponse servletResponse;
-
- public FilterInvokingRequestWrapper(
- HttpServletRequest request,
- OneTimeRunnable filterInvoker,
- HttpServletResponse servletResponse) {
- super(request);
- this.filterInvoker = filterInvoker;
- this.servletResponse = servletResponse;
- }
-
- @Override
- public AsyncContext startAsync() {
- final AsyncContext asyncContext = super.startAsync();
- return new FilterInvokingAsyncContext(asyncContext, filterInvoker, this, servletResponse);
- }
-
- @Override
- public AsyncContext startAsync(
- final ServletRequest wrappedRequest,
- final ServletResponse wrappedResponse) {
- // According to the documentation, the passed request/response parameters here must either
- // _be_ or _wrap_ the original request/response objects passed to the servlet - which are
- // our wrappers, so no need to wrap again - we can use the user-supplied objects.
- final AsyncContext asyncContext = super.startAsync(wrappedRequest, wrappedResponse);
- return new FilterInvokingAsyncContext(asyncContext, filterInvoker, this, wrappedResponse);
- }
-
- @Override
- public AsyncContext getAsyncContext() {
- final AsyncContext asyncContext = super.getAsyncContext();
- return new FilterInvokingAsyncContext(asyncContext, filterInvoker, this, servletResponse);
- }
- }
-
- // AsyncContext wrapper that is necessary for two reasons:
- // 1) Run response filters when AsyncContext.complete() is called.
- // 2) Eliminate paths where application code can get its hands on un-wrapped response object, circumventing
- // running of response filters.
- private static class FilterInvokingAsyncContext implements AsyncContext {
- private final AsyncContext delegate;
- private final OneTimeRunnable filterInvoker;
- private final ServletRequest servletRequest;
- private final ServletResponse servletResponse;
-
- public FilterInvokingAsyncContext(
- AsyncContext delegate,
- OneTimeRunnable filterInvoker,
- ServletRequest servletRequest,
- ServletResponse servletResponse) {
- this.delegate = delegate;
- this.filterInvoker = filterInvoker;
- this.servletRequest = servletRequest;
- this.servletResponse = servletResponse;
- }
-
- @Override
- public ServletRequest getRequest() {
- return servletRequest;
- }
-
- @Override
- public ServletResponse getResponse() {
- return servletResponse;
- }
-
- @Override
- public boolean hasOriginalRequestAndResponse() {
- return delegate.hasOriginalRequestAndResponse();
- }
-
- @Override
- public void dispatch() {
- delegate.dispatch();
- }
-
- @Override
- public void dispatch(String s) {
- delegate.dispatch(s);
- }
-
- @Override
- public void dispatch(ServletContext servletContext, String s) {
- delegate.dispatch(servletContext, s);
- }
-
- @Override
- public void complete() {
- // Completing may commit the response, so this is the last chance to run response filters.
- filterInvoker.runIfFirstInvocation();
- delegate.complete();
- }
-
- @Override
- public void start(Runnable runnable) {
- delegate.start(runnable);
- }
-
- @Override
- public void addListener(AsyncListener asyncListener) {
- delegate.addListener(asyncListener);
- }
-
- @Override
- public void addListener(AsyncListener asyncListener, ServletRequest servletRequest, ServletResponse servletResponse) {
- delegate.addListener(asyncListener, servletRequest, servletResponse);
- }
-
- @Override
- public <T extends AsyncListener> T createListener(Class<T> aClass) throws ServletException {
- return delegate.createListener(aClass);
- }
-
- @Override
- public void setTimeout(long l) {
- delegate.setTimeout(l);
- }
-
- @Override
- public long getTimeout() {
- return delegate.getTimeout();
- }
- }
-
- private static class FilterInvokingResponseWrapper extends HttpServletResponseWrapper {
- private final OneTimeRunnable filterInvoker;
-
- public FilterInvokingResponseWrapper(HttpServletResponse response, OneTimeRunnable filterInvoker) {
- super(response);
- this.filterInvoker = filterInvoker;
- }
-
- @Override
- public ServletOutputStream getOutputStream() throws IOException {
- ServletOutputStream delegate = super.getOutputStream();
- return new FilterInvokingServletOutputStream(delegate, filterInvoker);
- }
-
- @Override
- public PrintWriter getWriter() throws IOException {
- PrintWriter delegate = super.getWriter();
- return new FilterInvokingPrintWriter(delegate, filterInvoker);
- }
- }
-}
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
index 0e511fd3eaf..79cdb8f67cf 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
@@ -73,7 +73,7 @@ class JDiscServerConnector extends ServerConnector {
public Metric.Context createRequestMetricContext(HttpServletRequest request, Map<String, String> extraDimensions) {
String method = request.getMethod();
String scheme = request.getScheme();
- boolean clientAuthenticated = request.getAttribute(com.yahoo.jdisc.http.servlet.ServletRequest.SERVLET_REQUEST_X509CERT) != null;
+ boolean clientAuthenticated = request.getAttribute(RequestUtils.SERVLET_REQUEST_X509CERT) != null;
Map<String, Object> dimensions = createConnectorDimensions(listenPort, connectorName);
dimensions.put(MetricDefinitions.METHOD_DIMENSION, method);
dimensions.put(MetricDefinitions.SCHEME_DIMENSION, scheme);
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
index 3f2a91c60b5..fca34f3bbd7 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
@@ -2,14 +2,12 @@
package com.yahoo.jdisc.http.server.jetty;
import com.google.inject.Inject;
-import com.yahoo.component.ComponentId;
import com.yahoo.component.provider.ComponentRegistry;
import com.yahoo.container.logging.ConnectionLog;
import com.yahoo.container.logging.RequestLog;
import com.yahoo.jdisc.Metric;
import com.yahoo.jdisc.http.ConnectorConfig;
import com.yahoo.jdisc.http.ServerConfig;
-import com.yahoo.jdisc.http.ServletPathsConfig;
import com.yahoo.jdisc.service.AbstractServerProvider;
import com.yahoo.jdisc.service.CurrentContainer;
import org.eclipse.jetty.http.HttpField;
@@ -24,7 +22,6 @@ import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.server.handler.gzip.GzipHttpOutputInterceptor;
-import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.log.JavaUtilLog;
@@ -32,14 +29,12 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import javax.management.remote.JMXServiceURL;
-import javax.servlet.DispatcherType;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.BindException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.EnumSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -63,12 +58,9 @@ public class JettyHttpServer extends AbstractServerProvider {
public JettyHttpServer(CurrentContainer container,
Metric metric,
ServerConfig serverConfig,
- ServletPathsConfig servletPathsConfig,
FilterBindings filterBindings,
Janitor janitor,
ComponentRegistry<ConnectorFactory> connectorFactories,
- ComponentRegistry<ServletHolder> servletHolders,
- FilterInvoker filterInvoker,
RequestLog requestLog,
ConnectionLog connectionLog) {
super(container);
@@ -98,18 +90,13 @@ public class JettyHttpServer extends AbstractServerProvider {
serverConfig);
ServletHolder jdiscServlet = new ServletHolder(new JDiscHttpServlet(jDiscContext));
- FilterHolder jDiscFilterInvokerFilter = new FilterHolder(new JDiscFilterInvokerFilter(jDiscContext, filterInvoker));
-
List<JDiscServerConnector> connectors = Arrays.stream(server.getConnectors())
.map(JDiscServerConnector.class::cast)
.collect(toList());
server.setHandler(getHandlerCollection(serverConfig,
- servletPathsConfig,
connectors,
- jdiscServlet,
- servletHolders,
- jDiscFilterInvokerFilter));
+ jdiscServlet));
this.metricsReporter = new ServerMetricReporter(metric, server);
}
@@ -150,19 +137,9 @@ public class JettyHttpServer extends AbstractServerProvider {
}
private HandlerCollection getHandlerCollection(ServerConfig serverConfig,
- ServletPathsConfig servletPathsConfig,
List<JDiscServerConnector> connectors,
- ServletHolder jdiscServlet,
- ComponentRegistry<ServletHolder> servletHolders,
- FilterHolder jDiscFilterInvokerFilter) {
+ ServletHolder jdiscServlet) {
ServletContextHandler servletContextHandler = createServletContextHandler();
-
- servletHolders.allComponentsById().forEach((id, servlet) -> {
- String path = getServletPath(servletPathsConfig, id);
- servletContextHandler.addServlet(servlet, path);
- servletContextHandler.addFilter(jDiscFilterInvokerFilter, path, EnumSet.allOf(DispatcherType.class));
- });
-
servletContextHandler.addServlet(jdiscServlet, "/*");
List<ConnectorConfig> connectorConfigs = connectors.stream().map(JDiscServerConnector::connectorConfig).collect(toList());
@@ -191,10 +168,6 @@ public class JettyHttpServer extends AbstractServerProvider {
return handlerCollection;
}
- private static String getServletPath(ServletPathsConfig servletPathsConfig, ComponentId id) {
- return "/" + servletPathsConfig.servlets(id.stringValue()).path();
- }
-
private ServletContextHandler createServletContextHandler() {
ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SECURITY | ServletContextHandler.NO_SESSIONS);
servletContextHandler.setContextPath("/");
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/OneTimeRunnable.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/OneTimeRunnable.java
deleted file mode 100644
index 24cc41d009f..00000000000
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/OneTimeRunnable.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * @author Tony Vaagenes
- */
-public class OneTimeRunnable {
- private final Runnable runnable;
- private final AtomicBoolean hasRun = new AtomicBoolean(false);
-
- public OneTimeRunnable(Runnable runnable) {
- this.runnable = runnable;
- }
-
- public void runIfFirstInvocation() {
- boolean previous = hasRun.getAndSet(true);
- if (!previous) {
- runnable.run();
- }
- }
-}
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestUtils.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestUtils.java
index 1bddd491496..ae18c78a7d3 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestUtils.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestUtils.java
@@ -12,6 +12,11 @@ import javax.servlet.http.HttpServletRequest;
* @author bjorncs
*/
public class RequestUtils {
+ public static final String JDISC_REQUEST_X509CERT = "jdisc.request.X509Certificate";
+ public static final String JDISC_REQUEST_CHAIN = "jdisc.request.chain";
+ public static final String JDISC_RESPONSE_CHAIN = "jdisc.response.chain";
+ public static final String SERVLET_REQUEST_X509CERT = "javax.servlet.request.X509Certificate";
+
private RequestUtils() {}
public static Connection getConnection(Request request) {
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/TlsClientAuthenticationEnforcer.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/TlsClientAuthenticationEnforcer.java
index b9293226528..3059f972ce9 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/TlsClientAuthenticationEnforcer.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/TlsClientAuthenticationEnforcer.java
@@ -3,7 +3,6 @@ package com.yahoo.jdisc.http.server.jetty;
import com.yahoo.jdisc.Response;
import com.yahoo.jdisc.http.ConnectorConfig;
-import com.yahoo.jdisc.http.servlet.ServletRequest;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;
@@ -78,6 +77,6 @@ class TlsClientAuthenticationEnforcer extends HandlerWrapper {
}
private boolean isClientAuthenticated(HttpServletRequest servletRequest) {
- return servletRequest.getAttribute(ServletRequest.SERVLET_REQUEST_X509CERT) != null;
+ return servletRequest.getAttribute(RequestUtils.SERVLET_REQUEST_X509CERT) != null;
}
}
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/UnsupportedFilterInvoker.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/UnsupportedFilterInvoker.java
deleted file mode 100644
index 8d878b64e6f..00000000000
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/UnsupportedFilterInvoker.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.filter.RequestFilter;
-import com.yahoo.jdisc.http.filter.ResponseFilter;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import java.net.URI;
-
-/**
- * @author Tony Vaagenes
- */
-public class UnsupportedFilterInvoker implements FilterInvoker {
- @Override
- public HttpServletRequest invokeRequestFilterChain(RequestFilter requestFilterChain,
- URI uri,
- HttpServletRequest httpRequest,
- ResponseHandler responseHandler) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void invokeResponseFilterChain(
- ResponseFilter responseFilterChain,
- URI uri,
- HttpServletRequest request,
- HttpServletResponse response) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/testutils/ServletModule.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/testutils/ServletModule.java
deleted file mode 100644
index bb69832d767..00000000000
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/testutils/ServletModule.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty.testutils;
-
-import com.google.inject.Binder;
-import com.google.inject.Module;
-import com.google.inject.Provides;
-import com.yahoo.component.provider.ComponentRegistry;
-
-import org.eclipse.jetty.servlet.ServletHolder;
-
-/**
- * @author Tony Vaagenes
- */
-public class ServletModule implements Module {
-
- @SuppressWarnings("unused")
- @Provides
- public ComponentRegistry<ServletHolder> servletHolderComponentRegistry() {
- return new ComponentRegistry<>();
- }
-
- @Override public void configure(Binder binder) { }
-}
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/testutils/TestDriver.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/testutils/TestDriver.java
index 99c49527ea5..b0c1e7763ca 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/testutils/TestDriver.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/testutils/TestDriver.java
@@ -92,8 +92,7 @@ public class TestDriver implements AutoCloseable {
bind(RequestLog.class).toInstance(new VoidRequestLog());
}
},
- new ConnectorFactoryRegistryModule(connectorConfig),
- new ServletModule());
+ new ConnectorFactoryRegistryModule(connectorConfig));
}
public static class Builder {