aboutsummaryrefslogtreecommitdiffstats
path: root/jdisc_http_service/src/main/java/com/yahoo/jdisc
diff options
context:
space:
mode:
authorgjoranv <gv@verizonmedia.com>2021-03-23 21:21:39 +0100
committergjoranv <gv@verizonmedia.com>2021-03-23 23:13:01 +0100
commit5617a82f7a32ebcc37be226b27f6ff284f5c896d (patch)
tree45e8b3be33c372971c2b1349d245e223a1f46085 /jdisc_http_service/src/main/java/com/yahoo/jdisc
parent266046b2bb8bebbb683499f558a05aaf8a4f1ff3 (diff)
Remove the jdisc_http_service module.
- It has been merged into container-core.
Diffstat (limited to 'jdisc_http_service/src/main/java/com/yahoo/jdisc')
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/CertificateStore.java26
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/Cookie.java250
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpHeaders.java122
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpRequest.java342
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpResponse.java125
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/SecretStore.java23
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/cloud/package-info.java4
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterRequest.java543
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterResponse.java154
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/FilterConfig.java42
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JDiscCookieWrapper.java79
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JdiscFilterRequest.java133
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JdiscFilterResponse.java67
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestFilter.java14
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestFilterBase.java9
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestView.java45
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ResponseFilter.java14
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ResponseFilterBase.java9
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityFilterInvoker.java108
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityRequestFilter.java13
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityRequestFilterChain.java77
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityResponseFilter.java8
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityResponseFilterChain.java101
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ServletFilterRequest.java169
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ServletFilterResponse.java81
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/EmptyRequestFilter.java24
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/EmptyResponseFilter.java24
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/RequestFilterChain.java55
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/ResponseFilterChain.java54
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/ResponseHandlerGuard.java29
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/package-info.java5
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/package-info.java7
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/package-info.java7
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java167
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLoggingRequestHandler.java59
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AsyncCompleteListener.java22
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/CompletionHandlerUtils.java14
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/CompletionHandlers.java57
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectionThrottler.java274
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java140
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ErrorResponseContentCreator.java41
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ExceptionWrapper.java59
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterBindings.java102
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvoker.java28
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingPrintWriter.java266
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingServletOutputStream.java165
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterResolver.java88
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilteringRequestHandler.java134
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FormPostRequestHandler.java188
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HealthCheckProxyHandler.java274
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java243
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactory.java87
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpResponseStatisticsCollector.java300
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpServletRequestUtils.java38
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscContext.java33
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscFilterInvokerFilter.java294
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java148
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java104
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java373
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java298
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/MetricDefinitions.java79
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/OneTimeRunnable.java23
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ReferenceCountingRequestHandler.java257
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestException.java39
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestMetricReporter.java85
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SecuredRedirectHandler.java58
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServerMetricReporter.java115
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletOutputStreamWriter.java299
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletRequestReader.java270
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletResponseController.java251
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailedListener.java52
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailure.java61
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/TlsClientAuthenticationEnforcer.java83
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/UnsupportedFilterInvoker.java32
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/VoidConnectionLog.java16
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/VoidRequestLog.java14
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/package-info.java3
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletOrJdiscHttpRequest.java40
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletOrJdiscHttpResponse.java23
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletRequest.java272
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletResponse.java66
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/package-info.java5
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslContextFactoryProvider.java21
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/ConfiguredSslContextFactoryProvider.java138
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/DefaultSslContextFactoryProvider.java79
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/JDiscSslContextFactory.java37
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/SslContextFactoryUtils.java32
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/TlsContextBasedProvider.java42
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/package-info.java8
-rw-r--r--jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/package-info.java10
90 files changed, 0 insertions, 9269 deletions
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/CertificateStore.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/CertificateStore.java
deleted file mode 100644
index 3a63726b951..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/CertificateStore.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http;
-
-/**
- * A store of certificates. An implementation can be plugged in to provide certificates to components who use it.
- *
- * @author bratseth
- */
-public interface CertificateStore {
-
- /** Returns a certificate for a given appid, using the default TTL and retry time */
- default String getCertificate(String appid) { return getCertificate(appid, 0L, 0L); }
-
- /** Returns a certificate for a given appid, using a TTL and default retry time */
- default String getCertificate(String appid, long ttl) { return getCertificate(appid, ttl, 0L); }
-
- /**
- * Returns a certificate for a given appid, using a TTL and default retry time
- *
- * @param ttl certificate TTL in ms. Use the default TTL if set to 0
- * @param retry if no certificate is found, allow access to cert DB again in
- * "retry" ms. Use the default retry time if set to 0.
- */
- String getCertificate(String appid, long ttl, long retry);
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/Cookie.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/Cookie.java
deleted file mode 100644
index d882cf7a34a..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/Cookie.java
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http;
-
-import org.eclipse.jetty.http.HttpCookie;
-import org.eclipse.jetty.server.CookieCutter;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-
-import static java.util.stream.Collectors.toList;
-
-/**
- * A RFC 6265 compliant cookie.
- *
- * Note: RFC 2109 and RFC 2965 is no longer supported. All fields that are not part of RFC 6265 are deprecated.
- *
- * @author Einar M R Rosenvinge
- * @author bjorncs
- */
-public class Cookie {
-
- private final Set<Integer> ports = new HashSet<>();
- private String name;
- private String value;
- private String domain;
- private String path;
- private SameSite sameSite;
- private long maxAgeSeconds = Integer.MIN_VALUE;
- private boolean secure;
- private boolean httpOnly;
- private boolean discard;
-
- public Cookie() {
- }
-
- public Cookie(Cookie cookie) {
- ports.addAll(cookie.ports);
- name = cookie.name;
- value = cookie.value;
- domain = cookie.domain;
- path = cookie.path;
- sameSite = cookie.sameSite;
- maxAgeSeconds = cookie.maxAgeSeconds;
- secure = cookie.secure;
- httpOnly = cookie.httpOnly;
- discard = cookie.discard;
- }
-
- public Cookie(String name, String value) {
- this.name = name;
- this.value = value;
- }
-
- public String getName() {
- return name;
- }
-
- public Cookie setName(String name) {
- this.name = name;
- return this;
- }
-
- public String getValue() {
- return value;
- }
-
- public Cookie setValue(String value) {
- this.value = value;
- return this;
- }
-
- public String getDomain() {
- return domain;
- }
-
- public Cookie setDomain(String domain) {
- this.domain = domain;
- return this;
- }
-
- public String getPath() {
- return path;
- }
-
- public Cookie setPath(String path) {
- this.path = path;
- return this;
- }
-
- public SameSite getSameSite() {
- return sameSite;
- }
-
- public Cookie setSameSite(SameSite sameSite) {
- this.sameSite = sameSite;
- return this;
- }
-
- public int getMaxAge(TimeUnit unit) {
- return (int)unit.convert(maxAgeSeconds, TimeUnit.SECONDS);
- }
-
- public Cookie setMaxAge(int maxAge, TimeUnit unit) {
- this.maxAgeSeconds = maxAge >= 0 ? unit.toSeconds(maxAge) : Integer.MIN_VALUE;
- return this;
- }
-
- public boolean isSecure() {
- return secure;
- }
-
- public Cookie setSecure(boolean secure) {
- this.secure = secure;
- return this;
- }
-
- public boolean isHttpOnly() {
- return httpOnly;
- }
-
- public Cookie setHttpOnly(boolean httpOnly) {
- this.httpOnly = httpOnly;
- return this;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- Cookie cookie = (Cookie) o;
- return maxAgeSeconds == cookie.maxAgeSeconds &&
- secure == cookie.secure &&
- httpOnly == cookie.httpOnly &&
- discard == cookie.discard &&
- sameSite == cookie.sameSite &&
- Objects.equals(ports, cookie.ports) &&
- Objects.equals(name, cookie.name) &&
- Objects.equals(value, cookie.value) &&
- Objects.equals(domain, cookie.domain) &&
- Objects.equals(path, cookie.path);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(ports, name, value, domain, path, sameSite, maxAgeSeconds, secure, httpOnly, discard);
- }
-
- @Override
- public String toString() {
- StringBuilder ret = new StringBuilder();
- ret.append(name).append("=").append(value);
- return ret.toString();
- }
- // NOTE cookie encoding and decoding:
- // The implementation uses Jetty for server-side (encoding of Set-Cookie and decoding of Cookie header),
- // and java.net.HttpCookie for client-side (encoding of Cookie and decoding of Set-Cookie header).
- //
- // Implementation is RFC-6265 compliant.
-
- public static String toCookieHeader(Iterable<? extends Cookie> cookies) {
- return StreamSupport.stream(cookies.spliterator(), false)
- .map(cookie -> {
- java.net.HttpCookie httpCookie = new java.net.HttpCookie(cookie.getName(), cookie.getValue());
- httpCookie.setDomain(cookie.getDomain());
- httpCookie.setHttpOnly(cookie.isHttpOnly());
- httpCookie.setMaxAge(cookie.getMaxAge(TimeUnit.SECONDS));
- httpCookie.setPath(cookie.getPath());
- httpCookie.setSecure(cookie.isSecure());
- httpCookie.setVersion(0);
- return httpCookie.toString();
- })
- .collect(Collectors.joining(";"));
- }
-
- public static List<Cookie> fromCookieHeader(String headerVal) {
- CookieCutter cookieCutter = new CookieCutter();
- cookieCutter.addCookieField(headerVal);
- return Arrays.stream(cookieCutter.getCookies())
- .map(servletCookie -> {
- Cookie cookie = new Cookie();
- cookie.setName(servletCookie.getName());
- cookie.setValue(servletCookie.getValue());
- cookie.setPath(servletCookie.getPath());
- cookie.setDomain(servletCookie.getDomain());
- cookie.setMaxAge(servletCookie.getMaxAge(), TimeUnit.SECONDS);
- cookie.setSecure(servletCookie.getSecure());
- cookie.setHttpOnly(servletCookie.isHttpOnly());
- return cookie;
- })
- .collect(toList());
- }
-
- public static List<String> toSetCookieHeaders(Iterable<? extends Cookie> cookies) {
- return StreamSupport.stream(cookies.spliterator(), false)
- .map(cookie ->
- new org.eclipse.jetty.http.HttpCookie(
- cookie.getName(),
- cookie.getValue(),
- cookie.getDomain(),
- cookie.getPath(),
- cookie.getMaxAge(TimeUnit.SECONDS),
- cookie.isHttpOnly(),
- cookie.isSecure(),
- null, /* comment */
- 0, /* version */
- Optional.ofNullable(cookie.getSameSite()).map(SameSite::jettySameSite).orElse(null)
- ).getRFC6265SetCookie())
- .collect(toList());
- }
-
- @Deprecated // TODO Vespa 8 Remove
- public static List<String> toSetCookieHeaderAll(Iterable<? extends Cookie> cookies) {
- return toSetCookieHeaders(cookies);
- }
-
- public static Cookie fromSetCookieHeader(String headerVal) {
- return java.net.HttpCookie.parse(headerVal).stream()
- .map(httpCookie -> {
- Cookie cookie = new Cookie();
- cookie.setName(httpCookie.getName());
- cookie.setValue(httpCookie.getValue());
- cookie.setDomain(httpCookie.getDomain());
- cookie.setHttpOnly(httpCookie.isHttpOnly());
- cookie.setMaxAge((int) httpCookie.getMaxAge(), TimeUnit.SECONDS);
- cookie.setPath(httpCookie.getPath());
- cookie.setSecure(httpCookie.getSecure());
- return cookie;
- })
- .findFirst().get();
- }
-
- public enum SameSite {
- NONE, STRICT, LAX;
-
- HttpCookie.SameSite jettySameSite() {
- return HttpCookie.SameSite.valueOf(name());
- }
-
- static SameSite fromJettySameSite(HttpCookie.SameSite jettySameSite) {
- return valueOf(jettySameSite.name());
- }
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpHeaders.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpHeaders.java
deleted file mode 100644
index 039966133e8..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpHeaders.java
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http;
-
-/**
- * @author Anirudha Khanna
- */
-@SuppressWarnings("UnusedDeclaration")
-public class HttpHeaders {
-
- public static final class Names {
-
- public static final String ACCEPT = "Accept";
- public static final String ACCEPT_CHARSET = "Accept-Charset";
- public static final String ACCEPT_ENCODING = "Accept-Encoding";
- public static final String ACCEPT_LANGUAGE = "Accept-Language";
- public static final String ACCEPT_RANGES = "Accept-Ranges";
- public static final String ACCEPT_PATCH = "Accept-Patch";
- public static final String AGE = "Age";
- public static final String ALLOW = "Allow";
- public static final String AUTHORIZATION = "Authorization";
- public static final String CACHE_CONTROL = "Cache-Control";
- public static final String CONNECTION = "Connection";
- public static final String CONTENT_BASE = "Content-Base";
- public static final String CONTENT_ENCODING = "Content-Encoding";
- public static final String CONTENT_LANGUAGE = "Content-Language";
- public static final String CONTENT_LENGTH = "Content-Length";
- public static final String CONTENT_LOCATION = "Content-Location";
- public static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
- public static final String CONTENT_MD5 = "Content-MD5";
- public static final String CONTENT_RANGE = "Content-Range";
- public static final String CONTENT_TYPE = "Content-Type";
- public static final String COOKIE = "Cookie";
- public static final String DATE = "Date";
- public static final String ETAG = "ETag";
- public static final String EXPECT = "Expect";
- public static final String EXPIRES = "Expires";
- public static final String FROM = "From";
- public static final String HOST = "Host";
- public static final String IF_MATCH = "If-Match";
- public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
- public static final String IF_NONE_MATCH = "If-None-Match";
- public static final String IF_RANGE = "If-Range";
- public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
- public static final String LAST_MODIFIED = "Last-Modified";
- public static final String LOCATION = "Location";
- public static final String MAX_FORWARDS = "Max-Forwards";
- public static final String ORIGIN = "Origin";
- public static final String PRAGMA = "Pragma";
- public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
- public static final String PROXY_AUTHORIZATION = "Proxy-Authorization";
- public static final String RANGE = "Range";
- public static final String REFERER = "Referer";
- public static final String RETRY_AFTER = "Retry-After";
- public static final String SEC_WEBSOCKET_KEY1 = "Sec-WebSocket-Key1";
- public static final String SEC_WEBSOCKET_KEY2 = "Sec-WebSocket-Key2";
- public static final String SEC_WEBSOCKET_LOCATION = "Sec-WebSocket-Location";
- public static final String SEC_WEBSOCKET_ORIGIN = "Sec-WebSocket-Origin";
- public static final String SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol";
- public static final String SEC_WEBSOCKET_VERSION = "Sec-WebSocket-Version";
- public static final String SEC_WEBSOCKET_KEY = "Sec-WebSocket-Key";
- public static final String SEC_WEBSOCKET_ACCEPT = "Sec-WebSocket-Accept";
- public static final String SERVER = "Server";
- public static final String SET_COOKIE = "Set-Cookie";
- public static final String SET_COOKIE2 = "Set-Cookie2";
- public static final String TE = "TE";
- public static final String TRAILER = "Trailer";
- public static final String TRANSFER_ENCODING = "Transfer-Encoding";
- public static final String UPGRADE = "Upgrade";
- public static final String USER_AGENT = "User-Agent";
- public static final String VARY = "Vary";
- public static final String VIA = "Via";
- public static final String WARNING = "Warning";
- public static final String WEBSOCKET_LOCATION = "WebSocket-Location";
- public static final String WEBSOCKET_ORIGIN = "WebSocket-Origin";
- public static final String WEBSOCKET_PROTOCOL = "WebSocket-Protocol";
- public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
- public static final String X_DISABLE_CHUNKING = "X-JDisc-Disable-Chunking";
- public static final String X_YAHOO_SERVING_HOST = "X-Yahoo-Serving-Host";
-
- private Names() {
- // hide
- }
- }
-
- public static final class Values {
-
- public static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
- public static final String BASE64 = "base64";
- public static final String BINARY = "binary";
- public static final String BYTES = "bytes";
- public static final String CHARSET = "charset";
- public static final String CHUNKED = "chunked";
- public static final String CLOSE = "close";
- public static final String COMPRESS = "compress";
- public static final String CONTINUE = "100-continue";
- public static final String DEFLATE = "deflate";
- public static final String GZIP = "gzip";
- public static final String IDENTITY = "identity";
- public static final String KEEP_ALIVE = "keep-alive";
- public static final String MAX_AGE = "max-age";
- public static final String MAX_STALE = "max-stale";
- public static final String MIN_FRESH = "min-fresh";
- public static final String MUST_REVALIDATE = "must-revalidate";
- public static final String NO_CACHE = "no-cache";
- public static final String NO_STORE = "no-store";
- public static final String NO_TRANSFORM = "no-transform";
- public static final String NONE = "none";
- public static final String ONLY_IF_CACHED = "only-if-cached";
- public static final String PRIVATE = "private";
- public static final String PROXY_REVALIDATE = "proxy-revalidate";
- public static final String PUBLIC = "public";
- public static final String QUOTED_PRINTABLE = "quoted-printable";
- public static final String S_MAXAGE = "s-maxage";
- public static final String TRAILERS = "trailers";
- public static final String UPGRADE = "Upgrade";
- public static final String WEBSOCKET = "WebSocket";
-
- private Values() {
- // hide
- }
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpRequest.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpRequest.java
deleted file mode 100644
index 118c34245c0..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpRequest.java
+++ /dev/null
@@ -1,342 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http;
-
-import com.yahoo.jdisc.HeaderFields;
-import com.yahoo.jdisc.Request;
-import com.yahoo.jdisc.handler.CompletionHandler;
-import com.yahoo.jdisc.handler.ContentChannel;
-import com.yahoo.jdisc.handler.RequestHandler;
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.servlet.ServletOrJdiscHttpRequest;
-import com.yahoo.jdisc.service.CurrentContainer;
-import org.eclipse.jetty.http.HttpURI;
-import org.eclipse.jetty.util.MultiMap;
-
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.net.URI;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A HTTP request.
- *
- * @author Anirudha Khanna
- * @author Einar M R Rosenvinge
- */
-public class HttpRequest extends Request implements ServletOrJdiscHttpRequest {
-
- public enum Method {
- OPTIONS,
- GET,
- HEAD,
- POST,
- PUT,
- PATCH,
- DELETE,
- TRACE,
- CONNECT
- }
-
- public enum Version {
- HTTP_1_0("HTTP/1.0"),
- HTTP_1_1("HTTP/1.1");
-
- private final String str;
-
- private Version(String str) {
- this.str = str;
- }
-
- @Override
- public String toString() {
- return str;
- }
-
- public static Version fromString(String str) {
- for (Version version : values()) {
- if (version.str.equals(str)) {
- return version;
- }
- }
- throw new IllegalArgumentException(str);
- }
- }
-
- private final HeaderFields trailers = new HeaderFields();
- private final Map<String, List<String>> parameters = new HashMap<>();
- private Principal principal;
- private final long connectedAt;
- private Method method;
- private Version version;
- private SocketAddress remoteAddress;
- private URI proxyServer;
- private Long connectionTimeout;
-
- protected HttpRequest(CurrentContainer container, URI uri, Method method, Version version,
- SocketAddress remoteAddress, Long connectedAtMillis)
- {
- super(container, uri);
- try {
- this.method = method;
- this.version = version;
- this.remoteAddress = remoteAddress;
- this.parameters.putAll(getUriQueryParameters(uri));
- if (connectedAtMillis != null) {
- this.connectedAt = connectedAtMillis;
- } else {
- this.connectedAt = creationTime(TimeUnit.MILLISECONDS);
- }
- } catch (RuntimeException e) {
- release();
- throw e;
- }
- }
-
- private HttpRequest(Request parent, URI uri, Method method, Version version) {
- super(parent, uri);
- try {
- this.method = method;
- this.version = version;
- this.remoteAddress = null;
- this.parameters.putAll(getUriQueryParameters(uri));
- this.connectedAt = creationTime(TimeUnit.MILLISECONDS);
- } catch (RuntimeException e) {
- release();
- throw e;
- }
- }
-
- private static Map<String, List<String>> getUriQueryParameters(URI uri) {
- MultiMap<String> queryParameters = new MultiMap<>();
- new HttpURI(uri).decodeQueryTo(queryParameters);
-
- // Do a deep copy so we do not leak Jetty classes outside
- Map<String, List<String>> deepCopiedQueryParameters = new HashMap<>();
- for (Map.Entry<String, List<String>> entry : queryParameters.entrySet()) {
- deepCopiedQueryParameters.put(entry.getKey(), new ArrayList<>(entry.getValue()));
- }
- return deepCopiedQueryParameters;
- }
-
- public Method getMethod() {
- return method;
- }
-
- public void setMethod(Method method) {
- this.method = method;
- }
-
- public Version getVersion() {
- return version;
- }
-
- /** Returns the remote address, or null if unresolved */
- @Override
- public String getRemoteHostAddress() {
- if (remoteAddress instanceof InetSocketAddress) {
- InetAddress remoteInetAddress = ((InetSocketAddress) remoteAddress).getAddress();
- if (remoteInetAddress == null)
- return null;
- return remoteInetAddress.getHostAddress();
- }
- else {
- throw new RuntimeException("Unknown SocketAddress class: " + remoteAddress.getClass().getName());
- }
- }
-
- @Override
- public String getRemoteHostName() {
- if (remoteAddress instanceof InetSocketAddress) {
- InetAddress remoteInetAddress = ((InetSocketAddress) remoteAddress).getAddress();
- if (remoteInetAddress == null) return null; // not resolved; we have no network
- return remoteInetAddress.getHostName();
- }
- else {
- throw new RuntimeException("Unknown SocketAddress class: " + remoteAddress.getClass().getName());
- }
- }
-
- @Override
- public int getRemotePort() {
- if (remoteAddress instanceof InetSocketAddress)
- return ((InetSocketAddress) remoteAddress).getPort();
- else
- throw new RuntimeException("Unknown SocketAddress class: " + remoteAddress.getClass().getName());
- }
-
- public void setVersion(Version version) {
- this.version = version;
- }
-
- public SocketAddress getRemoteAddress() {
- return remoteAddress;
- }
-
- public void setRemoteAddress(SocketAddress remoteAddress) {
- this.remoteAddress = remoteAddress;
- }
-
- public URI getProxyServer() {
- return proxyServer;
- }
-
- public void setProxyServer(URI proxyServer) {
- this.proxyServer = proxyServer;
- }
-
- /**
- * <p>For server requests, this returns the timestamp of when the underlying HTTP channel was connected.
- *
- * <p>For client requests, this returns the same value as {@link #creationTime(java.util.concurrent.TimeUnit)}.</p>
- *
- * @param unit the unit to return the time in
- * @return the timestamp of when the underlying HTTP channel was connected, or request creation time
- */
- @Override
- public long getConnectedAt(TimeUnit unit) {
- return unit.convert(connectedAt, TimeUnit.MILLISECONDS);
- }
-
- public Long getConnectionTimeout(TimeUnit unit) {
- if (connectionTimeout == null) {
- return null;
- }
- return unit.convert(connectionTimeout, TimeUnit.MILLISECONDS);
- }
-
- /**
- * <p>Sets the allocated time that this HttpRequest is allowed to spend trying to connect to a remote host. This has
- * no effect on an HttpRequest received by a {@link RequestHandler}. If no connection timeout is assigned to an
- * HttpRequest, it defaults the connection-timeout in the client configuration.</p>
- *
- * <p><b>NOTE:</b> Where {@link Request#setTimeout(long, TimeUnit)} sets the expiration time between calling a
- * RequestHandler and a {@link ResponseHandler}, this method sets the expiration time of the connect-operation as
- * performed by the client.</p>
- *
- * @param timeout The allocated amount of time.
- * @param unit The time unit of the <em>timeout</em> argument.
- */
- public void setConnectionTimeout(long timeout, TimeUnit unit) {
- this.connectionTimeout = unit.toMillis(timeout);
- }
-
- public Map<String, List<String>> parameters() {
- return parameters;
- }
-
- @Override
- public void copyHeaders(HeaderFields target) {
- target.addAll(headers());
- }
-
- public List<Cookie> decodeCookieHeader() {
- List<String> cookies = headers().get(HttpHeaders.Names.COOKIE);
- if (cookies == null) {
- return Collections.emptyList();
- }
- List<Cookie> ret = new LinkedList<>();
- for (String cookie : cookies) {
- ret.addAll(Cookie.fromCookieHeader(cookie));
- }
- return ret;
- }
-
- public void encodeCookieHeader(List<Cookie> cookies) {
- headers().put(HttpHeaders.Names.COOKIE, Cookie.toCookieHeader(cookies));
- }
-
- /**
- * <p>Returns the set of trailer header fields of this HttpRequest. These are typically meta-data that should have
- * been part of {@link #headers()}, but were not available prior to calling {@link #connect(ResponseHandler)}. You
- * must NOT WRITE to these headers AFTER calling {@link ContentChannel#close(CompletionHandler)}, and you must NOT
- * READ from these headers BEFORE {@link ContentChannel#close(CompletionHandler)} has been called.</p>
- *
- * <p><b>NOTE:</b> These headers are NOT thread-safe. You need to explicitly synchronized on the returned object to
- * prevent concurrency issues such as ConcurrentModificationExceptions.</p>
- *
- * @return The trailer headers of this HttpRequest.
- */
- public HeaderFields trailers() {
- return trailers;
- }
-
- /**
- * Returns whether this request was <em>explicitly</em> chunked from the client.&nbsp;NOTE that there are cases
- * where the underlying HTTP server library (Netty for the time being) will read the request in a chunked manner. An
- * application MUST wait for {@link com.yahoo.jdisc.handler.ContentChannel#close(com.yahoo.jdisc.handler.CompletionHandler)}
- * before it can actually know that it has received the entire request.
- *
- * @return true if this request was chunked from the client.
- */
- public boolean isChunked() {
- return version == Version.HTTP_1_1 &&
- headers().containsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED);
- }
-
- public boolean hasChunkedResponse() {
- return version == Version.HTTP_1_1 &&
- !headers().isTrue(HttpHeaders.Names.X_DISABLE_CHUNKING);
- }
-
- public boolean isKeepAlive() {
- if (headers().containsIgnoreCase(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE)) {
- return true;
- }
- if (headers().containsIgnoreCase(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE)) {
- return false;
- }
- return version == Version.HTTP_1_1;
- }
-
- public Principal getUserPrincipal() {
- return principal;
- }
-
- public void setUserPrincipal(Principal principal) {
- this.principal = principal;
- }
-
- public static HttpRequest newServerRequest(CurrentContainer container, URI uri) {
- return newServerRequest(container, uri, Method.GET);
- }
-
- public static HttpRequest newServerRequest(CurrentContainer container, URI uri, Method method) {
- return newServerRequest(container, uri, method, Version.HTTP_1_1);
- }
-
- public static HttpRequest newServerRequest(CurrentContainer container, URI uri, Method method, Version version) {
- return newServerRequest(container, uri, method, version, null);
- }
-
- public static HttpRequest newServerRequest(CurrentContainer container, URI uri, Method method, Version version,
- SocketAddress remoteAddress) {
- return new HttpRequest(container, uri, method, version, remoteAddress, null);
- }
-
- public static HttpRequest newServerRequest(CurrentContainer container, URI uri, Method method, Version version,
- SocketAddress remoteAddress, long connectedAtMillis)
- {
- return new HttpRequest(container, uri, method, version, remoteAddress, connectedAtMillis);
- }
-
- public static HttpRequest newClientRequest(Request parent, URI uri) {
- return newClientRequest(parent, uri, Method.GET);
- }
-
- public static HttpRequest newClientRequest(Request parent, URI uri, Method method) {
- return newClientRequest(parent, uri, method, Version.HTTP_1_1);
- }
-
- public static HttpRequest newClientRequest(Request parent, URI uri, Method method, Version version) {
- return new HttpRequest(parent, uri, method, version);
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpResponse.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpResponse.java
deleted file mode 100644
index f7138ba0e2b..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/HttpResponse.java
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http;
-
-import com.yahoo.jdisc.HeaderFields;
-import com.yahoo.jdisc.Request;
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.handler.CompletionHandler;
-import com.yahoo.jdisc.handler.ContentChannel;
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.servlet.ServletOrJdiscHttpResponse;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * A HTTP response.
- *
- * @author Einar M R Rosenvinge
- */
-public class HttpResponse extends Response implements ServletOrJdiscHttpResponse {
-
- private final HeaderFields trailers = new HeaderFields();
- private boolean chunkedEncodingEnabled = true;
- private String message;
-
- public interface Status extends Response.Status {
- int REQUEST_ENTITY_TOO_LARGE = REQUEST_TOO_LONG;
- int REQUEST_RANGE_NOT_SATISFIABLE = REQUESTED_RANGE_NOT_SATISFIABLE;
- }
-
- protected HttpResponse(Request request, int status, String message, Throwable error) {
- super(status, error);
- this.message = message;
- }
-
- public boolean isChunkedEncodingEnabled() {
- if (headers().contains(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED)) {
- return true;
- }
- if (headers().containsKey(HttpHeaders.Names.CONTENT_LENGTH)) {
- return false;
- }
- return chunkedEncodingEnabled;
- }
-
- public void setChunkedEncodingEnabled(boolean chunkedEncodingEnabled) {
- this.chunkedEncodingEnabled = chunkedEncodingEnabled;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public String getMessage() {
- return message;
- }
-
- @Override
- public void copyHeaders(HeaderFields target) {
- target.addAll(headers());
- }
-
- public List<Cookie> decodeSetCookieHeader() {
- List<String> cookies = headers().get(HttpHeaders.Names.SET_COOKIE);
- if (cookies == null) {
- return Collections.emptyList();
- }
- List<Cookie> ret = new LinkedList<>();
- for (String cookie : cookies) {
- ret.add(Cookie.fromSetCookieHeader(cookie));
- }
- return ret;
- }
-
- public void encodeSetCookieHeader(List<Cookie> cookies) {
- headers().remove(HttpHeaders.Names.SET_COOKIE);
- for (Cookie cookie : cookies) {
- headers().add(HttpHeaders.Names.SET_COOKIE, Cookie.toSetCookieHeaders(Arrays.asList(cookie)));
- }
- }
-
- /**
- * <p>Returns the set of trailer header fields of this HttpResponse. These are typically meta-data that should have
- * been part of {@link #headers()}, but were not available prior to calling {@link
- * ResponseHandler#handleResponse(Response)}. You must NOT WRITE to these headers AFTER calling {@link
- * ContentChannel#close(CompletionHandler)}, and you must NOT READ from these headers BEFORE {@link
- * ContentChannel#close(CompletionHandler)} has been called.</p>
- *
- * <p><b>NOTE:</b> These headers are NOT thread-safe. You need to explicitly synchronized on the returned object to
- * prevent concurrency issues such as ConcurrentModificationExceptions.</p>
- *
- * @return The trailer headers of this HttpRequest.
- */
- public HeaderFields trailers() {
- return trailers;
- }
-
- public static boolean isServerError(Response response) {
- return (response.getStatus() >= 500) && (response.getStatus() < 600);
- }
-
- public static HttpResponse newInstance(int status) {
- return new HttpResponse(null, status, null, null);
- }
-
- public static HttpResponse newInstance(int status, String message) {
- return new HttpResponse(null, status, message, null);
- }
-
- public static HttpResponse newError(Request request, int status, Throwable error) {
- return new HttpResponse(request, status, formatMessage(error), error);
- }
-
- public static HttpResponse newInternalServerError(Request request, Throwable error) {
- return new HttpResponse(request, Status.INTERNAL_SERVER_ERROR, formatMessage(error), error);
- }
-
- private static String formatMessage(Throwable t) {
- String msg = t.getMessage();
- return msg != null ? msg : t.toString();
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/SecretStore.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/SecretStore.java
deleted file mode 100644
index 4f739c5bd78..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/SecretStore.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http;
-
-/**
- * An abstraction of a secret store for e.g passwords.
- * Implementations can be plugged in to provide passwords for various keys.
- *
- * @author bratseth
- * @author bjorncs
- * @deprecated Use com.yahoo.container.jdisc.secretstore.SecretStore
- */
-@Deprecated // Vespa 8
-public interface SecretStore {
-
- /** Returns the secret for this key */
- String getSecret(String key);
-
- /** Returns the secret for this key and version */
- default String getSecret(String key, int version) {
- throw new UnsupportedOperationException("SecretStore implementation does not support versioned secrets");
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/cloud/package-info.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/cloud/package-info.java
deleted file mode 100644
index 43da1a82077..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/cloud/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-@ExportPackage
-package com.yahoo.jdisc.http.cloud;
-import com.yahoo.osgi.annotation.ExportPackage;
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterRequest.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterRequest.java
deleted file mode 100644
index f7ab399574c..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterRequest.java
+++ /dev/null
@@ -1,543 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.jdisc.HeaderFields;
-import com.yahoo.jdisc.http.Cookie;
-import com.yahoo.jdisc.http.HttpHeaders;
-import com.yahoo.jdisc.http.HttpRequest;
-import com.yahoo.jdisc.http.HttpRequest.Version;
-import com.yahoo.jdisc.http.servlet.ServletOrJdiscHttpRequest;
-
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.security.Principal;
-import java.security.cert.X509Certificate;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Pattern;
-
-/**
- * The Request class on which all filters will operate upon.
- * Test cases that need a concrete
- * instance should create a {@link JdiscFilterRequest}.
- */
-public abstract class DiscFilterRequest {
-
- protected static final String HTTPS_PREFIX = "https";
- protected static final int DEFAULT_HTTP_PORT = 80;
- protected static final int DEFAULT_HTTPS_PORT = 443;
-
- private final ServletOrJdiscHttpRequest parent;
- protected final Map<String, List<String>> untreatedParams;
- private final HeaderFields untreatedHeaders;
- private List<Cookie> untreatedCookies = null;
- private String remoteUser = null;
- private String[] roles = null;
- private boolean overrideIsUserInRole = false;
-
- public DiscFilterRequest(ServletOrJdiscHttpRequest parent) {
- this.parent = parent;
-
- // save untreated headers from parent
- untreatedHeaders = new HeaderFields();
- parent.copyHeaders(untreatedHeaders);
-
- untreatedParams = new HashMap<>(parent.parameters());
- }
-
- public abstract String getMethod();
-
- public Version getVersion() {
- return parent.getVersion();
- }
-
- public URI getUri() {
- return parent.getUri();
- }
-
- public abstract void setUri(URI uri);
-
- public HttpRequest getParentRequest() {
- throw new UnsupportedOperationException("getParentRequest is not supported for " + parent.getClass().getName());
- }
-
- /**
- * Returns the Internet Protocol (IP) address of the client
- * or last proxy that sent the request.
- */
- public String getRemoteAddr() {
- return parent.getRemoteHostAddress();
- }
-
- /**
- * Set the IP address of the remote client associated with this Request.
- */
- public void setRemoteAddr(String remoteIpAddress) {
- InetSocketAddress remoteAddress = new InetSocketAddress(remoteIpAddress, this.getRemotePort());
- parent.setRemoteAddress(remoteAddress);
- }
-
- /**
- * Returns the Internet Protocol (IP) address of the interface
- * on which the request was received.
- */
- public String getLocalAddr() {
- InetSocketAddress localAddress = localAddress();
- if (localAddress.getAddress() == null) return null;
- return localAddress.getAddress().getHostAddress();
- }
-
- private InetSocketAddress localAddress() {
- int port = parent.getUri().getPort();
- if (port < 0)
- port = 0;
- return new InetSocketAddress(parent.getUri().getHost(), port);
- }
-
- public Enumeration<String> getAttributeNames() {
- return Collections.enumeration(parent.context().keySet());
- }
-
- public Object getAttribute(String name) {
- return parent.context().get(name);
- }
-
- public void setAttribute(String name, Object value) {
- parent.context().put(name, value);
- }
-
- public boolean containsAttribute(String name) {
- return parent.context().containsKey(name);
- }
-
- public void removeAttribute(String name) {
- parent.context().remove(name);
- }
-
- public abstract String getParameter(String name);
-
- public abstract Enumeration<String> getParameterNames();
-
- public List<String> getParameterNamesAsList() {
- return new ArrayList<String>(parent.parameters().keySet());
- }
-
- public Enumeration<String> getParameterValues(String name) {
- return Collections.enumeration(parent.parameters().get(name));
- }
-
- public List<String> getParameterValuesAsList(String name) {
- return parent.parameters().get(name);
- }
-
- public Map<String,List<String>> getParameterMap() {
- return parent.parameters();
- }
-
-
- /**
- * Returns the hostName of remoteHost, or null if none
- */
- public String getRemoteHost() {
- return parent.getRemoteHostName();
- }
-
- /**
- * Returns the Internet Protocol (IP) port number of
- * the interface on which the request was received.
- */
- public int getLocalPort() {
- return localAddress().getPort();
- }
-
- /**
- * Returns the port of remote host
- */
- public int getRemotePort() {
- return parent.getRemotePort();
- }
-
- /**
- * Returns a unmodifiable map of untreatedParameters from the
- * parent request.
- */
- public Map<String, List<String>> getUntreatedParams() {
- return Collections.unmodifiableMap(untreatedParams);
- }
-
-
- /**
- * Returns the untreatedHeaders from
- * parent request
- */
- public HeaderFields getUntreatedHeaders() {
- return untreatedHeaders;
- }
-
- /**
- * Returns the untreatedCookies from
- * parent request
- */
- public List<Cookie> getUntreatedCookies() {
- if (untreatedCookies == null) {
- this.untreatedCookies = parent.decodeCookieHeader();
- }
- return Collections.unmodifiableList(untreatedCookies);
- }
-
- /**
- * Sets a header with the given name and value.
- * If the header had already been set, the new value overwrites the previous one.
- */
- public abstract void addHeader(String name, String value);
-
- public long getDateHeader(String name) {
- String value = getHeader(name);
- if (value == null)
- return -1L;
-
- Date date = null;
- for (int i = 0; (date == null) && (i < formats.length); i++) {
- try {
- date = formats[i].parse(value);
- } catch (ParseException e) {
- }
- }
- if (date == null) {
- return -1L;
- }
-
- return date.getTime();
- }
-
- public abstract String getHeader(String name);
-
- public abstract Enumeration<String> getHeaderNames();
-
- public abstract List<String> getHeaderNamesAsList();
-
- public abstract Enumeration<String> getHeaders(String name);
-
- public abstract List<String> getHeadersAsList(String name);
-
- public abstract void removeHeaders(String name);
-
- /**
- * Sets a header with the given name and value.
- * If the header had already been set, the new value overwrites the previous one.
- *
- */
- public abstract void setHeaders(String name, String value);
-
- /**
- * Sets a header with the given name and value.
- * If the header had already been set, the new value overwrites the previous one.
- *
- */
- public abstract void setHeaders(String name, List<String> values);
-
- public int getIntHeader(String name) {
- String value = getHeader(name);
- if (value == null) {
- return -1;
- } else {
- return Integer.parseInt(value);
- }
- }
-
-
- public List<Cookie> getCookies() {
- return parent.decodeCookieHeader();
- }
-
- public void setCookies(List<Cookie> cookies) {
- parent.encodeCookieHeader(cookies);
- }
-
- public long getConnectedAt(TimeUnit unit) {
- return parent.getConnectedAt(unit);
- }
-
- public String getProtocol() {
- return getVersion().name();
- }
-
- /**
- * Returns the query string that is contained in the request URL.
- * Returns the undecoded value uri.getRawQuery()
- */
- public String getQueryString() {
- return getUri().getRawQuery();
- }
-
- /**
- * Returns the login of the user making this request,
- * if the user has been authenticated, or null if the user has not been authenticated.
- */
- public String getRemoteUser() {
- return remoteUser;
- }
-
- public String getRequestURI() {
- return getUri().getRawPath();
- }
-
- public String getRequestedSessionId() {
- return null;
- }
-
- public String getScheme() {
- return getUri().getScheme();
- }
-
- public void setScheme(String scheme, boolean isSecure) {
- String uri = getUri().toString();
- String arr [] = uri.split("://");
- URI newUri = URI.create(scheme + "://" + arr[1]);
- setUri(newUri);
- }
-
- public String getServerName() {
- return getUri().getHost();
- }
-
- public int getServerPort() {
- int port = getUri().getPort();
- if(port == -1) {
- if(isSecure()) {
- port = DEFAULT_HTTPS_PORT;
- }
- else {
- port = DEFAULT_HTTP_PORT;
- }
- }
-
- return port;
- }
-
- public abstract Principal getUserPrincipal();
-
- public boolean isSecure() {
- if(getScheme().equalsIgnoreCase(HTTPS_PREFIX)) {
- return true;
- }
- return false;
- }
-
-
- /**
- * Returns a boolean indicating whether the authenticated user
- * is included in the specified logical "role".
- */
- public boolean isUserInRole(String role) {
- if (overrideIsUserInRole) {
- if (roles != null) {
- for (String role1 : roles) {
- if (role1 != null && role1.trim().length() > 0) {
- String userRole = role1.trim();
- if (userRole.equals(role)) {
- return true;
- }
- }
- }
- }
- return false;
- }
- else {
- return false;
- }
- }
-
- public void setOverrideIsUserInRole(boolean overrideIsUserInRole) {
- this.overrideIsUserInRole = overrideIsUserInRole;
- }
-
- public void setRemoteHost(String remoteAddr) { }
-
- public void setRemoteUser(String remoteUser) {
- this.remoteUser = remoteUser;
- }
-
- public abstract void setUserPrincipal(Principal principal);
-
- /**
- * @return The client certificate chain in ascending order of trust. The first certificate is the one sent from the client.
- * Returns an empty list if the client did not provide a certificate.
- */
- public abstract List<X509Certificate> getClientCertificateChain();
-
- public void setUserRoles(String[] roles) {
- this.roles = roles;
- }
-
- /**
- * Returns the content-type for the request
- */
- public String getContentType() {
- return getHeader(HttpHeaders.Names.CONTENT_TYPE);
- }
-
-
- /**
- * Get character encoding
- */
- public String getCharacterEncoding() {
- return getCharsetFromContentType(this.getContentType());
- }
-
- /**
- * Set character encoding
- */
- public void setCharacterEncoding(String encoding) {
- String charEncoding = setCharsetFromContentType(this.getContentType(), encoding);
- if (charEncoding != null && !charEncoding.isEmpty()) {
- removeHeaders(HttpHeaders.Names.CONTENT_TYPE);
- setHeaders(HttpHeaders.Names.CONTENT_TYPE, charEncoding);
- }
- }
-
- /**
- * Can be called multiple times to add Cookies
- */
- public void addCookie(JDiscCookieWrapper cookie) {
- if (cookie != null) {
- List<Cookie> cookies = new ArrayList<>();
- // Get current set of cookies first
- List<Cookie> c = getCookies();
- if (c != null && !c.isEmpty()) {
- cookies.addAll(c);
- }
- cookies.add(cookie.getCookie());
- setCookies(cookies);
- }
- }
-
- public abstract void clearCookies();
-
- public JDiscCookieWrapper[] getWrappedCookies() {
- List<Cookie> cookies = getCookies();
- if (cookies == null) {
- return null;
- }
- List<JDiscCookieWrapper> cookieWrapper = new ArrayList<>(cookies.size());
- for(Cookie cookie : cookies) {
- cookieWrapper.add(JDiscCookieWrapper.wrap(cookie));
- }
-
- return cookieWrapper.toArray(new JDiscCookieWrapper[cookieWrapper.size()]);
- }
-
- private String setCharsetFromContentType(String contentType,String charset) {
- String newContentType = "";
- if (contentType == null)
- return (null);
- int start = contentType.indexOf("charset=");
- if (start < 0) {
- //No charset present:
- newContentType = contentType + ";charset=" + charset;
- return newContentType;
- }
- String encoding = contentType.substring(start + 8);
- int end = encoding.indexOf(';');
- if (end >= 0) {
- newContentType = contentType.substring(0,start);
- newContentType = newContentType + "charset=" + charset;
- newContentType = newContentType + encoding.substring(end,encoding.length());
- }
- else {
- newContentType = contentType.substring(0,start);
- newContentType = newContentType + "charset=" + charset;
- }
-
- return (newContentType.trim());
-
- }
-
- private String getCharsetFromContentType(String contentType) {
-
- if (contentType == null)
- return (null);
- int start = contentType.indexOf("charset=");
- if (start < 0)
- return (null);
- String encoding = contentType.substring(start + 8);
- int end = encoding.indexOf(';');
- if (end >= 0)
- encoding = encoding.substring(0, end);
- encoding = encoding.trim();
- if ((encoding.length() > 2) && (encoding.startsWith("\""))
- && (encoding.endsWith("\"")))
- encoding = encoding.substring(1, encoding.length() - 1);
- return (encoding.trim());
-
- }
-
- public static boolean isMultipart(DiscFilterRequest request) {
- if (request == null) {
- return false;
- }
-
- String contentType = request.getContentType();
-
- if (contentType == null) {
- return false;
- }
-
- String[] parts = Pattern.compile(";").split(contentType);
- if (parts.length == 0) {
- return false;
- }
-
- for (String part : parts) {
- if ("multipart/form-data".equals(part)) {
- return true;
- }
- }
-
- return false;
- }
-
- protected static ThreadLocalSimpleDateFormat formats[] = {
- new ThreadLocalSimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
- new ThreadLocalSimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
- new ThreadLocalSimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) };
-
- /**
- * The set of SimpleDateFormat formats to use in getDateHeader().
- *
- * Notice that because SimpleDateFormat is not thread-safe, we can't declare
- * formats[] as a static variable.
- */
- protected static final class ThreadLocalSimpleDateFormat extends ThreadLocal<SimpleDateFormat> {
-
- private final String format;
- private final Locale locale;
-
- public ThreadLocalSimpleDateFormat(String format, Locale locale) {
- super();
- this.format = format;
- this.locale = locale;
- }
-
- // @see java.lang.ThreadLocal#initialValue()
- @Override
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat(format, locale);
- }
-
- public Date parse(String value) throws ParseException {
- return get().parse(value);
- }
-
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterResponse.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterResponse.java
deleted file mode 100644
index 4e8b779c516..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterResponse.java
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-
-import com.yahoo.jdisc.http.servlet.ServletOrJdiscHttpResponse;
-
-import com.yahoo.jdisc.HeaderFields;
-import com.yahoo.jdisc.http.Cookie;
-
-
-import com.yahoo.jdisc.http.HttpResponse;
-
-/**
- * This class was made abstract from 5.27. Test cases that need
- * a concrete instance should create a {@link JdiscFilterResponse}.
- *
- * @author tejalk
- */
-public abstract class DiscFilterResponse {
-
- private final ServletOrJdiscHttpResponse parent;
- private final HeaderFields untreatedHeaders;
- private final List<Cookie> untreatedCookies;
-
- public DiscFilterResponse(ServletOrJdiscHttpResponse parent) {
- this.parent = parent;
-
- this.untreatedHeaders = new HeaderFields();
- parent.copyHeaders(untreatedHeaders);
-
- this.untreatedCookies = getCookies();
- }
-
- /* Attributes on the response are only used for unit testing.
- * There is no such thing as 'attributes' in the underlying response. */
-
- public Enumeration<String> getAttributeNames() {
- return Collections.enumeration(parent.context().keySet());
- }
-
- public Object getAttribute(String name) {
- return parent.context().get(name);
- }
-
- public void setAttribute(String name, Object value) {
- parent.context().put(name, value);
- }
-
- public void removeAttribute(String name) {
- parent.context().remove(name);
- }
-
- /**
- * Returns the untreatedHeaders from the parent request
- */
- public HeaderFields getUntreatedHeaders() {
- return untreatedHeaders;
- }
-
- /**
- * Returns the untreatedCookies from the parent request
- */
- public List<Cookie> getUntreatedCookies() {
- return untreatedCookies;
- }
-
- /**
- * Sets a header with the given name and value.
- * <p>
- * If the header had already been set, the new value overwrites the previous one.
- */
- public abstract void setHeader(String name, String value);
-
- public abstract void removeHeaders(String name);
-
- /**
- * Sets a header with the given name and value.
- * <p>
- * If the header had already been set, the new value overwrites the previous one.
- */
- public abstract void setHeaders(String name, String value);
-
- /**
- * Sets a header with the given name and value.
- * <p>
- * If the header had already been set, the new value overwrites the previous one.
- */
- public abstract void setHeaders(String name, List<String> values);
-
- /**
- * Adds a header with the given name and value
- * @see com.yahoo.jdisc.HeaderFields#add
- */
- public abstract void addHeader(String name, String value);
-
- public abstract String getHeader(String name);
-
- public List<Cookie> getCookies() {
- return parent.decodeSetCookieHeader();
- }
-
- public abstract void setCookies(List<Cookie> cookies);
-
- public int getStatus() {
- return parent.getStatus();
- }
-
- public abstract void setStatus(int status);
-
- /**
- * Return the parent HttpResponse
- */
- public HttpResponse getParentResponse() {
- if (parent instanceof HttpResponse)
- return (HttpResponse)parent;
- throw new UnsupportedOperationException(
- "getParentResponse is not supported for " + parent.getClass().getName());
- }
-
- public void addCookie(JDiscCookieWrapper cookie) {
- if(cookie != null) {
- List<Cookie> cookies = new ArrayList<>();
- //Get current set of cookies first
- List<Cookie> c = getCookies();
- if((c != null) && (! c.isEmpty())) {
- cookies.addAll(c);
- }
- cookies.add(cookie.getCookie());
- setCookies(cookies);
- }
- }
-
- /**
- * This method does not actually send the response as it
- * does not have access to responseHandler but
- * just sets the status. The methodName is misleading
- * for historical reasons.
- */
- public void sendError(int errorCode) throws IOException {
- setStatus(errorCode);
- }
-
- public void setCookie(String name, String value) {
- Cookie cookie = new Cookie(name, value);
- setCookies(Arrays.asList(cookie));
- }
-
- }
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/FilterConfig.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/FilterConfig.java
deleted file mode 100644
index af9e2b5e99a..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/FilterConfig.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import java.util.Collection;
-
-/**
- * Legacy filter config. Prefer to use a regular stringly typed config class for new filters.
- *
- * @author tejalk
- */
-public interface FilterConfig {
-
- /** Returns the filter-name of this filter */
- String getFilterName();
-
- /** Returns the filter-class of this filter */
- String getFilterClass();
-
- /**
- * Returns a String containing the value of the
- * named initialization parameter, or null if
- * the parameter does not exist.
- *
- * @param name a String specifying the name of the initialization parameter
- * @return a String containing the value of the initialization parameter
- */
- String getInitParameter(String name);
-
- /**
- * Returns the boolean value of the init parameter. If not present returns default value
- *
- * @return boolean value of init parameter
- */
- boolean getBooleanInitParameter(String name, boolean defaultValue);
-
- /**
- * Returns the names of the filter's initialization parameters as an Collection of String objects,
- * or an empty Collection if the filter has no initialization parameters.
- */
- Collection<String> getInitParameterNames();
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JDiscCookieWrapper.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JDiscCookieWrapper.java
deleted file mode 100644
index 2b9c650d545..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JDiscCookieWrapper.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.jdisc.http.Cookie;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Wrapper of Cookie.
- *
- * @author Tejal Knot
- *
- */
-public class JDiscCookieWrapper {
-
- private Cookie cookie;
-
- protected JDiscCookieWrapper(Cookie cookie) {
- this.cookie = cookie;
- }
-
- public static JDiscCookieWrapper wrap(Cookie cookie) {
- return new JDiscCookieWrapper(cookie);
- }
-
- public String getDomain() {
- return cookie.getDomain();
- }
-
- public int getMaxAge() {
- return cookie.getMaxAge(TimeUnit.SECONDS);
- }
-
- public String getName() {
- return cookie.getName();
- }
-
- public String getPath() {
- return cookie.getPath();
- }
-
- public boolean getSecure() {
- return cookie.isSecure();
- }
-
- public String getValue() {
- return cookie.getValue();
- }
-
- public void setDomain(String pattern) {
- cookie.setDomain(pattern);
- }
-
- public void setMaxAge(int expiry) {
- cookie.setMaxAge(expiry, TimeUnit.SECONDS);
- }
-
- public void setPath(String uri) {
- cookie.setPath(uri);
- }
-
- public void setSecure(boolean flag) {
- cookie.setSecure(flag);
- }
-
- public void setValue(String newValue) {
- cookie.setValue(newValue);
- }
-
- /**
- * Return com.yahoo.jdisc.http.Cookie
- *
- * @return - cookie
- */
- public Cookie getCookie() {
- return cookie;
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JdiscFilterRequest.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JdiscFilterRequest.java
deleted file mode 100644
index f8d9e6b2642..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JdiscFilterRequest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.jdisc.http.HttpHeaders;
-import com.yahoo.jdisc.http.HttpRequest;
-import com.yahoo.jdisc.http.servlet.ServletRequest;
-
-import java.net.URI;
-import java.security.Principal;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * JDisc implementation of a filter request.
- *
- * @since 5.27
- */
-public class JdiscFilterRequest extends DiscFilterRequest {
-
- private final HttpRequest parent;
-
- public JdiscFilterRequest(HttpRequest parent) {
- super(parent);
- this.parent = parent;
- }
-
- public HttpRequest getParentRequest() {
- return parent;
- }
-
- public void setUri(URI uri) {
- parent.setUri(uri);
- }
-
- @Override
- public String getMethod() {
- return parent.getMethod().name();
- }
-
- @Override
- public String getParameter(String name) {
- if(parent.parameters().containsKey(name)) {
- return parent.parameters().get(name).get(0);
- }
- else {
- return null;
- }
- }
-
- @Override
- public Enumeration<String> getParameterNames() {
- return Collections.enumeration(parent.parameters().keySet());
- }
-
- @Override
- public void addHeader(String name, String value) {
- parent.headers().add(name, value);
- }
-
- @Override
- public String getHeader(String name) {
- List<String> values = parent.headers().get(name);
- if (values == null || values.isEmpty()) {
- return null;
- }
- return values.get(values.size() - 1);
- }
-
- public Enumeration<String> getHeaderNames() {
- return Collections.enumeration(parent.headers().keySet());
- }
-
- public List<String> getHeaderNamesAsList() {
- return new ArrayList<String>(parent.headers().keySet());
- }
-
- @Override
- public Enumeration<String> getHeaders(String name) {
- return Collections.enumeration(getHeadersAsList(name));
- }
-
- public List<String> getHeadersAsList(String name) {
- List<String> values = parent.headers().get(name);
- if(values == null) {
- return Collections.<String>emptyList();
- }
- return parent.headers().get(name);
- }
-
- @Override
- public void removeHeaders(String name) {
- parent.headers().remove(name);
- }
-
- @Override
- public void setHeaders(String name, String value) {
- parent.headers().put(name, value);
- }
-
- @Override
- public void setHeaders(String name, List<String> values) {
- parent.headers().put(name, values);
- }
-
- @Override
- public Principal getUserPrincipal() {
- return parent.getUserPrincipal();
- }
-
- @Override
- public void setUserPrincipal(Principal principal) {
- this.parent.setUserPrincipal(principal);
- }
-
- @Override
- public List<X509Certificate> getClientCertificateChain() {
- return Optional.ofNullable(parent.context().get(ServletRequest.JDISC_REQUEST_X509CERT))
- .map(X509Certificate[].class::cast)
- .map(Arrays::asList)
- .orElse(Collections.emptyList());
- }
-
- @Override
- public void clearCookies() {
- parent.headers().remove(HttpHeaders.Names.COOKIE);
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JdiscFilterResponse.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JdiscFilterResponse.java
deleted file mode 100644
index ff81359f93c..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/JdiscFilterResponse.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.jdisc.http.Cookie;
-import com.yahoo.jdisc.http.HttpResponse;
-
-import java.util.List;
-
-/**
- * JDisc implementation of a filter request.
- *
- * @since 5.27
- */
-public class JdiscFilterResponse extends DiscFilterResponse {
-
- private final HttpResponse parent;
-
- public JdiscFilterResponse(HttpResponse parent) {
- super(parent);
- this.parent = parent;
- }
-
- @Override
- public void setStatus(int status) {
- parent.setStatus(status);
- }
-
- @Override
- public void setHeader(String name, String value) {
- parent.headers().put(name, value);
- }
-
- @Override
- public void removeHeaders(String name) {
- parent.headers().remove(name);
- }
-
- @Override
- public void setHeaders(String name, String value) {
- parent.headers().put(name, value);
- }
-
- @Override
- public void setHeaders(String name, List<String> values) {
- parent.headers().put(name, values);
- }
-
- @Override
- public void addHeader(String name, String value) {
- parent.headers().add(name, value);
- }
-
- @Override
- public String getHeader(String name) {
- List<String> values = parent.headers().get(name);
- if (values == null || values.isEmpty()) {
- return null;
- }
- return values.get(values.size() - 1);
- }
-
- @Override
- public void setCookies(List<Cookie> cookies) {
- parent.encodeSetCookieHeader(cookies);
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestFilter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestFilter.java
deleted file mode 100644
index 977e3ab5d1d..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestFilter.java
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.HttpRequest;
-
-/**
- * @author Einar M R Rosenvinge
- */
-public interface RequestFilter extends com.yahoo.jdisc.SharedResource, RequestFilterBase {
-
- void filter(HttpRequest request, ResponseHandler handler);
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestFilterBase.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestFilterBase.java
deleted file mode 100644
index 4eb7091f378..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestFilterBase.java
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-/**
- * @author gjoranv
- * @since 2.4
- */
-public interface RequestFilterBase {
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestView.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestView.java
deleted file mode 100644
index e5e7ae1ef56..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/RequestView.java
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.jdisc.http.HttpRequest.Method;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Read-only view of the request for use by SecurityResponseFilters.
- *
- * @author Tony Vaagenes
- */
-public interface RequestView {
-
- /**
- * Returns a named attribute.
- *
- * @see <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html#getAttribute%28java.lang.String%29">javax.servlet.ServletRequest.getAttribute(java.lang.String)</a>
- * @see com.yahoo.jdisc.Request#context()
- * @return the named data associated with the request that are private to this runtime (not exposed to the client)
- */
- Object getAttribute(String name);
-
- /**
- * Returns an immutable view of all values of a named header field.
- * Returns an empty list if no such header is present.
- */
- List<String> getHeaders(String name);
-
- /**
- * Convenience method for retrieving the first value of a named header field.
- * Returns empty if the header is not set, or if the value list is empty.
- */
- Optional<String> getFirstHeader(String name);
-
- /**
- * Returns the Http method. Only present if the underlying request has http-like semantics.
- */
- Optional<Method> getMethod();
-
- URI getUri();
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ResponseFilter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ResponseFilter.java
deleted file mode 100644
index 44fe7d9fcf1..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ResponseFilter.java
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.jdisc.Request;
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.SharedResource;
-
-/**
- * @author <a href="mailto:einarmr@yahoo-inc.com">Einar M R Rosenvinge</a>
- */
-public interface ResponseFilter extends SharedResource, ResponseFilterBase {
-
- public void filter(Response response, Request request);
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ResponseFilterBase.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ResponseFilterBase.java
deleted file mode 100644
index b869c882351..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ResponseFilterBase.java
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-/**
- * @author gjoranv
- * @since 2.4
- */
-public interface ResponseFilterBase {
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityFilterInvoker.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityFilterInvoker.java
deleted file mode 100644
index cbed273b7ee..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityFilterInvoker.java
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.google.common.annotations.Beta;
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.HttpRequest.Method;
-import com.yahoo.jdisc.http.servlet.ServletRequest;
-
-import com.yahoo.jdisc.http.servlet.ServletResponse;
-import com.yahoo.jdisc.http.server.jetty.FilterInvoker;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.net.URI;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Only intended for internal vespa use.
- *
- * Runs JDisc security filter without using JDisc request/response.
- * Only intended to be used in a servlet context, as the error messages are tailored for that.
- *
- * Assumes that SecurityResponseFilters mutate DiscFilterResponse in the thread they are invoked from.
- *
- * @author Tony Vaagenes
- */
-@Beta
-public class SecurityFilterInvoker implements FilterInvoker {
-
- /**
- * Returns the servlet request to be used in any servlets invoked after this.
- */
- @Override
- public HttpServletRequest invokeRequestFilterChain(RequestFilter requestFilterChain,
- URI uri, HttpServletRequest httpRequest,
- ResponseHandler responseHandler) {
-
- SecurityRequestFilterChain securityChain = cast(SecurityRequestFilterChain.class, requestFilterChain).
- orElseThrow(SecurityFilterInvoker::newUnsupportedOperationException);
-
- ServletRequest wrappedRequest = new ServletRequest(httpRequest, uri);
- securityChain.filter(new ServletFilterRequest(wrappedRequest), responseHandler);
- return wrappedRequest;
- }
-
- @Override
- public void invokeResponseFilterChain(
- ResponseFilter responseFilterChain,
- URI uri,
- HttpServletRequest request,
- HttpServletResponse response) {
-
- SecurityResponseFilterChain securityChain = cast(SecurityResponseFilterChain.class, responseFilterChain).
- orElseThrow(SecurityFilterInvoker::newUnsupportedOperationException);
-
- ServletFilterResponse wrappedResponse = new ServletFilterResponse(new ServletResponse(response));
- securityChain.filter(new ServletRequestView(uri, request), wrappedResponse);
- }
-
- private static UnsupportedOperationException newUnsupportedOperationException() {
- return new UnsupportedOperationException(
- "Filter type not supported. If a request is handled by servlets or jax-rs, then any filters invoked for that request must be security filters.");
- }
-
- private <T> Optional<T> cast(Class<T> securityFilterChainClass, Object filter) {
- return (securityFilterChainClass.isInstance(filter))?
- Optional.of(securityFilterChainClass.cast(filter)):
- Optional.empty();
- }
-
- private static class ServletRequestView implements RequestView {
- private final HttpServletRequest request;
- private final URI uri;
-
- public ServletRequestView(URI uri, HttpServletRequest request) {
- this.request = request;
- this.uri = uri;
- }
-
- @Override
- public Object getAttribute(String name) {
- return request.getAttribute(name);
- }
-
- @Override
- public List<String> getHeaders(String name) {
- return Collections.unmodifiableList(Collections.list(request.getHeaders(name)));
- }
-
- @Override
- public Optional<String> getFirstHeader(String name) {
- return getHeaders(name).stream().findFirst();
- }
-
- @Override
- public Optional<Method> getMethod() {
- return Optional.of(Method.valueOf(request.getMethod()));
- }
-
- @Override
- public URI getUri() {
- return uri;
- }
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityRequestFilter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityRequestFilter.java
deleted file mode 100644
index e6f4add49de..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityRequestFilter.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.jdisc.handler.ResponseHandler;
-
-/**
- * @author Simon Thoresen Hult
- */
-public interface SecurityRequestFilter extends RequestFilterBase {
-
- void filter(DiscFilterRequest request, ResponseHandler handler);
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityRequestFilterChain.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityRequestFilterChain.java
deleted file mode 100644
index 2d97bbdc494..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityRequestFilterChain.java
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.jdisc.AbstractResource;
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.handler.ContentChannel;
-import com.yahoo.jdisc.handler.ResponseHandler;
-
-import com.yahoo.jdisc.http.HttpRequest;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Implementation of TypedFilterChain for DiscFilterRequest
- *
- * @author tejalk
- */
-public final class SecurityRequestFilterChain extends AbstractResource implements RequestFilter {
-
- private final List<SecurityRequestFilter> filters = new ArrayList<>();
-
- private SecurityRequestFilterChain(Iterable<? extends SecurityRequestFilter> filters) {
- for (SecurityRequestFilter filter : filters) {
- this.filters.add(filter);
- }
- }
-
- @Override
- public void filter(HttpRequest request, ResponseHandler responseHandler) {
- DiscFilterRequest discFilterRequest = new JdiscFilterRequest(request);
- filter(discFilterRequest, responseHandler);
- }
-
- public void filter(DiscFilterRequest request, ResponseHandler responseHandler) {
- ResponseHandlerGuard guard = new ResponseHandlerGuard(responseHandler);
- for (int i = 0, len = filters.size(); i < len && !guard.isDone(); ++i) {
- filters.get(i).filter(request, guard);
- }
- }
-
- public static RequestFilter newInstance(SecurityRequestFilter... filters) {
- return newInstance(Arrays.asList(filters));
- }
-
- public static RequestFilter newInstance(List<? extends SecurityRequestFilter> filters) {
- return new SecurityRequestFilterChain(filters);
- }
-
- private static class ResponseHandlerGuard implements ResponseHandler {
-
- private final ResponseHandler responseHandler;
- private boolean done = false;
-
- public ResponseHandlerGuard(ResponseHandler handler) {
- this.responseHandler = handler;
- }
-
- @Override
- public ContentChannel handleResponse(Response response) {
- done = true;
- return responseHandler.handleResponse(response);
- }
-
- public boolean isDone() {
- return done;
- }
- }
-
- /** Returns an unmodifiable view of the filters in this */
- public List<SecurityRequestFilter> getFilters() {
- return Collections.unmodifiableList(filters);
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityResponseFilter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityResponseFilter.java
deleted file mode 100644
index aa4f7d29b89..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityResponseFilter.java
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-public interface SecurityResponseFilter extends ResponseFilterBase {
-
- void filter(DiscFilterResponse response, RequestView request);
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityResponseFilterChain.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityResponseFilterChain.java
deleted file mode 100644
index d45b406a375..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/SecurityResponseFilterChain.java
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-import com.yahoo.jdisc.AbstractResource;
-import com.yahoo.jdisc.Request;
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.http.HttpRequest;
-import com.yahoo.jdisc.http.HttpResponse;
-
-/**
- * Implementation of TypedFilterChain for DiscFilterResponse
- * @author tejalk
- *
- */
-public class SecurityResponseFilterChain extends AbstractResource implements ResponseFilter {
-
- private final List<SecurityResponseFilter> filters = new ArrayList<>();
-
- private SecurityResponseFilterChain(Iterable<? extends SecurityResponseFilter> filters) {
- for (SecurityResponseFilter filter : filters) {
- this.filters.add(filter);
- }
- }
-
- @Override
- public void filter(Response response, Request request) {
- if(response instanceof HttpResponse) {
- DiscFilterResponse discFilterResponse = new JdiscFilterResponse((HttpResponse)response);
- RequestView requestView = new RequestViewImpl(request);
- filter(requestView, discFilterResponse);
- }
-
- }
-
- public void filter(RequestView requestView, DiscFilterResponse response) {
- for (SecurityResponseFilter filter : filters) {
- filter.filter(response, requestView);
- }
- }
-
- public static ResponseFilter newInstance(SecurityResponseFilter... filters) {
- return newInstance(Arrays.asList(filters));
- }
-
- public static ResponseFilter newInstance(List<? extends SecurityResponseFilter> filters) {
- return new SecurityResponseFilterChain(filters);
- }
-
- /** Returns an unmodifiable view of the filters in this */
- public List<SecurityResponseFilter> getFilters() {
- return Collections.unmodifiableList(filters);
- }
-
- static class RequestViewImpl implements RequestView {
-
- private final Request request;
- private final Optional<HttpRequest.Method> method;
-
- public RequestViewImpl(Request request) {
- this.request = request;
- method = request instanceof HttpRequest ?
- Optional.of(((HttpRequest) request).getMethod()):
- Optional.empty();
- }
-
- @Override
- public Object getAttribute(String name) {
- return request.context().get(name);
- }
-
- @Override
- public List<String> getHeaders(String name) {
- List<String> headers = request.headers().get(name);
- return headers == null ? Collections.emptyList() : Collections.unmodifiableList(headers);
- }
-
- @Override
- public Optional<String> getFirstHeader(String name) {
- return getHeaders(name).stream().findFirst();
- }
-
- @Override
- public Optional<HttpRequest.Method> getMethod() {
- return method;
- }
-
- @Override
- public URI getUri() {
- return request.getUri();
- }
-
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ServletFilterRequest.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ServletFilterRequest.java
deleted file mode 100644
index f06f9e256ff..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ServletFilterRequest.java
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.jdisc.http.HttpHeaders;
-import com.yahoo.jdisc.http.servlet.ServletRequest;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.security.Principal;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * Servlet implementation for JDisc filter requests.
- */
-class ServletFilterRequest extends DiscFilterRequest {
-
- private final ServletRequest parent;
-
- public ServletFilterRequest(ServletRequest parent) {
- super(parent);
- this.parent = parent;
- }
-
- ServletRequest getServletRequest() {
- return parent;
- }
-
- public void setUri(URI uri) {
- parent.setUri(uri);
- }
-
- @Override
- public String getMethod() {
- return parent.getRequest().getMethod();
- }
-
- @Override
- public void setRemoteAddr(String remoteIpAddress) {
- throw new UnsupportedOperationException(
- "Setting remote address is not supported for " + this.getClass().getName());
- }
-
- @Override
- public Enumeration<String> getAttributeNames() {
- Set<String> names = new HashSet<>(Collections.list(super.getAttributeNames()));
- names.addAll(Collections.list(parent.getRequest().getAttributeNames()));
- return Collections.enumeration(names);
- }
-
- @Override
- public Object getAttribute(String name) {
- Object jdiscAttribute = super.getAttribute(name);
- return jdiscAttribute != null ?
- jdiscAttribute :
- parent.getRequest().getAttribute(name);
- }
-
- @Override
- public void setAttribute(String name, Object value) {
- super.setAttribute(name, value);
- parent.getRequest().setAttribute(name, value);
- }
-
- @Override
- public boolean containsAttribute(String name) {
- return super.containsAttribute(name)
- || parent.getRequest().getAttribute(name) != null;
- }
-
- @Override
- public void removeAttribute(String name) {
- super.removeAttribute(name);
- parent.getRequest().removeAttribute(name);
- }
-
- @Override
- public String getParameter(String name) {
- return parent.getParameter(name);
- }
-
- @Override
- public Enumeration<String> getParameterNames() {
- return parent.getParameterNames();
- }
-
- @Override
- public void addHeader(String name, String value) {
- parent.addHeader(name, value);
- }
-
- @Override
- public String getHeader(String name) {
- return parent.getHeader(name);
- }
-
- @Override
- public Enumeration<String> getHeaderNames() {
- return parent.getHeaderNames();
- }
-
- public List<String> getHeaderNamesAsList() {
- return Collections.list(getHeaderNames());
- }
-
- @Override
- public Enumeration<String> getHeaders(String name) {
- return parent.getHeaders(name);
- }
-
- @Override
- public List<String> getHeadersAsList(String name) {
- return Collections.list(getHeaders(name));
- }
-
- @Override
- public void setHeaders(String name, String value) {
- parent.setHeaders(name, value);
- }
-
- @Override
- public void setHeaders(String name, List<String> values) {
- parent.setHeaders(name, values);
- }
-
- @Override
- public Principal getUserPrincipal() {
- return parent.getUserPrincipal();
- }
-
- @Override
- public void setUserPrincipal(Principal principal) {
- parent.setUserPrincipal(principal);
- }
-
- @Override
- public List<X509Certificate> getClientCertificateChain() {
- return Optional.ofNullable(parent.getRequest().getAttribute(ServletRequest.SERVLET_REQUEST_X509CERT))
- .map(X509Certificate[].class::cast)
- .map(Arrays::asList)
- .orElse(Collections.emptyList());
- }
-
- @Override
- public void removeHeaders(String name) {
- parent.removeHeaders(name);
- }
-
- @Override
- public void clearCookies() {
- parent.removeHeaders(HttpHeaders.Names.COOKIE);
- }
-
- @Override
- public void setCharacterEncoding(String encoding) {
- super.setCharacterEncoding(encoding);
- try {
- parent.setCharacterEncoding(encoding);
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException("Encoding not supported: " + encoding, e);
- }
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ServletFilterResponse.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ServletFilterResponse.java
deleted file mode 100644
index b603e7776f1..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/ServletFilterResponse.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter;
-
-import com.google.common.collect.Iterables;
-import com.yahoo.jdisc.http.Cookie;
-import com.yahoo.jdisc.http.HttpHeaders;
-import com.yahoo.jdisc.http.servlet.ServletResponse;
-
-import javax.servlet.http.HttpServletResponse;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * Servlet implementation for JDisc filter responses.
- */
-class ServletFilterResponse extends DiscFilterResponse {
-
- private final ServletResponse parent;
-
- public ServletFilterResponse(ServletResponse parent) {
- super(parent);
- this.parent = parent;
- }
-
- ServletResponse getServletResponse() {
- return parent;
- }
-
- public void setStatus(int status) {
- parent.setStatus(status);
- }
-
- @Override
- public void setHeader(String name, String value) {
- parent.setHeader(name, value);
- }
-
- @Override
- public void removeHeaders(String name) {
- HttpServletResponse parentResponse = parent.getResponse();
- if (parentResponse instanceof org.eclipse.jetty.server.Response) {
- org.eclipse.jetty.server.Response jettyResponse = (org.eclipse.jetty.server.Response)parentResponse;
- jettyResponse.getHttpFields().remove(name);
- } else {
- throw new UnsupportedOperationException(
- "Cannot remove headers for response of type " + parentResponse.getClass().getName());
- }
- }
-
- // Why have a setHeaders that takes a single string?
- @Override
- public void setHeaders(String name, String value) {
- parent.setHeader(name, value);
- }
-
- @Override
- public void setHeaders(String name, List<String> values) {
- for (String value : values)
- parent.addHeader(name, value);
- }
-
- @Override
- public void addHeader(String name, String value) {
- parent.addHeader(name, value);
- }
-
- @Override
- public String getHeader(String name) {
- Collection<String> headers = parent.getHeaders(name);
- return headers.isEmpty()
- ? null
- : Iterables.getLast(headers);
- }
-
- @Override
- public void setCookies(List<Cookie> cookies) {
- removeHeaders(HttpHeaders.Names.SET_COOKIE);
- List<String> setCookieHeaders = Cookie.toSetCookieHeaders(cookies);
- setCookieHeaders.forEach(cookie -> addHeader(HttpHeaders.Names.SET_COOKIE, cookie));
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/EmptyRequestFilter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/EmptyRequestFilter.java
deleted file mode 100644
index e1834fd8b7d..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/EmptyRequestFilter.java
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter.chain;
-
-import com.yahoo.jdisc.NoopSharedResource;
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.HttpRequest;
-import com.yahoo.jdisc.http.filter.RequestFilter;
-
-/**
- * @author <a href="mailto:einarmr@yahoo-inc.com">Einar M R Rosenvinge</a>
- */
-public final class EmptyRequestFilter extends NoopSharedResource implements RequestFilter {
-
- public static final RequestFilter INSTANCE = new EmptyRequestFilter();
-
- private EmptyRequestFilter() {
- // hide
- }
-
- @Override
- public void filter(HttpRequest request, ResponseHandler handler) {
-
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/EmptyResponseFilter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/EmptyResponseFilter.java
deleted file mode 100644
index 5ce3f6a496f..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/EmptyResponseFilter.java
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter.chain;
-
-import com.yahoo.jdisc.NoopSharedResource;
-import com.yahoo.jdisc.Request;
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.http.filter.ResponseFilter;
-
-/**
- * @author <a href="mailto:einarmr@yahoo-inc.com">Einar M R Rosenvinge</a>
- */
-public final class EmptyResponseFilter extends NoopSharedResource implements ResponseFilter {
-
- public static final ResponseFilter INSTANCE = new EmptyResponseFilter();
-
- private EmptyResponseFilter() {
- // hide
- }
-
- @Override
- public void filter(Response response, Request request) {
-
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/RequestFilterChain.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/RequestFilterChain.java
deleted file mode 100644
index 85f71777cf3..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/RequestFilterChain.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter.chain;
-
-import com.yahoo.jdisc.AbstractResource;
-import com.yahoo.jdisc.application.ResourcePool;
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.HttpRequest;
-import com.yahoo.jdisc.http.filter.RequestFilter;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author <a href="mailto:einarmr@yahoo-inc.com">Einar M R Rosenvinge</a>
- */
-public final class RequestFilterChain extends AbstractResource implements RequestFilter {
-
- private final List<RequestFilter> filters = new ArrayList<>();
- private final ResourcePool filterReferences = new ResourcePool();
-
- private RequestFilterChain(Iterable<? extends RequestFilter> filters) {
- for (RequestFilter filter : filters) {
- this.filters.add(filter);
- filterReferences.retain(filter);
- }
- }
-
- @Override
- public void filter(HttpRequest request, ResponseHandler responseHandler) {
- ResponseHandlerGuard guard = new ResponseHandlerGuard(responseHandler);
- for (int i = 0, len = filters.size(); i < len && !guard.isDone(); ++i) {
- filters.get(i).filter(request, guard);
- }
- }
-
- @Override
- protected void destroy() {
- filterReferences.release();
- }
-
- public static RequestFilter newInstance(RequestFilter... filters) {
- return newInstance(Arrays.asList(filters));
- }
-
- public static RequestFilter newInstance(List<? extends RequestFilter> filters) {
- if (filters.size() == 0) {
- return EmptyRequestFilter.INSTANCE;
- }
- if (filters.size() == 1) {
- return filters.get(0);
- }
- return new RequestFilterChain(filters);
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/ResponseFilterChain.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/ResponseFilterChain.java
deleted file mode 100644
index 5c5eda1f139..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/ResponseFilterChain.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter.chain;
-
-import com.yahoo.jdisc.AbstractResource;
-import com.yahoo.jdisc.Request;
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.application.ResourcePool;
-import com.yahoo.jdisc.http.filter.ResponseFilter;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author Simon Thoresen Hult
- */
-public final class ResponseFilterChain extends AbstractResource implements ResponseFilter {
-
- private final List<ResponseFilter> filters = new ArrayList<>();
- private final ResourcePool filterReferences = new ResourcePool();
-
- private ResponseFilterChain(Iterable<? extends ResponseFilter> filters) {
- for (ResponseFilter filter : filters) {
- this.filters.add(filter);
- filterReferences.retain(filter);
- }
- }
-
- @Override
- public void filter(Response response, Request request) {
- for (ResponseFilter filter : filters) {
- filter.filter(response, request);
- }
- }
-
- @Override
- protected void destroy() {
- filterReferences.release();
- }
-
- public static ResponseFilter newInstance(ResponseFilter... filters) {
- return newInstance(Arrays.asList(filters));
- }
-
- public static ResponseFilter newInstance(List<? extends ResponseFilter> filters) {
- if (filters.size() == 0) {
- return EmptyResponseFilter.INSTANCE;
- }
- if (filters.size() == 1) {
- return filters.get(0);
- }
- return new ResponseFilterChain(filters);
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/ResponseHandlerGuard.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/ResponseHandlerGuard.java
deleted file mode 100644
index 02600683e27..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/ResponseHandlerGuard.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.filter.chain;
-
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.handler.ContentChannel;
-import com.yahoo.jdisc.handler.ResponseHandler;
-
-/**
- * @author Simon Thoresen Hult
- */
-final class ResponseHandlerGuard implements ResponseHandler {
-
- private final ResponseHandler responseHandler;
- private boolean done = false;
-
- public ResponseHandlerGuard(ResponseHandler handler) {
- this.responseHandler = handler;
- }
-
- @Override
- public ContentChannel handleResponse(Response response) {
- done = true;
- return responseHandler.handleResponse(response);
- }
-
- public boolean isDone() {
- return done;
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/package-info.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/package-info.java
deleted file mode 100644
index 540a1be7b73..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/chain/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-@ExportPackage
-package com.yahoo.jdisc.http.filter.chain;
-
-import com.yahoo.osgi.annotation.ExportPackage;
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/package-info.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/package-info.java
deleted file mode 100644
index e97d447adbb..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/filter/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-@PublicApi
-@ExportPackage
-package com.yahoo.jdisc.http.filter;
-
-import com.yahoo.api.annotations.PublicApi;
-import com.yahoo.osgi.annotation.ExportPackage;
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/package-info.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/package-info.java
deleted file mode 100644
index b8bd76483cf..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-@PublicApi
-@ExportPackage
-package com.yahoo.jdisc.http;
-
-import com.yahoo.api.annotations.PublicApi;
-import com.yahoo.osgi.annotation.ExportPackage;
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java
deleted file mode 100644
index 4de5e5e5387..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLog.java
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.common.base.Objects;
-import com.yahoo.container.logging.AccessLog;
-import com.yahoo.container.logging.AccessLogEntry;
-import com.yahoo.container.logging.RequestLog;
-import com.yahoo.container.logging.RequestLogEntry;
-import com.yahoo.jdisc.http.ServerConfig;
-import com.yahoo.jdisc.http.servlet.ServletRequest;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Response;
-import org.eclipse.jetty.util.component.AbstractLifeCycle;
-
-import javax.servlet.http.HttpServletRequest;
-import java.security.Principal;
-import java.security.cert.X509Certificate;
-import java.time.Duration;
-import java.time.Instant;
-import java.util.List;
-import java.util.OptionalInt;
-import java.util.UUID;
-import java.util.function.BiConsumer;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import static com.yahoo.jdisc.http.server.jetty.HttpServletRequestUtils.getConnectorLocalPort;
-
-/**
- * This class is a bridge between Jetty's {@link org.eclipse.jetty.server.handler.RequestLogHandler}
- * and our own configurable access logging in different formats provided by {@link AccessLog}.
- *
- * @author Oyvind Bakksjo
- * @author bjorncs
- */
-class AccessLogRequestLog extends AbstractLifeCycle implements org.eclipse.jetty.server.RequestLog {
-
- private static final Logger logger = Logger.getLogger(AccessLogRequestLog.class.getName());
-
- // HTTP headers that are logged as extra key-value-pairs in access log entries
- private static final List<String> LOGGED_REQUEST_HEADERS = List.of("Vespa-Client-Version");
-
- private final RequestLog requestLog;
- private final List<String> remoteAddressHeaders;
- private final List<String> remotePortHeaders;
-
- AccessLogRequestLog(RequestLog requestLog, ServerConfig.AccessLog config) {
- this.requestLog = requestLog;
- this.remoteAddressHeaders = config.remoteAddressHeaders();
- this.remotePortHeaders = config.remotePortHeaders();
- }
-
- @Override
- public void log(Request request, Response response) {
- try {
- RequestLogEntry.Builder builder = new RequestLogEntry.Builder();
-
- String peerAddress = request.getRemoteAddr();
- int peerPort = request.getRemotePort();
- long startTime = request.getTimeStamp();
- long endTime = System.currentTimeMillis();
- builder.peerAddress(peerAddress)
- .peerPort(peerPort)
- .localPort(getLocalPort(request))
- .timestamp(Instant.ofEpochMilli(startTime))
- .duration(Duration.ofMillis(Math.max(0, endTime - startTime)))
- .contentSize(response.getHttpChannel().getBytesWritten())
- .statusCode(response.getCommittedMetaData().getStatus());
-
- addNonNullValue(builder, request.getMethod(), RequestLogEntry.Builder::httpMethod);
- addNonNullValue(builder, request.getRequestURI(), RequestLogEntry.Builder::rawPath);
- addNonNullValue(builder, request.getProtocol(), RequestLogEntry.Builder::httpVersion);
- addNonNullValue(builder, request.getScheme(), RequestLogEntry.Builder::scheme);
- addNonNullValue(builder, request.getHeader("User-Agent"), RequestLogEntry.Builder::userAgent);
- addNonNullValue(builder, request.getHeader("Host"), RequestLogEntry.Builder::hostString);
- addNonNullValue(builder, request.getHeader("Referer"), RequestLogEntry.Builder::referer);
- addNonNullValue(builder, request.getQueryString(), RequestLogEntry.Builder::rawQuery);
-
- Principal principal = (Principal) request.getAttribute(ServletRequest.JDISC_REQUEST_PRINCIPAL);
- addNonNullValue(builder, principal, RequestLogEntry.Builder::userPrincipal);
-
- String requestFilterId = (String) request.getAttribute(ServletRequest.JDISC_REQUEST_CHAIN);
- addNonNullValue(builder, requestFilterId, (b, chain) -> b.addExtraAttribute("request-chain", chain));
-
- String responseFilterId = (String) request.getAttribute(ServletRequest.JDISC_RESPONSE_CHAIN);
- addNonNullValue(builder, responseFilterId, (b, chain) -> b.addExtraAttribute("response-chain", chain));
-
- UUID connectionId = (UUID) request.getAttribute(JettyConnectionLogger.CONNECTION_ID_REQUEST_ATTRIBUTE);
- addNonNullValue(builder, connectionId, (b, uuid) -> b.connectionId(uuid.toString()));
-
- String remoteAddress = getRemoteAddress(request);
- if (!Objects.equal(remoteAddress, peerAddress)) {
- builder.remoteAddress(remoteAddress);
- }
- int remotePort = getRemotePort(request);
- if (remotePort != peerPort) {
- builder.remotePort(remotePort);
- }
- LOGGED_REQUEST_HEADERS.forEach(header -> {
- String value = request.getHeader(header);
- if (value != null) {
- builder.addExtraAttribute(header, value);
- }
- });
- X509Certificate[] clientCert = (X509Certificate[]) request.getAttribute(ServletRequest.SERVLET_REQUEST_X509CERT);
- if (clientCert != null && clientCert.length > 0) {
- builder.sslPrincipal(clientCert[0].getSubjectX500Principal());
- }
-
- AccessLogEntry accessLogEntry = (AccessLogEntry) request.getAttribute(JDiscHttpServlet.ATTRIBUTE_NAME_ACCESS_LOG_ENTRY);
- if (accessLogEntry != null) {
- var extraAttributes = accessLogEntry.getKeyValues();
- if (extraAttributes != null) {
- extraAttributes.forEach(builder::addExtraAttributes);
- }
- addNonNullValue(builder, accessLogEntry.getHitCounts(), RequestLogEntry.Builder::hitCounts);
- addNonNullValue(builder, accessLogEntry.getTrace(), RequestLogEntry.Builder::traceNode);
- }
-
- requestLog.log(builder.build());
- } catch (Exception e) {
- // Catching any exceptions here as it is unclear how Jetty handles exceptions from a RequestLog.
- logger.log(Level.SEVERE, "Failed to log access log entry: " + e.getMessage(), e);
- }
- }
-
- private String getRemoteAddress(HttpServletRequest request) {
- for (String header : remoteAddressHeaders) {
- String value = request.getHeader(header);
- if (value != null) return value;
- }
- return request.getRemoteAddr();
- }
-
- private int getRemotePort(HttpServletRequest request) {
- for (String header : remotePortHeaders) {
- String value = request.getHeader(header);
- if (value != null) {
- OptionalInt maybePort = parsePort(value);
- if (maybePort.isPresent()) return maybePort.getAsInt();
- }
- }
- return request.getRemotePort();
- }
-
- private static int getLocalPort(Request request) {
- int connectorLocalPort = getConnectorLocalPort(request);
- if (connectorLocalPort <= 0) return request.getLocalPort(); // If connector is already closed
- return connectorLocalPort;
- }
-
- private static OptionalInt parsePort(String port) {
- try {
- return OptionalInt.of(Integer.parseInt(port));
- } catch (IllegalArgumentException e) {
- return OptionalInt.empty();
- }
- }
-
- private static <T> void addNonNullValue(
- RequestLogEntry.Builder builder, T value, BiConsumer<RequestLogEntry.Builder, T> setter) {
- if (value != null) {
- setter.accept(builder, value);
- }
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLoggingRequestHandler.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLoggingRequestHandler.java
deleted file mode 100644
index 842ab75a312..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AccessLoggingRequestHandler.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.common.base.Preconditions;
-import com.yahoo.container.logging.AccessLogEntry;
-import com.yahoo.jdisc.Request;
-import com.yahoo.jdisc.handler.AbstractRequestHandler;
-import com.yahoo.jdisc.handler.ContentChannel;
-import com.yahoo.jdisc.handler.RequestHandler;
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.HttpRequest;
-
-import java.util.Map;
-import java.util.Optional;
-
-/**
- * A wrapper RequestHandler that enables access logging. By wrapping the request handler, we are able to wrap the
- * response handler as well. Hence, we can populate the access log entry with information from both the request
- * and the response. This wrapper also adds the access log entry to the request context, so that request handlers
- * may add information to it.
- *
- * Does not otherwise interfere with the request processing of the delegate request handler.
- *
- * @author bakksjo
- */
-public class AccessLoggingRequestHandler extends AbstractRequestHandler {
- public static final String CONTEXT_KEY_ACCESS_LOG_ENTRY
- = AccessLoggingRequestHandler.class.getName() + "_access-log-entry";
-
- public static Optional<AccessLogEntry> getAccessLogEntry(final HttpRequest jdiscRequest) {
- final Map<String, Object> requestContextMap = jdiscRequest.context();
- return getAccessLogEntry(requestContextMap);
- }
-
- public static Optional<AccessLogEntry> getAccessLogEntry(final Map<String, Object> requestContextMap) {
- return Optional.ofNullable(
- (AccessLogEntry) requestContextMap.get(CONTEXT_KEY_ACCESS_LOG_ENTRY));
- }
-
- private final RequestHandler delegate;
- private final AccessLogEntry accessLogEntry;
-
- public AccessLoggingRequestHandler(
- final RequestHandler delegateRequestHandler,
- final AccessLogEntry accessLogEntry) {
- this.delegate = delegateRequestHandler;
- this.accessLogEntry = accessLogEntry;
- }
-
- @Override
- public ContentChannel handleRequest(final Request request, final ResponseHandler handler) {
- Preconditions.checkArgument(request instanceof HttpRequest, "Expected HttpRequest, got " + request);
- final HttpRequest httpRequest = (HttpRequest) request;
- httpRequest.context().put(CONTEXT_KEY_ACCESS_LOG_ENTRY, accessLogEntry);
- return delegate.handleRequest(request, handler);
- }
-
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AsyncCompleteListener.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AsyncCompleteListener.java
deleted file mode 100644
index 7dba217e01c..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/AsyncCompleteListener.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.AsyncEvent;
-import javax.servlet.AsyncListener;
-import java.io.IOException;
-
-/**
- * Interface for async listeners only interested in onComplete.
- * @author Tony Vaagenes
- */
-@FunctionalInterface
-interface AsyncCompleteListener extends AsyncListener {
- @Override
- default void onTimeout(AsyncEvent event) throws IOException {}
-
- @Override
- default void onError(AsyncEvent event) throws IOException {}
-
- @Override
- default void onStartAsync(AsyncEvent event) throws IOException {}
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/CompletionHandlerUtils.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/CompletionHandlerUtils.java
deleted file mode 100644
index f436d5490d7..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/CompletionHandlerUtils.java
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.CompletionHandler;
-
-/**
- * @author bjorncs
- */
-public interface CompletionHandlerUtils {
- CompletionHandler NOOP_COMPLETION_HANDLER = new CompletionHandler() {
- @Override public void completed() {}
- @Override public void failed(final Throwable t) {}
- };
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/CompletionHandlers.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/CompletionHandlers.java
deleted file mode 100644
index 975d88f5c34..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/CompletionHandlers.java
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.CompletionHandler;
-
-import java.util.Arrays;
-
-/**
- * @author Simon Thoresen Hult
- */
-public class CompletionHandlers {
-
- public static void tryComplete(CompletionHandler handler) {
- if (handler == null) {
- return;
- }
- try {
- handler.completed();
- } catch (Exception e) {
- // ignore
- }
- }
-
- public static void tryFail(CompletionHandler handler, Throwable t) {
- if (handler == null) {
- return;
- }
- try {
- handler.failed(t);
- } catch (Exception e) {
- // ignore
- }
- }
-
- public static CompletionHandler wrap(CompletionHandler... handlers) {
- return wrap(Arrays.asList(handlers));
- }
-
- public static CompletionHandler wrap(final Iterable<CompletionHandler> handlers) {
- return new CompletionHandler() {
-
- @Override
- public void completed() {
- for (CompletionHandler handler : handlers) {
- tryComplete(handler);
- }
- }
-
- @Override
- public void failed(Throwable t) {
- for (CompletionHandler handler : handlers) {
- tryFail(handler, t);
- }
- }
- };
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectionThrottler.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectionThrottler.java
deleted file mode 100644
index b9001d187a9..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectionThrottler.java
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright 2019 Yahoo Holdings. 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.http.ConnectorConfig;
-import org.eclipse.jetty.io.Connection;
-import org.eclipse.jetty.io.SelectorManager;
-import org.eclipse.jetty.server.AbstractConnector;
-import org.eclipse.jetty.server.ConnectionLimit;
-import org.eclipse.jetty.server.LowResourceMonitor;
-import org.eclipse.jetty.util.annotation.ManagedObject;
-import org.eclipse.jetty.util.component.AbstractLifeCycle;
-import org.eclipse.jetty.util.component.ContainerLifeCycle;
-import org.eclipse.jetty.util.component.LifeCycle;
-import org.eclipse.jetty.util.statistic.RateStatistic;
-import org.eclipse.jetty.util.thread.Scheduler;
-
-import java.nio.channels.SelectableChannel;
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Logger;
-
-import static java.util.stream.Collectors.toList;
-
-/**
- * Monitor various resource constraints and throttles new connections once a threshold is exceeded.
- * Implementation inspired by Jetty's {@link LowResourceMonitor}, {@link AcceptRateLimit} and {@link ConnectionLimit}.
- *
- * @author bjorncs
- */
-@ManagedObject("Monitor various resource constraints and throttles new connections once a threshold is exceeded")
-class ConnectionThrottler extends ContainerLifeCycle implements SelectorManager.AcceptListener {
-
- private static final Logger log = Logger.getLogger(ConnectionThrottler.class.getName());
-
- private final Object monitor = new Object();
- private final Collection<ResourceLimit> resourceLimits = new ArrayList<>();
- private final AbstractConnector connector;
- private final Duration idleTimeout;
- private final Scheduler scheduler;
-
- private boolean isRegistered = false;
- private boolean isThrottling = false;
-
- ConnectionThrottler(AbstractConnector connector, ConnectorConfig.Throttling config) {
- this(Runtime.getRuntime(), new RateStatistic(1, TimeUnit.SECONDS), connector.getScheduler(), connector, config);
- }
-
- // Intended for unit testing
- ConnectionThrottler(Runtime runtime,
- RateStatistic rateStatistic,
- Scheduler scheduler,
- AbstractConnector connector,
- ConnectorConfig.Throttling config) {
- this.connector = connector;
- if (config.maxHeapUtilization() != -1) {
- this.resourceLimits.add(new HeapResourceLimit(runtime, config.maxHeapUtilization()));
- }
- if (config.maxConnections() != -1) {
- this.resourceLimits.add(new ConnectionLimitThreshold(config.maxConnections()));
- }
- if (config.maxAcceptRate() != -1) {
- this.resourceLimits.add(new AcceptRateLimit(rateStatistic, config.maxAcceptRate()));
- }
- this.idleTimeout = config.idleTimeout() != -1 ? Duration.ofMillis((long) (config.idleTimeout()*1000)) : null;
- this.scheduler = scheduler;
- }
-
- void registerWithConnector() {
- synchronized (monitor) {
- if (isRegistered) return;
- isRegistered = true;
- resourceLimits.forEach(connector::addBean);
- connector.addBean(this);
- }
- }
-
- @Override
- public void onAccepting(SelectableChannel channel) {
- throttleIfAnyThresholdIsExceeded();
- }
-
- private void throttleIfAnyThresholdIsExceeded() {
- synchronized (monitor) {
- if (isThrottling) return;
- List<String> reasons = getThrottlingReasons();
- if (reasons.isEmpty()) return;
- log.warning(String.format("Throttling new connection. Reasons: %s", reasons));
- isThrottling = true;
- if (connector.isAccepting()) {
- connector.setAccepting(false);
- }
- if (idleTimeout != null) {
- log.warning(String.format("Applying idle timeout to existing connections: timeout=%sms", idleTimeout));
- connector.getConnectedEndPoints()
- .forEach(endPoint -> endPoint.setIdleTimeout(idleTimeout.toMillis()));
- }
- scheduler.schedule(this::unthrottleIfBelowThresholds, 1, TimeUnit.SECONDS);
- }
- }
-
- private void unthrottleIfBelowThresholds() {
- synchronized (monitor) {
- if (!isThrottling) return;
- List<String> reasons = getThrottlingReasons();
- if (!reasons.isEmpty()) {
- log.warning(String.format("Throttling continued. Reasons: %s", reasons));
- scheduler.schedule(this::unthrottleIfBelowThresholds, 1, TimeUnit.SECONDS);
- return;
- }
- if (idleTimeout != null) {
- long originalTimeout = connector.getIdleTimeout();
- log.info(String.format("Reverting idle timeout for existing connections: timeout=%sms", originalTimeout));
- connector.getConnectedEndPoints()
- .forEach(endPoint -> endPoint.setIdleTimeout(originalTimeout));
- }
- log.info("Throttling disabled - resource thresholds no longer exceeded");
- if (!connector.isAccepting()) {
- connector.setAccepting(true);
- }
- isThrottling = false;
- }
- }
-
- private List<String> getThrottlingReasons() {
- synchronized (monitor) {
- return resourceLimits.stream()
- .map(ResourceLimit::isThresholdExceeded)
- .filter(Optional::isPresent)
- .map(Optional::get)
- .collect(toList());
- }
- }
-
- private interface ResourceLimit extends LifeCycle, SelectorManager.AcceptListener, Connection.Listener {
- /**
- * @return A string containing the reason if threshold exceeded, empty otherwise.
- */
- Optional<String> isThresholdExceeded();
-
- @Override default void onOpened(Connection connection) {}
-
- @Override default void onClosed(Connection connection) {}
- }
-
- /**
- * Note: implementation inspired by Jetty's {@link LowResourceMonitor}
- */
- private static class HeapResourceLimit extends AbstractLifeCycle implements ResourceLimit {
- private final Runtime runtime;
- private final double maxHeapUtilization;
-
- HeapResourceLimit(Runtime runtime, double maxHeapUtilization) {
- this.runtime = runtime;
- this.maxHeapUtilization = maxHeapUtilization;
- }
-
- @Override
- public Optional<String> isThresholdExceeded() {
- double heapUtilization = (runtime.maxMemory() - runtime.freeMemory()) / (double) runtime.maxMemory();
- if (heapUtilization > maxHeapUtilization) {
- return Optional.of(String.format("Max heap utilization exceeded: %f%%>%f%%", heapUtilization*100, maxHeapUtilization*100));
- }
- return Optional.empty();
- }
- }
-
- /**
- * Note: implementation inspired by Jetty's {@link org.eclipse.jetty.server.AcceptRateLimit}
- */
- private static class AcceptRateLimit extends AbstractLifeCycle implements ResourceLimit {
- private final Object monitor = new Object();
- private final RateStatistic rateStatistic;
- private final int maxAcceptRate;
-
- AcceptRateLimit(RateStatistic rateStatistic, int maxAcceptRate) {
- this.rateStatistic = rateStatistic;
- this.maxAcceptRate = maxAcceptRate;
- }
-
- @Override
- public Optional<String> isThresholdExceeded() {
- synchronized (monitor) {
- int acceptRate = rateStatistic.getRate();
- if (acceptRate > maxAcceptRate) {
- return Optional.of(String.format("Max accept rate exceeded: %d>%d", acceptRate, maxAcceptRate));
- }
- return Optional.empty();
- }
- }
-
- @Override
- public void onAccepting(SelectableChannel channel) {
- synchronized (monitor) {
- rateStatistic.record();
- }
- }
-
- @Override
- protected void doStop() {
- synchronized (monitor) {
- rateStatistic.reset();
- }
- }
- }
-
- /**
- * Note: implementation inspired by Jetty's {@link ConnectionLimit}.
- */
- private static class ConnectionLimitThreshold extends AbstractLifeCycle implements ResourceLimit {
- private final Object monitor = new Object();
- private final int maxConnections;
- private final Set<SelectableChannel> connectionsAccepting = new HashSet<>();
- private int connectionOpened;
-
- ConnectionLimitThreshold(int maxConnections) {
- this.maxConnections = maxConnections;
- }
-
- @Override
- public Optional<String> isThresholdExceeded() {
- synchronized (monitor) {
- int totalConnections = connectionOpened + connectionsAccepting.size();
- if (totalConnections > maxConnections) {
- return Optional.of(String.format("Max connection exceeded: %d>%d", totalConnections, maxConnections));
- }
- return Optional.empty();
- }
- }
-
- @Override
- public void onOpened(Connection connection) {
- synchronized (monitor) {
- connectionsAccepting.remove(connection.getEndPoint().getTransport());
- ++connectionOpened;
- }
- }
-
- @Override
- public void onClosed(Connection connection) {
- synchronized (monitor) {
- --connectionOpened;
- }
- }
-
- @Override
- public void onAccepting(SelectableChannel channel) {
- synchronized (monitor) {
- connectionsAccepting.add(channel);
- }
-
- }
-
- @Override
- public void onAcceptFailed(SelectableChannel channel, Throwable cause) {
- synchronized (monitor) {
- connectionsAccepting.remove(channel);
- }
- }
-
- @Override
- protected void doStop() {
- synchronized (monitor) {
- connectionsAccepting.clear();
- connectionOpened = 0;
- }
- }
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java
deleted file mode 100644
index d7ad12a5c64..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ConnectorFactory.java
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.Inject;
-import com.yahoo.jdisc.Metric;
-import com.yahoo.jdisc.http.ConnectorConfig;
-import com.yahoo.jdisc.http.ssl.SslContextFactoryProvider;
-import com.yahoo.security.tls.MixedMode;
-import com.yahoo.security.tls.TransportSecurityUtils;
-import org.eclipse.jetty.server.ConnectionFactory;
-import org.eclipse.jetty.server.DetectorConnectionFactory;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.ProxyConnectionFactory;
-import org.eclipse.jetty.server.SecureRequestCustomizer;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-import java.util.List;
-
-/**
- * @author Einar M R Rosenvinge
- * @author bjorncs
- */
-public class ConnectorFactory {
-
- private final ConnectorConfig connectorConfig;
- private final SslContextFactoryProvider sslContextFactoryProvider;
-
- @Inject
- public ConnectorFactory(ConnectorConfig connectorConfig,
- SslContextFactoryProvider sslContextFactoryProvider) {
- runtimeConnectorConfigValidation(connectorConfig);
- this.connectorConfig = connectorConfig;
- this.sslContextFactoryProvider = sslContextFactoryProvider;
- }
-
- // Perform extra connector config validation that can only be performed at runtime,
- // e.g. due to TLS configuration through environment variables.
- private static void runtimeConnectorConfigValidation(ConnectorConfig config) {
- validateProxyProtocolConfiguration(config);
- validateSecureRedirectConfig(config);
- }
-
- private static void validateProxyProtocolConfiguration(ConnectorConfig config) {
- ConnectorConfig.ProxyProtocol proxyProtocolConfig = config.proxyProtocol();
- if (proxyProtocolConfig.enabled()) {
- boolean tlsMixedModeEnabled = TransportSecurityUtils.getInsecureMixedMode() != MixedMode.DISABLED;
- if (!isSslEffectivelyEnabled(config) || tlsMixedModeEnabled) {
- throw new IllegalArgumentException("Proxy protocol can only be enabled if connector is effectively HTTPS only");
- }
- }
- }
-
- private static void validateSecureRedirectConfig(ConnectorConfig config) {
- if (config.secureRedirect().enabled() && isSslEffectivelyEnabled(config)) {
- throw new IllegalArgumentException("Secure redirect can only be enabled on connectors without HTTPS");
- }
- }
-
- public ConnectorConfig getConnectorConfig() {
- return connectorConfig;
- }
-
- public ServerConnector createConnector(final Metric metric, final Server server, JettyConnectionLogger connectionLogger) {
- ServerConnector connector = new JDiscServerConnector(
- connectorConfig, metric, server, connectionLogger, createConnectionFactories(metric).toArray(ConnectionFactory[]::new));
- connector.setPort(connectorConfig.listenPort());
- connector.setName(connectorConfig.name());
- connector.setAcceptQueueSize(connectorConfig.acceptQueueSize());
- connector.setReuseAddress(connectorConfig.reuseAddress());
- connector.setIdleTimeout((long)(connectorConfig.idleTimeout() * 1000.0));
- return connector;
- }
-
- private List<ConnectionFactory> createConnectionFactories(Metric metric) {
- HttpConnectionFactory httpFactory = newHttpConnectionFactory();
- if (!isSslEffectivelyEnabled(connectorConfig)) {
- return List.of(httpFactory);
- } else if (connectorConfig.ssl().enabled()) {
- return connectionFactoriesForHttps(metric, httpFactory);
- } else if (TransportSecurityUtils.isTransportSecurityEnabled()) {
- switch (TransportSecurityUtils.getInsecureMixedMode()) {
- case TLS_CLIENT_MIXED_SERVER:
- case PLAINTEXT_CLIENT_MIXED_SERVER:
- return List.of(new DetectorConnectionFactory(newSslConnectionFactory(metric, httpFactory)), httpFactory);
- case DISABLED:
- return connectionFactoriesForHttps(metric, httpFactory);
- default:
- throw new IllegalStateException();
- }
- } else {
- return List.of(httpFactory);
- }
- }
-
- private List<ConnectionFactory> connectionFactoriesForHttps(Metric metric, HttpConnectionFactory httpFactory) {
- ConnectorConfig.ProxyProtocol proxyProtocolConfig = connectorConfig.proxyProtocol();
- SslConnectionFactory sslFactory = newSslConnectionFactory(metric, httpFactory);
- if (proxyProtocolConfig.enabled()) {
- if (proxyProtocolConfig.mixedMode()) {
- return List.of(new DetectorConnectionFactory(sslFactory, new ProxyConnectionFactory(sslFactory.getProtocol())), sslFactory, httpFactory);
- } else {
- return List.of(new ProxyConnectionFactory(sslFactory.getProtocol()), sslFactory, httpFactory);
- }
- } else {
- return List.of(sslFactory, httpFactory);
- }
- }
-
- private HttpConnectionFactory newHttpConnectionFactory() {
- HttpConfiguration httpConfig = new HttpConfiguration();
- httpConfig.setSendDateHeader(true);
- httpConfig.setSendServerVersion(false);
- httpConfig.setSendXPoweredBy(false);
- httpConfig.setHeaderCacheSize(connectorConfig.headerCacheSize());
- httpConfig.setOutputBufferSize(connectorConfig.outputBufferSize());
- httpConfig.setRequestHeaderSize(connectorConfig.requestHeaderSize());
- httpConfig.setResponseHeaderSize(connectorConfig.responseHeaderSize());
- if (isSslEffectivelyEnabled(connectorConfig)) {
- httpConfig.addCustomizer(new SecureRequestCustomizer());
- }
- return new HttpConnectionFactory(httpConfig);
- }
-
- private SslConnectionFactory newSslConnectionFactory(Metric metric, HttpConnectionFactory httpFactory) {
- SslContextFactory ctxFactory = sslContextFactoryProvider.getInstance(connectorConfig.name(), connectorConfig.listenPort());
- SslConnectionFactory connectionFactory = new SslConnectionFactory(ctxFactory, httpFactory.getProtocol());
- connectionFactory.addBean(new SslHandshakeFailedListener(metric, connectorConfig.name(), connectorConfig.listenPort()));
- return connectionFactory;
- }
-
- private static boolean isSslEffectivelyEnabled(ConnectorConfig config) {
- return config.ssl().enabled()
- || (config.implicitTlsEnabled() && TransportSecurityUtils.isTransportSecurityEnabled());
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ErrorResponseContentCreator.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ErrorResponseContentCreator.java
deleted file mode 100644
index cd21dccde0e..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ErrorResponseContentCreator.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-import org.eclipse.jetty.util.ByteArrayISO8859Writer;
-import org.eclipse.jetty.util.StringUtil;
-
-import java.io.IOException;
-import java.util.Optional;
-
-/**
- * Creates HTML body having the status code, error message and request uri.
- * The body is constructed from a template that is inspired by the default Jetty template (see {@link org.eclipse.jetty.server.Response#sendError(int, String)}).
- * The content is written using the ISO-8859-1 charset.
- *
- * @author bjorncs
- */
-public class ErrorResponseContentCreator {
-
- private final ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(2048);
-
- public byte[] createErrorContent(String requestUri, int statusCode, Optional<String> message) {
- String sanitizedString = message.map(StringUtil::sanitizeXmlString).orElse("");
- String statusCodeString = Integer.toString(statusCode);
- writer.resetWriter();
- try {
- writer.write("<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\"/>\n<title>Error ");
- writer.write(statusCodeString);
- writer.write("</title>\n</head>\n<body>\n<h2>HTTP ERROR: ");
- writer.write(statusCodeString);
- writer.write("</h2>\n<p>Problem accessing ");
- writer.write(StringUtil.sanitizeXmlString(requestUri));
- writer.write(". Reason:\n<pre> ");
- writer.write(sanitizedString);
- writer.write("</pre></p>\n<hr/>\n</body>\n</html>\n");
- } catch (IOException e) {
- // IOException should not be thrown unless writer is constructed using byte[] parameter
- throw new RuntimeException(e);
- }
- return writer.getByteArray();
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ExceptionWrapper.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ExceptionWrapper.java
deleted file mode 100644
index ebc10482600..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ExceptionWrapper.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-/**
- * A wrapper to make exceptions leaking into Jetty easier to track. Jetty
- * swallows all information about where an exception was thrown, so this wrapper
- * ensures some extra information is automatically added to the contents of
- * getMessage().
- *
- * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a>
- */
-public class ExceptionWrapper extends RuntimeException {
- private final String message;
-
- /**
- * Update if serializable contents are added.
- */
- private static final long serialVersionUID = 1L;
-
- public ExceptionWrapper(Throwable t) {
- super(t);
- this.message = formatMessage(t);
- }
-
- // If calling methods from the constructor, it makes life easier if the
- // methods are static...
- private static String formatMessage(final Throwable t) {
- StringBuilder b = new StringBuilder();
- Throwable cause = t;
- while (cause != null) {
- StackTraceElement[] trace = cause.getStackTrace();
- String currentMsg = cause.getMessage();
-
- if (b.length() > 0) {
- b.append(": ");
- }
- b.append(t.getClass().getSimpleName()).append('(');
- if (currentMsg != null) {
- b.append('"').append(currentMsg).append('"');
- }
- b.append(')');
- if (trace.length > 0) {
- b.append(" at ").append(trace[0].getClassName()).append('(');
- if (trace[0].getFileName() != null) {
- b.append(trace[0].getFileName()).append(':')
- .append(trace[0].getLineNumber());
- }
- b.append(')');
- }
- cause = cause.getCause();
- }
- return b.toString();
- }
-
- @Override
- public String getMessage() {
- return message;
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterBindings.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterBindings.java
deleted file mode 100644
index 310f3c9a646..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterBindings.java
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.application.BindingRepository;
-import com.yahoo.jdisc.application.BindingSet;
-import com.yahoo.jdisc.http.filter.RequestFilter;
-import com.yahoo.jdisc.http.filter.ResponseFilter;
-
-import java.net.URI;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Optional;
-import java.util.TreeMap;
-
-/**
- * Resolves request/response filter (chain) from a {@link URI} instance.
- *
- * @author Oyvind Bakksjo
- * @author bjorncs
- */
-public class FilterBindings {
-
- private final Map<String, RequestFilter> requestFilters;
- private final Map<String, ResponseFilter> responseFilters;
- private final Map<Integer, String> defaultRequestFilters;
- private final Map<Integer, String> defaultResponseFilters;
- private final BindingSet<String> requestFilterBindings;
- private final BindingSet<String> responseFilterBindings;
-
- private FilterBindings(
- Map<String, RequestFilter> requestFilters,
- Map<String, ResponseFilter> responseFilters,
- Map<Integer, String> defaultRequestFilters,
- Map<Integer, String> defaultResponseFilters,
- BindingSet<String> requestFilterBindings,
- BindingSet<String> responseFilterBindings) {
- this.requestFilters = requestFilters;
- this.responseFilters = responseFilters;
- this.defaultRequestFilters = defaultRequestFilters;
- this.defaultResponseFilters = defaultResponseFilters;
- this.requestFilterBindings = requestFilterBindings;
- this.responseFilterBindings = responseFilterBindings;
- }
-
- public Optional<String> resolveRequestFilter(URI uri, int localPort) {
- String filterId = requestFilterBindings.resolve(uri);
- if (filterId != null) return Optional.of(filterId);
- return Optional.ofNullable(defaultRequestFilters.get(localPort));
- }
-
- public Optional<String> resolveResponseFilter(URI uri, int localPort) {
- String filterId = responseFilterBindings.resolve(uri);
- if (filterId != null) return Optional.of(filterId);
- return Optional.ofNullable(defaultResponseFilters.get(localPort));
- }
-
- public RequestFilter getRequestFilter(String filterId) { return requestFilters.get(filterId); }
-
- public ResponseFilter getResponseFilter(String filterId) { return responseFilters.get(filterId); }
-
- public Collection<String> requestFilterIds() { return requestFilters.keySet(); }
-
- public Collection<String> responseFilterIds() { return responseFilters.keySet(); }
-
- public Collection<RequestFilter> requestFilters() { return requestFilters.values(); }
-
- public Collection<ResponseFilter> responseFilters() { return responseFilters.values(); }
-
- public static class Builder {
- private final Map<String, RequestFilter> requestFilters = new TreeMap<>();
- private final Map<String, ResponseFilter> responseFilters = new TreeMap<>();
- private final Map<Integer, String> defaultRequestFilters = new TreeMap<>();
- private final Map<Integer, String> defaultResponseFilters = new TreeMap<>();
- private final BindingRepository<String> requestFilterBindings = new BindingRepository<>();
- private final BindingRepository<String> responseFilterBindings = new BindingRepository<>();
-
- public Builder() {}
-
- public Builder addRequestFilter(String id, RequestFilter filter) { requestFilters.put(id, filter); return this; }
-
- public Builder addResponseFilter(String id, ResponseFilter filter) { responseFilters.put(id, filter); return this; }
-
- public Builder addRequestFilterBinding(String id, String binding) { requestFilterBindings.bind(binding, id); return this; }
-
- public Builder addResponseFilterBinding(String id, String binding) { responseFilterBindings.bind(binding, id); return this; }
-
- public Builder setRequestFilterDefaultForPort(String id, int port) { defaultRequestFilters.put(port, id); return this; }
-
- public Builder setResponseFilterDefaultForPort(String id, int port) { defaultResponseFilters.put(port, id); return this; }
-
- public FilterBindings build() {
- return new FilterBindings(
- Collections.unmodifiableMap(requestFilters),
- Collections.unmodifiableMap(responseFilters),
- Collections.unmodifiableMap(defaultRequestFilters),
- Collections.unmodifiableMap(defaultResponseFilters),
- requestFilterBindings.activate(),
- responseFilterBindings.activate());
- }
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvoker.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvoker.java
deleted file mode 100644
index 0827ccdc39e..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvoker.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingPrintWriter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingPrintWriter.java
deleted file mode 100644
index 3ebc7bbc551..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingPrintWriter.java
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingServletOutputStream.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingServletOutputStream.java
deleted file mode 100644
index a605ccebfa7..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterInvokingServletOutputStream.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterResolver.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterResolver.java
deleted file mode 100644
index 1e2686aa184..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilterResolver.java
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright Verizon Media. 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.Metric;
-import com.yahoo.jdisc.NoopSharedResource;
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.handler.FastContentWriter;
-import com.yahoo.jdisc.handler.ResponseDispatch;
-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 javax.servlet.http.HttpServletRequest;
-import java.net.URI;
-import java.util.Map;
-import java.util.Optional;
-
-import static com.yahoo.jdisc.http.server.jetty.JDiscHttpServlet.getConnector;
-
-/**
- * Resolve request/response filter (chain) based on {@link FilterBindings}.
- *
- * @author bjorncs
- */
-class FilterResolver {
-
- private final FilterBindings bindings;
- private final Metric metric;
- private final boolean strictFiltering;
-
- FilterResolver(FilterBindings bindings, Metric metric, boolean strictFiltering) {
- this.bindings = bindings;
- this.metric = metric;
- this.strictFiltering = strictFiltering;
- }
-
- Optional<RequestFilter> resolveRequestFilter(HttpServletRequest servletRequest, URI jdiscUri) {
- Optional<String> maybeFilterId = bindings.resolveRequestFilter(jdiscUri, getConnector(servletRequest).listenPort());
- if (maybeFilterId.isPresent()) {
- metric.add(MetricDefinitions.FILTERING_REQUEST_HANDLED, 1L, createMetricContext(servletRequest, maybeFilterId.get()));
- servletRequest.setAttribute(ServletRequest.JDISC_REQUEST_CHAIN, maybeFilterId.get());
- } else if (!strictFiltering) {
- metric.add(MetricDefinitions.FILTERING_REQUEST_UNHANDLED, 1L, createMetricContext(servletRequest, null));
- } else {
- String syntheticFilterId = RejectingRequestFilter.SYNTHETIC_FILTER_CHAIN_ID;
- metric.add(MetricDefinitions.FILTERING_REQUEST_HANDLED, 1L, createMetricContext(servletRequest, syntheticFilterId));
- servletRequest.setAttribute(ServletRequest.JDISC_REQUEST_CHAIN, syntheticFilterId);
- return Optional.of(RejectingRequestFilter.INSTANCE);
- }
- return maybeFilterId.map(bindings::getRequestFilter);
- }
-
- Optional<ResponseFilter> resolveResponseFilter(HttpServletRequest servletRequest, URI jdiscUri) {
- Optional<String> maybeFilterId = bindings.resolveResponseFilter(jdiscUri, getConnector(servletRequest).listenPort());
- if (maybeFilterId.isPresent()) {
- metric.add(MetricDefinitions.FILTERING_RESPONSE_HANDLED, 1L, createMetricContext(servletRequest, maybeFilterId.get()));
- servletRequest.setAttribute(ServletRequest.JDISC_RESPONSE_CHAIN, maybeFilterId.get());
- } else {
- metric.add(MetricDefinitions.FILTERING_RESPONSE_UNHANDLED, 1L, createMetricContext(servletRequest, null));
- }
- return maybeFilterId.map(bindings::getResponseFilter);
- }
-
- private Metric.Context createMetricContext(HttpServletRequest request, String filterId) {
- Map<String, String> extraDimensions = filterId != null
- ? Map.of(MetricDefinitions.FILTER_CHAIN_ID_DIMENSION, filterId)
- : Map.of();
- return JDiscHttpServlet.getConnector(request).createRequestMetricContext(request, extraDimensions);
- }
-
- private static class RejectingRequestFilter extends NoopSharedResource implements RequestFilter {
-
- private static final RejectingRequestFilter INSTANCE = new RejectingRequestFilter();
- private static final String SYNTHETIC_FILTER_CHAIN_ID = "strict-reject";
-
- @Override
- public void filter(HttpRequest request, ResponseHandler handler) {
- Response response = new Response(Response.Status.FORBIDDEN);
- response.headers().add("Content-Type", "text/plain");
- try (FastContentWriter writer = ResponseDispatch.newInstance(response).connectFastWriter(handler)) {
- writer.write("Request did not match any request filter chain");
- }
- }
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilteringRequestHandler.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilteringRequestHandler.java
deleted file mode 100644
index de768f979a1..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FilteringRequestHandler.java
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.common.base.Preconditions;
-import com.yahoo.jdisc.Request;
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.handler.AbstractRequestHandler;
-import com.yahoo.jdisc.handler.BindingNotFoundException;
-import com.yahoo.jdisc.handler.CompletionHandler;
-import com.yahoo.jdisc.handler.ContentChannel;
-import com.yahoo.jdisc.handler.RequestDeniedException;
-import com.yahoo.jdisc.handler.RequestHandler;
-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 javax.servlet.http.HttpServletRequest;
-import java.nio.ByteBuffer;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Request handler that invokes request and response filters in addition to the bound request handler.
- *
- * @author Øyvind Bakksjø
- */
-class FilteringRequestHandler extends AbstractRequestHandler {
-
- private static final ContentChannel COMPLETING_CONTENT_CHANNEL = new ContentChannel() {
-
- @Override
- public void write(ByteBuffer buf, CompletionHandler handler) {
- CompletionHandlers.tryComplete(handler);
- }
-
- @Override
- public void close(CompletionHandler handler) {
- CompletionHandlers.tryComplete(handler);
- }
-
- };
-
- private final FilterResolver filterResolver;
- private final HttpServletRequest servletRequest;
-
- public FilteringRequestHandler(FilterResolver filterResolver, HttpServletRequest servletRequest) {
- this.filterResolver = filterResolver;
- this.servletRequest = servletRequest;
- }
-
- @Override
- public ContentChannel handleRequest(Request request, ResponseHandler originalResponseHandler) {
- Preconditions.checkArgument(request instanceof HttpRequest, "Expected HttpRequest, got " + request);
- Objects.requireNonNull(originalResponseHandler, "responseHandler");
-
- RequestFilter requestFilter = filterResolver.resolveRequestFilter(servletRequest, request.getUri())
- .orElse(null);
- ResponseFilter responseFilter = filterResolver.resolveResponseFilter(servletRequest, request.getUri())
- .orElse(null);
-
- // Not using request.connect() here - it adds logic for error handling that we'd rather leave to the framework.
- RequestHandler resolvedRequestHandler = request.container().resolveHandler(request);
-
- if (resolvedRequestHandler == null) {
- throw new BindingNotFoundException(request.getUri());
- }
-
- RequestHandler requestHandler = new ReferenceCountingRequestHandler(resolvedRequestHandler);
-
- ResponseHandler responseHandler;
- if (responseFilter != null) {
- responseHandler = new FilteringResponseHandler(originalResponseHandler, responseFilter, request);
- } else {
- responseHandler = originalResponseHandler;
- }
-
- if (requestFilter != null) {
- InterceptingResponseHandler interceptingResponseHandler = new InterceptingResponseHandler(responseHandler);
- requestFilter.filter(HttpRequest.class.cast(request), interceptingResponseHandler);
- if (interceptingResponseHandler.hasProducedResponse()) {
- return COMPLETING_CONTENT_CHANNEL;
- }
- }
-
- ContentChannel contentChannel = requestHandler.handleRequest(request, responseHandler);
- if (contentChannel == null) {
- throw new RequestDeniedException(request);
- }
- return contentChannel;
- }
-
- private static class FilteringResponseHandler implements ResponseHandler {
-
- private final ResponseHandler delegate;
- private final ResponseFilter responseFilter;
- private final Request request;
-
- public FilteringResponseHandler(ResponseHandler delegate, ResponseFilter responseFilter, Request request) {
- this.delegate = Objects.requireNonNull(delegate);
- this.responseFilter = Objects.requireNonNull(responseFilter);
- this.request = request;
- }
-
- @Override
- public ContentChannel handleResponse(Response response) {
- responseFilter.filter(response, request);
- return delegate.handleResponse(response);
- }
-
- }
-
- private static class InterceptingResponseHandler implements ResponseHandler {
-
- private final ResponseHandler delegate;
- private AtomicBoolean hasResponded = new AtomicBoolean(false);
-
- public InterceptingResponseHandler(ResponseHandler delegate) {
- this.delegate = Objects.requireNonNull(delegate);
- }
-
- @Override
- public ContentChannel handleResponse(Response response) {
- ContentChannel content = delegate.handleResponse(response);
- hasResponded.set(true);
- return content;
- }
-
- public boolean hasProducedResponse() {
- return hasResponded.get();
- }
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FormPostRequestHandler.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FormPostRequestHandler.java
deleted file mode 100644
index 38f84438526..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/FormPostRequestHandler.java
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.common.base.Preconditions;
-import com.yahoo.jdisc.Request;
-import com.yahoo.jdisc.ResourceReference;
-import com.yahoo.jdisc.handler.AbstractRequestHandler;
-import com.yahoo.jdisc.handler.CompletionHandler;
-import com.yahoo.jdisc.handler.ContentChannel;
-import com.yahoo.jdisc.handler.RequestHandler;
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.HttpRequest;
-
-import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.StandardCharsets;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-import static com.yahoo.jdisc.Response.Status.UNSUPPORTED_MEDIA_TYPE;
-import static com.yahoo.jdisc.http.server.jetty.CompletionHandlerUtils.NOOP_COMPLETION_HANDLER;
-
-/**
- * Request handler that wraps POST requests of application/x-www-form-urlencoded data.
- *
- * The wrapper defers invocation of the "real" request handler until it has read the request content (body),
- * parsed the form parameters and merged them into the request's parameters.
- *
- * @author bakksjo
- * $Id$
- */
-class FormPostRequestHandler extends AbstractRequestHandler implements ContentChannel {
-
- private final ByteArrayOutputStream accumulatedRequestContent = new ByteArrayOutputStream();
- private final RequestHandler delegateHandler;
- private final String contentCharsetName;
- private final boolean removeBody;
-
- private Charset contentCharset;
- private HttpRequest request;
- private ResourceReference requestReference;
- private ResponseHandler responseHandler;
-
- /**
- * @param delegateHandler the "real" request handler that this handler wraps
- * @param contentCharsetName name of the charset to use when interpreting the content data
- */
- public FormPostRequestHandler(
- final RequestHandler delegateHandler,
- final String contentCharsetName,
- final boolean removeBody) {
- this.delegateHandler = Objects.requireNonNull(delegateHandler);
- this.contentCharsetName = Objects.requireNonNull(contentCharsetName);
- this.removeBody = removeBody;
- }
-
- @Override
- public ContentChannel handleRequest(final Request request, final ResponseHandler responseHandler) {
- Preconditions.checkArgument(request instanceof HttpRequest, "Expected HttpRequest, got " + request);
- Objects.requireNonNull(responseHandler, "responseHandler");
-
- this.contentCharset = getCharsetByName(contentCharsetName);
- this.responseHandler = responseHandler;
- this.request = (HttpRequest) request;
- this.requestReference = request.refer();
-
- return this;
- }
-
- @Override
- public void write(final ByteBuffer buf, final CompletionHandler completionHandler) {
- assert buf.hasArray();
- accumulatedRequestContent.write(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining());
- completionHandler.completed();
- }
-
- @SuppressWarnings("try")
- @Override
- public void close(final CompletionHandler completionHandler) {
- try (final ResourceReference ref = requestReference) {
- final byte[] requestContentBytes = accumulatedRequestContent.toByteArray();
- final String content = new String(requestContentBytes, contentCharset);
- completionHandler.completed();
- final Map<String, List<String>> parameterMap = parseFormParameters(content);
- mergeParameters(parameterMap, request.parameters());
- final ContentChannel contentChannel = delegateHandler.handleRequest(request, responseHandler);
- if (contentChannel != null) {
- if (!removeBody) {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(requestContentBytes);
- contentChannel.write(byteBuffer, NOOP_COMPLETION_HANDLER);
- }
- contentChannel.close(NOOP_COMPLETION_HANDLER);
- }
- }
- }
-
- /**
- * Looks up a Charset given a charset name.
- *
- * @param charsetName the name of the charset to look up
- * @return a valid Charset for the charset name (never returns null)
- * @throws RequestException if the charset name is invalid or unsupported
- */
- private static Charset getCharsetByName(final String charsetName) throws RequestException {
- try {
- final Charset charset = Charset.forName(charsetName);
- if (charset == null) {
- throw new RequestException(UNSUPPORTED_MEDIA_TYPE, "Unsupported charset " + charsetName);
- }
- return charset;
- } catch (final IllegalCharsetNameException |UnsupportedCharsetException e) {
- throw new RequestException(UNSUPPORTED_MEDIA_TYPE, "Unsupported charset " + charsetName, e);
- }
- }
-
- /**
- * Parses application/x-www-form-urlencoded data into a map of parameters.
- *
- * @param formContent raw form content data (body)
- * @return map of decoded parameters
- */
- private static Map<String, List<String>> parseFormParameters(final String formContent) {
- if (formContent.isEmpty()) {
- return Collections.emptyMap();
- }
-
- final Map<String, List<String>> parameterMap = new HashMap<>();
- final String[] params = formContent.split("&");
- for (final String param : params) {
- final String[] parts = param.split("=");
- final String paramName = urlDecode(parts[0]);
- final String paramValue = parts.length > 1 ? urlDecode(parts[1]) : "";
- List<String> currentValues = parameterMap.get(paramName);
- if (currentValues == null) {
- currentValues = new LinkedList<>();
- parameterMap.put(paramName, currentValues);
- }
- currentValues.add(paramValue);
- }
- return parameterMap;
- }
-
- /**
- * Percent-decoding method that doesn't throw.
- *
- * @param encoded percent-encoded data
- * @return decoded data
- */
- private static String urlDecode(final String encoded) {
- try {
- // Regardless of the charset used to transfer the request body,
- // all percent-escaping of non-ascii characters should use UTF-8 code points.
- return URLDecoder.decode(encoded, StandardCharsets.UTF_8.name());
- } catch (final UnsupportedEncodingException e) {
- // Unfortunately, there is no URLDecoder.decode() method that takes a Charset, so we have to deal
- // with this exception.
- throw new IllegalStateException("Whoa, JVM doesn't support UTF-8 today.", e);
- }
- }
-
- /**
- * Merges source parameters into a destination map.
- *
- * @param source containing the parameters to copy into the destination
- * @param destination receiver of parameters, possibly already containing data
- */
- private static void mergeParameters(
- final Map<String,List<String>> source,
- final Map<String,List<String>> destination) {
- for (Map.Entry<String, List<String>> entry : source.entrySet()) {
- final List<String> destinationValues = destination.get(entry.getKey());
- if (destinationValues != null) {
- destinationValues.addAll(entry.getValue());
- } else {
- destination.put(entry.getKey(), entry.getValue());
- }
- }
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HealthCheckProxyHandler.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HealthCheckProxyHandler.java
deleted file mode 100644
index 0f7ce77e4cd..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HealthCheckProxyHandler.java
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright 2019 Oath Inc. 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.concurrent.DaemonThreadFactory;
-import com.yahoo.jdisc.http.ConnectorConfig;
-import com.yahoo.security.SslContextBuilder;
-import com.yahoo.security.tls.TransportSecurityOptions;
-import com.yahoo.security.tls.TransportSecurityUtils;
-import com.yahoo.security.tls.TrustAllX509TrustManager;
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.ssl.NoopHostnameVerifier;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.http.util.EntityUtils;
-import org.eclipse.jetty.server.DetectorConnectionFactory;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.server.handler.HandlerWrapper;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-import javax.net.ssl.SSLContext;
-import javax.servlet.AsyncContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.WriteListener;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.time.Duration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import static com.yahoo.jdisc.http.server.jetty.HttpServletRequestUtils.getConnectorLocalPort;
-
-/**
- * A handler that proxies status.html health checks
- *
- * @author bjorncs
- */
-class HealthCheckProxyHandler extends HandlerWrapper {
-
- private static final Logger log = Logger.getLogger(HealthCheckProxyHandler.class.getName());
-
- private static final String HEALTH_CHECK_PATH = "/status.html";
-
- private final Executor executor = Executors.newSingleThreadExecutor(new DaemonThreadFactory("health-check-proxy-client-"));
- private final Map<Integer, ProxyTarget> portToProxyTargetMapping;
-
- HealthCheckProxyHandler(List<JDiscServerConnector> connectors) {
- this.portToProxyTargetMapping = createPortToProxyTargetMapping(connectors);
- }
-
- private static Map<Integer, ProxyTarget> createPortToProxyTargetMapping(List<JDiscServerConnector> connectors) {
- var mapping = new HashMap<Integer, ProxyTarget>();
- for (JDiscServerConnector connector : connectors) {
- ConnectorConfig.HealthCheckProxy proxyConfig = connector.connectorConfig().healthCheckProxy();
- if (proxyConfig.enable()) {
- Duration targetTimeout = Duration.ofMillis((int) (proxyConfig.clientTimeout() * 1000));
- mapping.put(connector.listenPort(), createProxyTarget(proxyConfig.port(), targetTimeout, connectors));
- log.info(String.format("Port %1$d is configured as a health check proxy for port %2$d. " +
- "HTTP requests to '%3$s' on %1$d are proxied as HTTPS to %2$d.",
- connector.listenPort(), proxyConfig.port(), HEALTH_CHECK_PATH));
- }
- }
- return mapping;
- }
-
- private static ProxyTarget createProxyTarget(int targetPort, Duration targetTimeout, List<JDiscServerConnector> connectors) {
- JDiscServerConnector targetConnector = connectors.stream()
- .filter(connector -> connector.listenPort() == targetPort)
- .findAny()
- .orElseThrow(() -> new IllegalArgumentException("Could not find any connector with listen port " + targetPort));
- SslContextFactory.Server sslContextFactory =
- Optional.ofNullable(targetConnector.getConnectionFactory(SslConnectionFactory.class))
- .or(() -> Optional.ofNullable(targetConnector.getConnectionFactory(DetectorConnectionFactory.class))
- .map(detectorConnFactory -> detectorConnFactory.getBean(SslConnectionFactory.class)))
- .map(connFactory -> (SslContextFactory.Server) connFactory.getSslContextFactory())
- .orElseThrow(() -> new IllegalArgumentException("Health check proxy can only target https port"));
- return new ProxyTarget(targetPort, targetTimeout, sslContextFactory);
- }
-
- @Override
- public void handle(String target, Request request, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, ServletException {
- int localPort = getConnectorLocalPort(servletRequest);
- ProxyTarget proxyTarget = portToProxyTargetMapping.get(localPort);
- if (proxyTarget != null) {
- AsyncContext asyncContext = servletRequest.startAsync();
- ServletOutputStream out = servletResponse.getOutputStream();
- if (servletRequest.getRequestURI().equals(HEALTH_CHECK_PATH)) {
- executor.execute(new ProxyRequestTask(asyncContext, proxyTarget, servletResponse, out));
- } else {
- servletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
- asyncContext.complete();
- }
- request.setHandled(true);
- } else {
- _handler.handle(target, request, servletRequest, servletResponse);
- }
- }
-
- @Override
- protected void doStop() throws Exception {
- for (ProxyTarget target : portToProxyTargetMapping.values()) {
- target.close();
- }
- super.doStop();
- }
-
- private static class ProxyRequestTask implements Runnable {
-
- final AsyncContext asyncContext;
- final ProxyTarget target;
- final HttpServletResponse servletResponse;
- final ServletOutputStream output;
-
- ProxyRequestTask(AsyncContext asyncContext, ProxyTarget target, HttpServletResponse servletResponse, ServletOutputStream output) {
- this.asyncContext = asyncContext;
- this.target = target;
- this.servletResponse = servletResponse;
- this.output = output;
- }
-
- @Override
- public void run() {
- StatusResponse statusResponse = target.requestStatusHtml();
- servletResponse.setStatus(statusResponse.statusCode);
- if (statusResponse.contentType != null) {
- servletResponse.setHeader("Content-Type", statusResponse.contentType);
- }
- servletResponse.setHeader("Vespa-Health-Check-Proxy-Target", Integer.toString(target.port));
- output.setWriteListener(new WriteListener() {
- @Override
- public void onWritePossible() throws IOException {
- if (output.isReady()) {
- if (statusResponse.content != null) {
- output.write(statusResponse.content);
- }
- asyncContext.complete();
- }
- }
-
- @Override
- public void onError(Throwable t) {
- log.log(Level.FINE, t, () -> "Failed to write status response: " + t.getMessage());
- asyncContext.complete();
- }
- });
- }
- }
-
- private static class ProxyTarget implements AutoCloseable {
- final int port;
- final Duration timeout;
- final SslContextFactory.Server sslContextFactory;
- volatile CloseableHttpClient client;
- volatile StatusResponse lastResponse;
-
- ProxyTarget(int port, Duration timeout, SslContextFactory.Server sslContextFactory) {
- this.port = port;
- this.timeout = timeout;
- this.sslContextFactory = sslContextFactory;
- }
-
- StatusResponse requestStatusHtml() {
- StatusResponse response = lastResponse;
- if (response != null && !response.isExpired()) {
- return response;
- }
- return this.lastResponse = getStatusResponse();
- }
-
- private StatusResponse getStatusResponse() {
- try (CloseableHttpResponse clientResponse = client().execute(new HttpGet("https://localhost:" + port + HEALTH_CHECK_PATH))) {
- int statusCode = clientResponse.getStatusLine().getStatusCode();
- HttpEntity entity = clientResponse.getEntity();
- if (entity != null) {
- Header contentTypeHeader = entity.getContentType();
- String contentType = contentTypeHeader != null ? contentTypeHeader.getValue() : null;
- byte[] content = EntityUtils.toByteArray(entity);
- return new StatusResponse(statusCode, contentType, content);
- } else {
- return new StatusResponse(statusCode, null, null);
- }
- } catch (Exception e) {
- log.log(Level.FINE, e, () -> "Proxy request failed" + e.getMessage());
- return new StatusResponse(500, "text/plain", e.getMessage().getBytes());
- }
- }
-
- // Client construction must be delayed to ensure that the SslContextFactory is started before calling getSslContext().
- private CloseableHttpClient client() {
- if (client == null) {
- synchronized (this) {
- if (client == null) {
- int timeoutMillis = (int) timeout.toMillis();
- client = HttpClientBuilder.create()
- .disableAutomaticRetries()
- .setMaxConnPerRoute(4)
- .setSSLContext(getSslContext(sslContextFactory))
- .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) // Certificate may not match "localhost"
- .setUserTokenHandler(context -> null) // https://stackoverflow.com/a/42112034/1615280
- .setUserAgent("health-check-proxy-client")
- .setDefaultRequestConfig(
- RequestConfig.custom()
- .setConnectTimeout(timeoutMillis)
- .setConnectionRequestTimeout(timeoutMillis)
- .setSocketTimeout(timeoutMillis)
- .build())
- .build();
- }
- }
- }
- return client;
- }
-
- private SSLContext getSslContext(SslContextFactory.Server sslContextFactory) {
- // A client certificate is only required if the server connector's ssl context factory is configured with "need-auth".
- if (sslContextFactory.getNeedClientAuth()) {
- log.info(String.format("Port %d requires client certificate - client will provide its node certificate", port));
- // We should ideally specify the client certificate through connector config, but the model has currently no knowledge of node certificate location on disk.
- // Instead we assume that the server connector will accept its own node certificate. This will work for the current hosted use-case.
- // The Vespa TLS config will provide us the location of certificate and key.
- TransportSecurityOptions options = TransportSecurityUtils.getOptions()
- .orElseThrow(() ->
- new IllegalStateException("Vespa TLS configuration is required when using health check proxy to a port with client auth 'need'"));
- return new SslContextBuilder()
- .withKeyStore(options.getPrivateKeyFile().get(), options.getCertificatesFile().get())
- .withTrustManager(new TrustAllX509TrustManager())
- .build();
- } else {
- log.info(String.format(
- "Port %d does not require a client certificate - client will not provide a certificate", port));
- return new SslContextBuilder()
- .withTrustManager(new TrustAllX509TrustManager())
- .build();
- }
- }
-
- @Override
- public void close() throws IOException {
- synchronized (this) {
- if (client != null) {
- client.close();
- client = null;
- }
- }
- }
- }
-
- private static class StatusResponse {
- final long createdAt = System.nanoTime();
- final int statusCode;
- final String contentType;
- final byte[] content;
-
- StatusResponse(int statusCode, String contentType, byte[] content) {
- this.statusCode = statusCode;
- this.contentType = contentType;
- this.content = content;
- }
-
- boolean isExpired() { return System.nanoTime() - createdAt > Duration.ofSeconds(1).toNanos(); }
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java
deleted file mode 100644
index 05715b13d10..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestDispatch.java
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.Metric.Context;
-import com.yahoo.jdisc.References;
-import com.yahoo.jdisc.ResourceReference;
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.handler.BindingNotFoundException;
-import com.yahoo.jdisc.handler.ContentChannel;
-import com.yahoo.jdisc.handler.OverloadException;
-import com.yahoo.jdisc.handler.RequestHandler;
-import com.yahoo.jdisc.http.ConnectorConfig;
-import com.yahoo.jdisc.http.HttpHeaders;
-import com.yahoo.jdisc.http.HttpRequest;
-import org.eclipse.jetty.io.EofException;
-import org.eclipse.jetty.server.HttpConnection;
-import org.eclipse.jetty.server.Request;
-
-import javax.servlet.AsyncContext;
-import javax.servlet.ServletInputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.time.Instant;
-import java.util.Arrays;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import static com.yahoo.jdisc.http.HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED;
-import static com.yahoo.jdisc.http.server.jetty.HttpServletRequestUtils.getConnection;
-import static com.yahoo.jdisc.http.server.jetty.JDiscHttpServlet.getConnector;
-import static com.yahoo.yolean.Exceptions.throwUnchecked;
-
-/**
- * @author Simon Thoresen Hult
- * @author bjorncs
- */
-class HttpRequestDispatch {
-
- private static final Logger log = Logger.getLogger(HttpRequestDispatch.class.getName());
-
- private final static String CHARSET_ANNOTATION = ";charset=";
-
- private final JDiscContext jDiscContext;
- private final AsyncContext async;
- private final Request jettyRequest;
-
- private final ServletResponseController servletResponseController;
- private final RequestHandler requestHandler;
- private final RequestMetricReporter metricReporter;
-
- public HttpRequestDispatch(JDiscContext jDiscContext,
- AccessLogEntry accessLogEntry,
- Context metricContext,
- HttpServletRequest servletRequest,
- HttpServletResponse servletResponse) throws IOException {
- this.jDiscContext = jDiscContext;
-
- requestHandler = newRequestHandler(jDiscContext, accessLogEntry, servletRequest);
-
- this.jettyRequest = (Request) servletRequest;
- this.metricReporter = new RequestMetricReporter(jDiscContext.metric, metricContext, jettyRequest.getTimeStamp());
- this.servletResponseController = new ServletResponseController(servletRequest,
- servletResponse,
- jDiscContext.janitor,
- metricReporter,
- jDiscContext.developerMode());
- markConnectionAsNonPersistentIfThresholdReached(servletRequest);
- this.async = servletRequest.startAsync();
- async.setTimeout(0);
- metricReporter.uriLength(jettyRequest.getOriginalURI().length());
- }
-
- public void dispatch() throws IOException {
- ServletRequestReader servletRequestReader;
- try {
- servletRequestReader = handleRequest();
- } catch (Throwable throwable) {
- servletResponseController.trySendError(throwable);
- servletResponseController.finishedFuture().whenComplete((result, exception) ->
- completeRequestCallback.accept(null, throwable));
- return;
- }
-
- try {
- onError(servletRequestReader.finishedFuture, servletResponseController::trySendError);
- onError(servletResponseController.finishedFuture(), servletRequestReader::onError);
- CompletableFuture.allOf(servletRequestReader.finishedFuture, servletResponseController.finishedFuture())
- .whenComplete(completeRequestCallback);
- } catch (Throwable throwable) {
- log.log(Level.WARNING, "Failed registering finished listeners.", throwable);
- }
- }
-
- private final BiConsumer<Void, Throwable> completeRequestCallback;
- {
- AtomicBoolean completeRequestCalled = new AtomicBoolean(false);
- HttpRequestDispatch parent = this; //used to avoid binding uninitialized variables
-
- completeRequestCallback = (result, error) -> {
- boolean alreadyCalled = completeRequestCalled.getAndSet(true);
- if (alreadyCalled) {
- AssertionError e = new AssertionError("completeRequest called more than once");
- log.log(Level.WARNING, "Assertion failed.", e);
- throw e;
- }
-
- boolean reportedError = false;
-
- if (error != null) {
- if (isErrorOfType(error, EofException.class, IOException.class)) {
- log.log(Level.FINE,
- error,
- () -> "Network connection was unexpectedly terminated: " + parent.jettyRequest.getRequestURI());
- parent.metricReporter.prematurelyClosed();
- } else if (!isErrorOfType(error, OverloadException.class, BindingNotFoundException.class, RequestException.class)) {
- log.log(Level.WARNING, "Request failed: " + parent.jettyRequest.getRequestURI(), error);
- }
- reportedError = true;
- parent.metricReporter.failedResponse();
- } else {
- parent.metricReporter.successfulResponse();
- }
-
- try {
- parent.async.complete();
- log.finest(() -> "Request completed successfully: " + parent.jettyRequest.getRequestURI());
- } catch (Throwable throwable) {
- Level level = reportedError ? Level.FINE: Level.WARNING;
- log.log(level, "Async.complete failed", throwable);
- }
- };
- }
-
- private static void markConnectionAsNonPersistentIfThresholdReached(HttpServletRequest request) {
- ConnectorConfig connectorConfig = getConnector(request).connectorConfig();
- int maxRequestsPerConnection = connectorConfig.maxRequestsPerConnection();
- if (maxRequestsPerConnection > 0) {
- HttpConnection connection = getConnection(request);
- if (connection.getMessagesIn() >= maxRequestsPerConnection) {
- connection.getGenerator().setPersistent(false);
- }
- }
- double maxConnectionLifeInSeconds = connectorConfig.maxConnectionLife();
- if (maxConnectionLifeInSeconds > 0) {
- HttpConnection connection = getConnection(request);
- Instant expireAt = Instant.ofEpochMilli((long)(connection.getCreatedTimeStamp() + maxConnectionLifeInSeconds * 1000));
- if (Instant.now().isAfter(expireAt)) {
- connection.getGenerator().setPersistent(false);
- }
- }
- }
-
- @SafeVarargs
- @SuppressWarnings("varargs")
- private static boolean isErrorOfType(Throwable throwable, Class<? extends Throwable>... handledTypes) {
- return Arrays.stream(handledTypes)
- .anyMatch(
- exceptionType -> exceptionType.isInstance(throwable)
- || throwable instanceof CompletionException && exceptionType.isInstance(throwable.getCause()));
- }
-
- @SuppressWarnings("try")
- private ServletRequestReader handleRequest() throws IOException {
- HttpRequest jdiscRequest = HttpRequestFactory.newJDiscRequest(jDiscContext.container, jettyRequest);
- ContentChannel requestContentChannel;
-
- try (ResourceReference ref = References.fromResource(jdiscRequest)) {
- HttpRequestFactory.copyHeaders(jettyRequest, jdiscRequest);
- requestContentChannel = requestHandler.handleRequest(jdiscRequest, servletResponseController.responseHandler);
- }
-
- ServletInputStream servletInputStream = jettyRequest.getInputStream();
-
- ServletRequestReader servletRequestReader = new ServletRequestReader(servletInputStream,
- requestContentChannel,
- jDiscContext.janitor,
- metricReporter);
-
- servletInputStream.setReadListener(servletRequestReader);
- return servletRequestReader;
- }
-
- private static void onError(CompletableFuture<?> future, Consumer<Throwable> errorHandler) {
- future.whenComplete((result, exception) -> {
- if (exception != null) {
- errorHandler.accept(exception);
- }
- });
- }
-
- ContentChannel handleRequestFilterResponse(Response response) {
- try {
- jettyRequest.getInputStream().close();
- ContentChannel responseContentChannel = servletResponseController.responseHandler.handleResponse(response);
- servletResponseController.finishedFuture().whenComplete(completeRequestCallback);
- return responseContentChannel;
- } catch (IOException e) {
- throw throwUnchecked(e);
- }
- }
-
-
- private static RequestHandler newRequestHandler(JDiscContext context,
- AccessLogEntry accessLogEntry,
- HttpServletRequest servletRequest) {
- RequestHandler requestHandler = wrapHandlerIfFormPost(
- new FilteringRequestHandler(context.filterResolver, servletRequest),
- servletRequest, context.serverConfig.removeRawPostBodyForWwwUrlEncodedPost());
-
- return new AccessLoggingRequestHandler(requestHandler, accessLogEntry);
- }
-
- private static RequestHandler wrapHandlerIfFormPost(RequestHandler requestHandler,
- HttpServletRequest servletRequest,
- boolean removeBodyForFormPost) {
- if (!servletRequest.getMethod().equals("POST")) {
- return requestHandler;
- }
- String contentType = servletRequest.getHeader(HttpHeaders.Names.CONTENT_TYPE);
- if (contentType == null) {
- return requestHandler;
- }
- if (!contentType.startsWith(APPLICATION_X_WWW_FORM_URLENCODED)) {
- return requestHandler;
- }
- return new FormPostRequestHandler(requestHandler, getCharsetName(contentType), removeBodyForFormPost);
- }
-
- private static String getCharsetName(String contentType) {
- if (!contentType.startsWith(CHARSET_ANNOTATION, APPLICATION_X_WWW_FORM_URLENCODED.length())) {
- return StandardCharsets.UTF_8.name();
- }
- return contentType.substring(APPLICATION_X_WWW_FORM_URLENCODED.length() + CHARSET_ANNOTATION.length());
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactory.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactory.java
deleted file mode 100644
index e8d37cfadb5..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactory.java
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.http.HttpRequest;
-import com.yahoo.jdisc.http.servlet.ServletRequest;
-import com.yahoo.jdisc.service.CurrentContainer;
-import org.eclipse.jetty.util.Utf8Appendable;
-
-import javax.servlet.http.HttpServletRequest;
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.security.cert.X509Certificate;
-import java.util.Enumeration;
-
-import static com.yahoo.jdisc.Response.Status.BAD_REQUEST;
-import static com.yahoo.jdisc.http.server.jetty.HttpServletRequestUtils.getConnection;
-import static com.yahoo.jdisc.http.server.jetty.HttpServletRequestUtils.getConnectorLocalPort;
-
-/**
- * @author Simon Thoresen Hult
- * @author bjorncs
- */
-class HttpRequestFactory {
-
- public static HttpRequest newJDiscRequest(CurrentContainer container, HttpServletRequest servletRequest) {
- try {
- HttpRequest httpRequest = HttpRequest.newServerRequest(
- container,
- getUri(servletRequest),
- HttpRequest.Method.valueOf(servletRequest.getMethod()),
- HttpRequest.Version.fromString(servletRequest.getProtocol()),
- new InetSocketAddress(servletRequest.getRemoteAddr(), servletRequest.getRemotePort()),
- getConnection(servletRequest).getCreatedTimeStamp());
- httpRequest.context().put(ServletRequest.JDISC_REQUEST_X509CERT, getCertChain(servletRequest));
- return httpRequest;
- } catch (Utf8Appendable.NotUtf8Exception e) {
- throw createBadQueryException(e);
- }
- }
-
- // Implementation based on org.eclipse.jetty.server.Request.getRequestURL(), but with the connector's local port instead
- public static URI getUri(HttpServletRequest servletRequest) {
- try {
- String scheme = servletRequest.getScheme();
- String host = servletRequest.getServerName();
- int port = getConnectorLocalPort(servletRequest);
- String path = servletRequest.getRequestURI();
- String query = servletRequest.getQueryString();
-
- URI uri = URI.create(scheme + "://" +
- host + ":" + port +
- (path != null ? path : "") +
- (query != null ? "?" + query : ""));
-
- validateSchemeHostPort(scheme, host, port, uri);
- return uri;
- }
- catch (IllegalArgumentException e) {
- throw createBadQueryException(e);
- }
- }
-
- private static void validateSchemeHostPort(String scheme, String host, int port, URI uri) {
- if ( ! scheme.equals(uri.getScheme()))
- throw new IllegalArgumentException("Bad scheme: " + scheme);
-
- if ( ! host.equals(uri.getHost()) || port != uri.getPort())
- throw new IllegalArgumentException("Bad authority: " + uri.getRawAuthority() + " != " + host + ":" + port);
- }
-
- private static RequestException createBadQueryException(IllegalArgumentException e) {
- return new RequestException(BAD_REQUEST, "URL violates RFC 2396: " + e.getMessage(), e);
- }
-
- public static void copyHeaders(HttpServletRequest from, HttpRequest to) {
- for (Enumeration<String> it = from.getHeaderNames(); it.hasMoreElements(); ) {
- String key = it.nextElement();
- for (Enumeration<String> value = from.getHeaders(key); value.hasMoreElements(); ) {
- to.headers().add(key, value.nextElement());
- }
- }
- }
-
- private static X509Certificate[] getCertChain(HttpServletRequest servletRequest) {
- return (X509Certificate[]) servletRequest.getAttribute("javax.servlet.request.X509Certificate");
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpResponseStatisticsCollector.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpResponseStatisticsCollector.java
deleted file mode 100644
index 82c445c7ca9..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpResponseStatisticsCollector.java
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright 2018 Yahoo Holdings. 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.http.HttpRequest;
-import org.eclipse.jetty.http.HttpStatus;
-import org.eclipse.jetty.server.AsyncContextEvent;
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.HttpChannelState;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.HandlerWrapper;
-import org.eclipse.jetty.util.FutureCallback;
-import org.eclipse.jetty.util.component.Graceful;
-
-import javax.servlet.AsyncEvent;
-import javax.servlet.AsyncListener;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.atomic.LongAdder;
-
-/**
- * HttpResponseStatisticsCollector collects statistics about HTTP response types aggregated by category
- * (1xx, 2xx, etc). It is similar to {@link org.eclipse.jetty.server.handler.StatisticsHandler}
- * with the distinction that this class collects response type statistics grouped
- * by HTTP method and only collects the numbers that are reported as metrics from Vespa.
- *
- * @author ollivir
- */
-public class HttpResponseStatisticsCollector extends HandlerWrapper implements Graceful {
-
- static final String requestTypeAttribute = "requestType";
-
- private final AtomicReference<FutureCallback> shutdown = new AtomicReference<>();
- private final List<String> monitoringHandlerPaths;
- private final List<String> searchHandlerPaths;
-
- public enum HttpMethod {
- GET, PATCH, POST, PUT, DELETE, OPTIONS, HEAD, OTHER
- }
-
- public enum HttpScheme {
- HTTP, HTTPS, OTHER
- }
-
- private static final String[] HTTP_RESPONSE_GROUPS = {
- MetricDefinitions.RESPONSES_1XX,
- MetricDefinitions.RESPONSES_2XX,
- MetricDefinitions.RESPONSES_3XX,
- MetricDefinitions.RESPONSES_4XX,
- MetricDefinitions.RESPONSES_5XX,
- MetricDefinitions.RESPONSES_401,
- MetricDefinitions.RESPONSES_403
- };
-
- private final AtomicLong inFlight = new AtomicLong();
- private final LongAdder[][][][] statistics;
-
- public HttpResponseStatisticsCollector(List<String> monitoringHandlerPaths, List<String> searchHandlerPaths) {
- this.monitoringHandlerPaths = monitoringHandlerPaths;
- this.searchHandlerPaths = searchHandlerPaths;
- statistics = new LongAdder[HttpScheme.values().length][HttpMethod.values().length][][];
- for (int scheme = 0; scheme < HttpScheme.values().length; ++scheme) {
- for (int method = 0; method < HttpMethod.values().length; method++) {
- statistics[scheme][method] = new LongAdder[HTTP_RESPONSE_GROUPS.length][];
- for (int group = 0; group < HTTP_RESPONSE_GROUPS.length; group++) {
- statistics[scheme][method][group] = new LongAdder[HttpRequest.RequestType.values().length];
- for (int requestType = 0; requestType < HttpRequest.RequestType.values().length; requestType++) {
- statistics[scheme][method][group][requestType] = new LongAdder();
- }
- }
- }
- }
- }
-
- private final AsyncListener completionWatcher = new AsyncListener() {
-
- @Override
- public void onTimeout(AsyncEvent event) { }
-
- @Override
- public void onStartAsync(AsyncEvent event) {
- event.getAsyncContext().addListener(this);
- }
-
- @Override
- public void onError(AsyncEvent event) { }
-
- @Override
- public void onComplete(AsyncEvent event) throws IOException {
- HttpChannelState state = ((AsyncContextEvent) event).getHttpChannelState();
- Request request = state.getBaseRequest();
-
- observeEndOfRequest(request, null);
- }
- };
-
- @Override
- public void handle(String path, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
- throws IOException, ServletException {
- inFlight.incrementAndGet();
-
- try {
- Handler handler = getHandler();
- if (handler != null && shutdown.get() == null && isStarted()) {
- handler.handle(path, baseRequest, request, response);
- } else if ( ! baseRequest.isHandled()) {
- baseRequest.setHandled(true);
- response.sendError(HttpStatus.SERVICE_UNAVAILABLE_503);
- }
- } finally {
- HttpChannelState state = baseRequest.getHttpChannelState();
- if (state.isSuspended()) {
- if (state.isInitial()) {
- state.addListener(completionWatcher);
- }
- } else if (state.isInitial()) {
- observeEndOfRequest(baseRequest, response);
- }
- }
- }
-
- private void observeEndOfRequest(Request request, HttpServletResponse flushableResponse) throws IOException {
- int group = groupIndex(request);
- if (group >= 0) {
- HttpScheme scheme = getScheme(request);
- HttpMethod method = getMethod(request);
- HttpRequest.RequestType requestType = getRequestType(request);
-
- statistics[scheme.ordinal()][method.ordinal()][group][requestType.ordinal()].increment();
- if (group == 5 || group == 6) { // if 401/403, also increment 4xx
- statistics[scheme.ordinal()][method.ordinal()][3][requestType.ordinal()].increment();
- }
- }
-
- long live = inFlight.decrementAndGet();
- FutureCallback shutdownCb = shutdown.get();
- if (shutdownCb != null) {
- if (flushableResponse != null) {
- flushableResponse.flushBuffer();
- }
- if (live == 0) {
- shutdownCb.succeeded();
- }
- }
- }
-
- private int groupIndex(Request request) {
- int index = request.getResponse().getStatus();
- if (index == 401) {
- return 5;
- }
- if (index == 403) {
- return 6;
- }
-
- index = index / 100 - 1; // 1xx = 0, 2xx = 1 etc.
- if (index < 0 || index >= statistics[0].length) {
- return -1;
- } else {
- return index;
- }
- }
-
- private HttpScheme getScheme(Request request) {
- switch (request.getScheme()) {
- case "http":
- return HttpScheme.HTTP;
- case "https":
- return HttpScheme.HTTPS;
- default:
- return HttpScheme.OTHER;
- }
- }
-
- private HttpMethod getMethod(Request request) {
- switch (request.getMethod()) {
- case "GET":
- return HttpMethod.GET;
- case "PATCH":
- return HttpMethod.PATCH;
- case "POST":
- return HttpMethod.POST;
- case "PUT":
- return HttpMethod.PUT;
- case "DELETE":
- return HttpMethod.DELETE;
- case "OPTIONS":
- return HttpMethod.OPTIONS;
- case "HEAD":
- return HttpMethod.HEAD;
- default:
- return HttpMethod.OTHER;
- }
- }
-
- private HttpRequest.RequestType getRequestType(Request request) {
- HttpRequest.RequestType requestType = (HttpRequest.RequestType)request.getAttribute(requestTypeAttribute);
- if (requestType != null) return requestType;
-
- // Deduce from path and method:
- String path = request.getRequestURI();
- for (String monitoringHandlerPath : monitoringHandlerPaths) {
- if (path.startsWith(monitoringHandlerPath)) return HttpRequest.RequestType.MONITORING;
- }
- for (String searchHandlerPath : searchHandlerPaths) {
- if (path.startsWith(searchHandlerPath)) return HttpRequest.RequestType.READ;
- }
- if ("GET".equals(request.getMethod())) {
- return HttpRequest.RequestType.READ;
- } else {
- return HttpRequest.RequestType.WRITE;
- }
- }
-
- public List<StatisticsEntry> takeStatistics() {
- var ret = new ArrayList<StatisticsEntry>();
- for (HttpScheme scheme : HttpScheme.values()) {
- int schemeIndex = scheme.ordinal();
- for (HttpMethod method : HttpMethod.values()) {
- int methodIndex = method.ordinal();
- for (int group = 0; group < HTTP_RESPONSE_GROUPS.length; group++) {
- for (HttpRequest.RequestType type : HttpRequest.RequestType.values()) {
- long value = statistics[schemeIndex][methodIndex][group][type.ordinal()].sumThenReset();
- if (value > 0) {
- ret.add(new StatisticsEntry(scheme.name().toLowerCase(), method.name(), HTTP_RESPONSE_GROUPS[group], type.name().toLowerCase(), value));
- }
- }
- }
- }
- }
- return ret;
- }
-
- @Override
- protected void doStart() throws Exception {
- shutdown.set(null);
- super.doStart();
- }
-
- @Override
- protected void doStop() throws Exception {
- super.doStop();
- FutureCallback shutdownCb = shutdown.get();
- if ( ! shutdownCb.isDone()) {
- shutdownCb.failed(new TimeoutException());
- }
- }
-
- @Override
- public Future<Void> shutdown() {
- FutureCallback shutdownCb = new FutureCallback(false);
- shutdown.compareAndSet(null, shutdownCb);
- shutdownCb = shutdown.get();
- if (inFlight.get() == 0) {
- shutdownCb.succeeded();
- }
- return shutdownCb;
- }
-
- @Override
- public boolean isShutdown() {
- FutureCallback futureCallback = shutdown.get();
- return futureCallback != null && futureCallback.isDone();
- }
-
- public static class StatisticsEntry {
-
- public final String scheme;
- public final String method;
- public final String name;
- public final String requestType;
- public final long value;
-
- public StatisticsEntry(String scheme, String method, String name, String requestType, long value) {
- this.scheme = scheme;
- this.method = method;
- this.name = name;
- this.requestType = requestType;
- this.value = value;
- }
-
- @Override
- public String toString() {
- return "scheme: " + scheme +
- ", method: " + method +
- ", name: " + name +
- ", requestType: " + requestType +
- ", value: " + value;
- }
-
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpServletRequestUtils.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpServletRequestUtils.java
deleted file mode 100644
index e7b9f459d2e..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/HttpServletRequestUtils.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-import org.eclipse.jetty.server.HttpConnection;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * @author bjorncs
- */
-public class HttpServletRequestUtils {
- private HttpServletRequestUtils() {}
-
- public static HttpConnection getConnection(HttpServletRequest request) {
- return (HttpConnection)request.getAttribute("org.eclipse.jetty.server.HttpConnection");
- }
-
- /**
- * Note: {@link HttpServletRequest#getLocalPort()} may return the local port of the load balancer / reverse proxy if proxy-protocol is enabled.
- * @return the actual local port of the underlying Jetty connector
- */
- public static int getConnectorLocalPort(HttpServletRequest request) {
- JDiscServerConnector connector = (JDiscServerConnector) getConnection(request).getConnector();
- int actualLocalPort = connector.getLocalPort();
- int localPortIfConnectorUnopened = -1;
- int localPortIfConnectorClosed = -2;
- if (actualLocalPort == localPortIfConnectorUnopened || actualLocalPort == localPortIfConnectorClosed) {
- int configuredLocalPort = connector.listenPort();
- int localPortEphemeralPort = 0;
- if (configuredLocalPort == localPortEphemeralPort) {
- throw new IllegalStateException("Unable to determine connector's listen port");
- }
- return configuredLocalPort;
- }
- return actualLocalPort;
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscContext.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscContext.java
deleted file mode 100644
index b37a7352dc6..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscContext.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.Metric;
-import com.yahoo.jdisc.http.ServerConfig;
-import com.yahoo.jdisc.service.CurrentContainer;
-
-import java.util.concurrent.Executor;
-
-public class JDiscContext {
- final FilterResolver filterResolver;
- final CurrentContainer container;
- final Executor janitor;
- final Metric metric;
- final ServerConfig serverConfig;
-
- public JDiscContext(FilterBindings filterBindings,
- CurrentContainer container,
- Executor janitor,
- Metric metric,
- ServerConfig serverConfig) {
-
- this.filterResolver = new FilterResolver(filterBindings, metric, serverConfig.strictFiltering());
- this.container = container;
- this.janitor = janitor;
- this.metric = metric;
- this.serverConfig = serverConfig;
- }
-
- public boolean developerMode() {
- return serverConfig.developerMode();
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscFilterInvokerFilter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscFilterInvokerFilter.java
deleted file mode 100644
index a89c115a1c2..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscFilterInvokerFilter.java
+++ /dev/null
@@ -1,294 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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 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.JDiscHttpServlet.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(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(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.handleRequestFilterResponse(jdiscResponse);
- };
- }
-
- private HttpRequestDispatch createRequestDispatch(HttpServletRequest request, HttpServletResponse response) {
- try {
- final AccessLogEntry accessLogEntry = null; // Not used in this context.
- return new HttpRequestDispatch(jDiscContext,
- accessLogEntry,
- getConnector(request).createRequestMetricContext(request, Map.of()),
- request, response);
- } catch (IOException e) {
- throw throwUnchecked(e);
- }
- }
-
- @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/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java
deleted file mode 100644
index 41a1ffc2709..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServlet.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.Metric;
-import com.yahoo.jdisc.handler.OverloadException;
-import com.yahoo.jdisc.http.HttpRequest.Method;
-
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static com.yahoo.jdisc.http.server.jetty.HttpServletRequestUtils.getConnection;
-
-/**
- * @author Simon Thoresen Hult
- * @author bjorncs
- */
-@WebServlet(asyncSupported = true, description = "Bridge between Servlet and JDisc APIs")
-class JDiscHttpServlet extends HttpServlet {
-
- public static final String ATTRIBUTE_NAME_ACCESS_LOG_ENTRY = JDiscHttpServlet.class.getName() + "_access-log-entry";
-
- private final static Logger log = Logger.getLogger(JDiscHttpServlet.class.getName());
- private final JDiscContext context;
-
- private static final Set<String> servletSupportedMethods =
- Stream.of(Method.OPTIONS, Method.GET, Method.HEAD, Method.POST, Method.PUT, Method.DELETE, Method.TRACE)
- .map(Method::name)
- .collect(Collectors.toSet());
-
- public JDiscHttpServlet(JDiscContext context) {
- this.context = context;
- }
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
- dispatchHttpRequest(request, response);
- }
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
- dispatchHttpRequest(request, response);
- }
-
- @Override
- protected void doHead(HttpServletRequest request, HttpServletResponse response) throws IOException {
- dispatchHttpRequest(request, response);
- }
-
- @Override
- protected void doPut(HttpServletRequest request, HttpServletResponse response) throws IOException {
- dispatchHttpRequest(request, response);
- }
-
- @Override
- protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException {
- dispatchHttpRequest(request, response);
- }
-
- @Override
- protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws IOException {
- dispatchHttpRequest(request, response);
- }
-
- @Override
- protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws IOException {
- dispatchHttpRequest(request, response);
- }
-
- /**
- * Override to set connector attribute before the request becomes an upgrade request in the web socket case.
- * (After the upgrade, the HttpConnection is no longer available.)
- */
- @Override
- protected void service(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- request.setAttribute(JDiscServerConnector.REQUEST_ATTRIBUTE, getConnector(request));
-
- Metric.Context metricContext = getMetricContext(request);
- context.metric.add(MetricDefinitions.NUM_REQUESTS, 1, metricContext);
- context.metric.add(MetricDefinitions.JDISC_HTTP_REQUESTS, 1, metricContext);
-
- String method = request.getMethod().toUpperCase();
- if (servletSupportedMethods.contains(method)) {
- super.service(request, response);
- } else if (method.equals(Method.PATCH.name())) {
- // PATCH method is not handled by the Servlet spec
- dispatchHttpRequest(request, response);
- } else {
- // Divergence from HTTP / Servlet spec: JDisc returns 405 for both unknown and known (but unsupported) methods.
- response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
- }
- }
-
- static JDiscServerConnector getConnector(HttpServletRequest request) {
- return (JDiscServerConnector)getConnection(request).getConnector();
- }
-
- private void dispatchHttpRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
- AccessLogEntry accessLogEntry = new AccessLogEntry();
- request.setAttribute(ATTRIBUTE_NAME_ACCESS_LOG_ENTRY, accessLogEntry);
- try {
- switch (request.getDispatcherType()) {
- case REQUEST:
- new HttpRequestDispatch(context, accessLogEntry, getMetricContext(request), request, response).dispatch();
- break;
- default:
- if (log.isLoggable(Level.INFO)) {
- log.info("Unexpected " + request.getDispatcherType() + "; " + formatAttributes(request));
- }
- break;
- }
- } catch (OverloadException e) {
- // nop
- } catch (RuntimeException e) {
- throw new ExceptionWrapper(e);
- }
- }
-
- private static Metric.Context getMetricContext(HttpServletRequest request) {
- return JDiscServerConnector.fromRequest(request).createRequestMetricContext(request, Map.of());
- }
-
- private static String formatAttributes(final HttpServletRequest request) {
- StringBuilder out = new StringBuilder();
- out.append("attributes = {");
- for (Enumeration<String> names = request.getAttributeNames(); names.hasMoreElements(); ) {
- String name = names.nextElement();
- out.append(" '").append(name).append("' = '").append(request.getAttribute(name)).append("'");
- if (names.hasMoreElements()) {
- out.append(",");
- }
- }
- out.append(" }");
- return out.toString();
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
deleted file mode 100644
index 99d0c5c8d8c..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.Metric;
-import com.yahoo.jdisc.http.ConnectorConfig;
-import org.eclipse.jetty.io.ConnectionStatistics;
-import org.eclipse.jetty.server.ConnectionFactory;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-
-/**
- * @author bjorncs
- */
-class JDiscServerConnector extends ServerConnector {
-
- public static final String REQUEST_ATTRIBUTE = JDiscServerConnector.class.getName();
- private final Metric.Context metricCtx;
- private final ConnectionStatistics statistics;
- private final ConnectorConfig config;
- private final boolean tcpKeepAlive;
- private final boolean tcpNoDelay;
- private final Metric metric;
- private final String connectorName;
- private final int listenPort;
-
- JDiscServerConnector(ConnectorConfig config, Metric metric, Server server, JettyConnectionLogger connectionLogger, ConnectionFactory... factories) {
- super(server, factories);
- this.config = config;
- this.tcpKeepAlive = config.tcpKeepAliveEnabled();
- this.tcpNoDelay = config.tcpNoDelay();
- this.metric = metric;
- this.connectorName = config.name();
- this.listenPort = config.listenPort();
- this.metricCtx = metric.createContext(createConnectorDimensions(listenPort, connectorName));
-
- this.statistics = new ConnectionStatistics();
- addBean(statistics);
- ConnectorConfig.Throttling throttlingConfig = config.throttling();
- if (throttlingConfig.enabled()) {
- new ConnectionThrottler(this, throttlingConfig).registerWithConnector();
- }
- addBean(connectionLogger);
- }
-
- @Override
- protected void configure(final Socket socket) {
- super.configure(socket);
- try {
- socket.setKeepAlive(tcpKeepAlive);
- socket.setTcpNoDelay(tcpNoDelay);
- } catch (SocketException ignored) {
- }
- }
-
- public ConnectionStatistics getStatistics() {
- return statistics;
- }
-
- public Metric.Context getConnectorMetricContext() {
- return metricCtx;
- }
-
- 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;
- Map<String, Object> dimensions = createConnectorDimensions(listenPort, connectorName);
- dimensions.put(MetricDefinitions.METHOD_DIMENSION, method);
- dimensions.put(MetricDefinitions.SCHEME_DIMENSION, scheme);
- dimensions.put(MetricDefinitions.CLIENT_AUTHENTICATED_DIMENSION, Boolean.toString(clientAuthenticated));
- String serverName = Optional.ofNullable(request.getServerName()).orElse("unknown");
- dimensions.put(MetricDefinitions.REQUEST_SERVER_NAME_DIMENSION, serverName);
- dimensions.putAll(extraDimensions);
- return metric.createContext(dimensions);
- }
-
- public static JDiscServerConnector fromRequest(ServletRequest request) {
- return (JDiscServerConnector) request.getAttribute(REQUEST_ATTRIBUTE);
- }
-
- ConnectorConfig connectorConfig() {
- return config;
- }
-
- int listenPort() {
- return listenPort;
- }
-
- private static Map<String, Object> createConnectorDimensions(int listenPort, String connectorName) {
- Map<String, Object> props = new HashMap<>();
- props.put(MetricDefinitions.NAME_DIMENSION, connectorName);
- props.put(MetricDefinitions.PORT_DIMENSION, listenPort);
- return props;
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java
deleted file mode 100644
index cd1ca490f61..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyConnectionLogger.java
+++ /dev/null
@@ -1,373 +0,0 @@
-// Copyright Verizon Media. 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.ConnectionLog;
-import com.yahoo.container.logging.ConnectionLogEntry;
-import com.yahoo.container.logging.ConnectionLogEntry.SslHandshakeFailure.ExceptionEntry;
-import com.yahoo.io.HexDump;
-import com.yahoo.jdisc.http.ServerConfig;
-import org.eclipse.jetty.io.Connection;
-import org.eclipse.jetty.io.EndPoint;
-import org.eclipse.jetty.io.SocketChannelEndPoint;
-import org.eclipse.jetty.io.ssl.SslConnection;
-import org.eclipse.jetty.io.ssl.SslHandshakeListener;
-import org.eclipse.jetty.server.HttpChannel;
-import org.eclipse.jetty.server.HttpConnection;
-import org.eclipse.jetty.server.ProxyConnectionFactory;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.util.component.AbstractLifeCycle;
-
-import javax.net.ssl.ExtendedSSLSession;
-import javax.net.ssl.SNIHostName;
-import javax.net.ssl.SNIServerName;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.StandardConstants;
-import java.net.InetSocketAddress;
-import java.security.cert.X509Certificate;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Jetty integration for jdisc connection log ({@link ConnectionLog}).
- *
- * @author bjorncs
- */
-class JettyConnectionLogger extends AbstractLifeCycle implements Connection.Listener, HttpChannel.Listener, SslHandshakeListener {
-
- static final String CONNECTION_ID_REQUEST_ATTRIBUTE = "jdisc.request.connection.id";
-
- private static final Logger log = Logger.getLogger(JettyConnectionLogger.class.getName());
-
- private final ConcurrentMap<IdentityKey<SocketChannelEndPoint>, ConnectionInfo> connectionInfo = new ConcurrentHashMap<>();
- private final ConcurrentMap<IdentityKey<SSLEngine>, ConnectionInfo> sslToConnectionInfo = new ConcurrentHashMap<>();
-
- private final boolean enabled;
- private final ConnectionLog connectionLog;
-
- JettyConnectionLogger(ServerConfig.ConnectionLog config, ConnectionLog connectionLog) {
- this.enabled = config.enabled();
- this.connectionLog = connectionLog;
- log.log(Level.FINE, () -> "Jetty connection logger is " + (config.enabled() ? "enabled" : "disabled"));
- }
-
- //
- // AbstractLifeCycle methods start
- //
- @Override
- protected void doStop() {
- handleListenerInvocation("AbstractLifeCycle", "doStop", "", List.of(), () -> {
- log.log(Level.FINE, () -> "Jetty connection logger is stopped");
- });
- }
-
- @Override
- protected void doStart() {
- handleListenerInvocation("AbstractLifeCycle", "doStart", "", List.of(), () -> {
- log.log(Level.FINE, () -> "Jetty connection logger is started");
- });
- }
- //
- // AbstractLifeCycle methods stop
- //
-
- //
- // Connection.Listener methods start
- //
- @Override
- public void onOpened(Connection connection) {
- handleListenerInvocation("Connection.Listener", "onOpened", "%h", List.of(connection), () -> {
- SocketChannelEndPoint endpoint = findUnderlyingSocketEndpoint(connection.getEndPoint());
- var endpointKey = IdentityKey.of(endpoint);
- ConnectionInfo info = connectionInfo.get(endpointKey);
- if (info == null) {
- info = ConnectionInfo.from(endpoint);
- connectionInfo.put(IdentityKey.of(endpoint), info);
- }
- if (connection instanceof SslConnection) {
- SSLEngine sslEngine = ((SslConnection) connection).getSSLEngine();
- sslToConnectionInfo.put(IdentityKey.of(sslEngine), info);
- }
- if (connection.getEndPoint() instanceof ProxyConnectionFactory.ProxyEndPoint) {
- InetSocketAddress remoteAddress = connection.getEndPoint().getRemoteAddress();
- info.setRemoteAddress(remoteAddress);
- }
- });
- }
-
- @Override
- public void onClosed(Connection connection) {
- handleListenerInvocation("Connection.Listener", "onClosed", "%h", List.of(connection), () -> {
- SocketChannelEndPoint endpoint = findUnderlyingSocketEndpoint(connection.getEndPoint());
- var endpointKey = IdentityKey.of(endpoint);
- ConnectionInfo info = connectionInfo.get(endpointKey);
- if (info == null) return; // Closed connection already handled
- if (connection instanceof HttpConnection) {
- info.setHttpBytes(connection.getBytesIn(), connection.getBytesOut());
- }
- if (!endpoint.isOpen()) {
- info.setClosedAt(System.currentTimeMillis());
- connectionLog.log(info.toLogEntry());
- connectionInfo.remove(endpointKey);
- }
- });
- }
- //
- // Connection.Listener methods end
- //
-
- //
- // HttpChannel.Listener methods start
- //
- @Override
- public void onRequestBegin(Request request) {
- handleListenerInvocation("HttpChannel.Listener", "onRequestBegin", "%h", List.of(request), () -> {
- SocketChannelEndPoint endpoint = findUnderlyingSocketEndpoint(request.getHttpChannel().getEndPoint());
- ConnectionInfo info = Objects.requireNonNull(connectionInfo.get(IdentityKey.of(endpoint)));
- info.incrementRequests();
- request.setAttribute(CONNECTION_ID_REQUEST_ATTRIBUTE, info.uuid());
- });
- }
-
- @Override
- public void onResponseBegin(Request request) {
- handleListenerInvocation("HttpChannel.Listener", "onResponseBegin", "%h", List.of(request), () -> {
- SocketChannelEndPoint endpoint = findUnderlyingSocketEndpoint(request.getHttpChannel().getEndPoint());
- ConnectionInfo info = Objects.requireNonNull(connectionInfo.get(IdentityKey.of(endpoint)));
- info.incrementResponses();
- });
- }
- //
- // HttpChannel.Listener methods end
- //
-
- //
- // SslHandshakeListener methods start
- //
- @Override
- public void handshakeSucceeded(Event event) {
- SSLEngine sslEngine = event.getSSLEngine();
- handleListenerInvocation("SslHandshakeListener", "handshakeSucceeded", "sslEngine=%h", List.of(sslEngine), () -> {
- ConnectionInfo info = sslToConnectionInfo.remove(IdentityKey.of(sslEngine));
- info.setSslSessionDetails(sslEngine.getSession());
- });
- }
-
- @Override
- public void handshakeFailed(Event event, Throwable failure) {
- SSLEngine sslEngine = event.getSSLEngine();
- handleListenerInvocation("SslHandshakeListener", "handshakeFailed", "sslEngine=%h,failure=%s", List.of(sslEngine, failure), () -> {
- log.log(Level.FINE, failure, failure::toString);
- ConnectionInfo info = sslToConnectionInfo.remove(IdentityKey.of(sslEngine));
- info.setSslHandshakeFailure((SSLHandshakeException)failure);
- });
- }
- //
- // SslHandshakeListener methods end
- //
-
- private void handleListenerInvocation(
- String listenerType, String methodName, String methodArgumentsFormat, List<Object> methodArguments, ListenerHandler handler) {
- if (!enabled) return;
- try {
- log.log(Level.FINE, () -> String.format(listenerType + "." + methodName + "(" + methodArgumentsFormat + ")", methodArguments.toArray()));
- handler.run();
- } catch (Exception e) {
- log.log(Level.WARNING, String.format("Exception in %s.%s listener: %s", listenerType, methodName, e.getMessage()), e);
- }
- }
-
- /**
- * Protocol layers are connected through each {@link Connection}'s {@link EndPoint} reference.
- * This methods iterates through the endpoints recursively to find the underlying socket endpoint.
- */
- private static SocketChannelEndPoint findUnderlyingSocketEndpoint(EndPoint endpoint) {
- if (endpoint instanceof SocketChannelEndPoint) {
- return (SocketChannelEndPoint) endpoint;
- } else if (endpoint instanceof SslConnection.DecryptedEndPoint) {
- var decryptedEndpoint = (SslConnection.DecryptedEndPoint) endpoint;
- return findUnderlyingSocketEndpoint(decryptedEndpoint.getSslConnection().getEndPoint());
- } else if (endpoint instanceof ProxyConnectionFactory.ProxyEndPoint) {
- var proxyEndpoint = (ProxyConnectionFactory.ProxyEndPoint) endpoint;
- return findUnderlyingSocketEndpoint(proxyEndpoint.unwrap());
- } else {
- throw new IllegalArgumentException("Unknown connection endpoint type: " + endpoint.getClass().getName());
- }
- }
-
- @FunctionalInterface private interface ListenerHandler { void run() throws Exception; }
-
- private static class ConnectionInfo {
- private final UUID uuid;
- private final long createdAt;
- private final InetSocketAddress localAddress;
- private final InetSocketAddress peerAddress;
-
- private long closedAt = 0;
- private long httpBytesReceived = 0;
- private long httpBytesSent = 0;
- private long requests = 0;
- private long responses = 0;
- private InetSocketAddress remoteAddress;
- private byte[] sslSessionId;
- private String sslProtocol;
- private String sslCipherSuite;
- private String sslPeerSubject;
- private Date sslPeerNotBefore;
- private Date sslPeerNotAfter;
- private List<SNIServerName> sslSniServerNames;
- private SSLHandshakeException sslHandshakeException;
-
- private ConnectionInfo(UUID uuid, long createdAt, InetSocketAddress localAddress, InetSocketAddress peerAddress) {
- this.uuid = uuid;
- this.createdAt = createdAt;
- this.localAddress = localAddress;
- this.peerAddress = peerAddress;
- }
-
- static ConnectionInfo from(SocketChannelEndPoint endpoint) {
- return new ConnectionInfo(
- UUID.randomUUID(),
- endpoint.getCreatedTimeStamp(),
- endpoint.getLocalAddress(),
- endpoint.getRemoteAddress());
- }
-
- synchronized UUID uuid() { return uuid; }
-
- synchronized ConnectionInfo setClosedAt(long closedAt) {
- this.closedAt = closedAt;
- return this;
- }
-
- synchronized ConnectionInfo setHttpBytes(long received, long sent) {
- this.httpBytesReceived = received;
- this.httpBytesSent = sent;
- return this;
- }
-
- synchronized ConnectionInfo incrementRequests() { ++this.requests; return this; }
-
- synchronized ConnectionInfo incrementResponses() { ++this.responses; return this; }
-
- synchronized ConnectionInfo setRemoteAddress(InetSocketAddress remoteAddress) {
- this.remoteAddress = remoteAddress;
- return this;
- }
-
- synchronized ConnectionInfo setSslSessionDetails(SSLSession session) {
- this.sslCipherSuite = session.getCipherSuite();
- this.sslProtocol = session.getProtocol();
- this.sslSessionId = session.getId();
- if (session instanceof ExtendedSSLSession) {
- ExtendedSSLSession extendedSession = (ExtendedSSLSession) session;
- this.sslSniServerNames = extendedSession.getRequestedServerNames();
- }
- try {
- this.sslPeerSubject = session.getPeerPrincipal().getName();
- X509Certificate peerCertificate = (X509Certificate) session.getPeerCertificates()[0];
- this.sslPeerNotBefore = peerCertificate.getNotBefore();
- this.sslPeerNotAfter = peerCertificate.getNotAfter();
- } catch (SSLPeerUnverifiedException e) {
- // Throw if peer is not authenticated (e.g when client auth is disabled)
- // JSSE provides no means of checking for client authentication without catching this exception
- }
- return this;
- }
-
- synchronized ConnectionInfo setSslHandshakeFailure(SSLHandshakeException exception) {
- this.sslHandshakeException = exception;
- return this;
- }
-
- synchronized ConnectionLogEntry toLogEntry() {
- ConnectionLogEntry.Builder builder = ConnectionLogEntry.builder(uuid, Instant.ofEpochMilli(createdAt));
- if (closedAt > 0) {
- builder.withDuration((closedAt - createdAt) / 1000D);
- }
- if (httpBytesReceived > 0) {
- builder.withHttpBytesReceived(httpBytesReceived);
- }
- if (httpBytesSent > 0) {
- builder.withHttpBytesSent(httpBytesSent);
- }
- if (requests > 0) {
- builder.withRequests(requests);
- }
- if (responses > 0) {
- builder.withResponses(responses);
- }
- if (peerAddress != null) {
- builder.withPeerAddress(peerAddress.getHostString())
- .withPeerPort(peerAddress.getPort());
- }
- if (localAddress != null) {
- builder.withLocalAddress(localAddress.getHostString())
- .withLocalPort(localAddress.getPort());
- }
- if (remoteAddress != null) {
- builder.withRemoteAddress(remoteAddress.getHostString())
- .withRemotePort(remoteAddress.getPort());
- }
- if (sslProtocol != null && sslCipherSuite != null && sslSessionId != null) {
- builder.withSslProtocol(sslProtocol)
- .withSslCipherSuite(sslCipherSuite)
- .withSslSessionId(HexDump.toHexString(sslSessionId));
- }
- if (sslSniServerNames != null) {
- sslSniServerNames.stream()
- .filter(name -> name instanceof SNIHostName && name.getType() == StandardConstants.SNI_HOST_NAME)
- .map(name -> ((SNIHostName) name).getAsciiName())
- .findAny()
- .ifPresent(builder::withSslSniServerName);
- }
- if (sslPeerSubject != null && sslPeerNotAfter != null && sslPeerNotBefore != null) {
- builder.withSslPeerSubject(sslPeerSubject)
- .withSslPeerNotAfter(sslPeerNotAfter.toInstant())
- .withSslPeerNotBefore(sslPeerNotBefore.toInstant());
- }
- if (sslHandshakeException != null) {
- List<ExceptionEntry> exceptionChain = new ArrayList<>();
- Throwable cause = sslHandshakeException;
- while (cause != null) {
- exceptionChain.add(new ExceptionEntry(cause.getClass().getName(), cause.getMessage()));
- cause = cause.getCause();
- }
- String type = SslHandshakeFailure.fromSslHandshakeException(sslHandshakeException)
- .map(SslHandshakeFailure::failureType)
- .orElse("UNKNOWN");
- builder.withSslHandshakeFailure(new ConnectionLogEntry.SslHandshakeFailure(type, exceptionChain));
- }
- return builder.build();
- }
-
- }
-
- private static class IdentityKey<T> {
- final T instance;
-
- IdentityKey(T instance) { this.instance = instance; }
-
- static <T> IdentityKey<T> of(T instance) { return new IdentityKey<>(instance); }
-
- @Override public int hashCode() { return System.identityHashCode(instance); }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (!(obj instanceof IdentityKey<?>)) return false;
- IdentityKey<?> other = (IdentityKey<?>) obj;
- return this.instance == other.instance;
- }
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
deleted file mode 100644
index 510c561c10f..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/JettyHttpServer.java
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright 2018 Yahoo Holdings. 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.Inject;
-import com.yahoo.component.ComponentId;
-import com.yahoo.component.provider.ComponentRegistry;
-import com.yahoo.concurrent.DaemonThreadFactory;
-import com.yahoo.container.logging.AccessLog;
-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;
-import org.eclipse.jetty.jmx.ConnectorServer;
-import org.eclipse.jetty.jmx.MBeanContainer;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
-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;
-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.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-
-import static java.util.stream.Collectors.toList;
-
-/**
- * @author Simon Thoresen Hult
- * @author bjorncs
- */
-public class JettyHttpServer extends AbstractServerProvider {
-
- private final static Logger log = Logger.getLogger(JettyHttpServer.class.getName());
-
- private final ExecutorService janitor;
-
- private final Server server;
- private final List<Integer> listenedPorts = new ArrayList<>();
- private final ServerMetricReporter metricsReporter;
-
- @Inject
- public JettyHttpServer(CurrentContainer container,
- Metric metric,
- ServerConfig serverConfig,
- ServletPathsConfig servletPathsConfig,
- FilterBindings filterBindings,
- ComponentRegistry<ConnectorFactory> connectorFactories,
- ComponentRegistry<ServletHolder> servletHolders,
- FilterInvoker filterInvoker,
- RequestLog requestLog,
- ConnectionLog connectionLog) {
- super(container);
- if (connectorFactories.allComponents().isEmpty())
- throw new IllegalArgumentException("No connectors configured.");
-
- initializeJettyLogging();
-
- server = new Server();
- server.setStopTimeout((long)(serverConfig.stopTimeout() * 1000.0));
- server.setRequestLog(new AccessLogRequestLog(requestLog, serverConfig.accessLog()));
- setupJmx(server, serverConfig);
- configureJettyThreadpool(server, serverConfig);
- JettyConnectionLogger connectionLogger = new JettyConnectionLogger(serverConfig.connectionLog(), connectionLog);
-
- for (ConnectorFactory connectorFactory : connectorFactories.allComponents()) {
- ConnectorConfig connectorConfig = connectorFactory.getConnectorConfig();
- server.addConnector(connectorFactory.createConnector(metric, server, connectionLogger));
- listenedPorts.add(connectorConfig.listenPort());
- }
-
- janitor = newJanitor();
-
- JDiscContext jDiscContext = new JDiscContext(filterBindings,
- container,
- janitor,
- metric,
- 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));
- this.metricsReporter = new ServerMetricReporter(metric, server);
- }
-
- private static void initializeJettyLogging() {
- // Note: Jetty is logging stderr if no logger is explicitly configured
- try {
- Log.setLog(new JavaUtilLog());
- } catch (Exception e) {
- throw new RuntimeException("Unable to initialize logging framework for Jetty");
- }
- }
-
- private static void setupJmx(Server server, ServerConfig serverConfig) {
- if (serverConfig.jmx().enabled()) {
- System.setProperty("java.rmi.server.hostname", "localhost");
- server.addBean(new MBeanContainer(ManagementFactory.getPlatformMBeanServer()));
- server.addBean(new ConnectorServer(createJmxLoopbackOnlyServiceUrl(serverConfig.jmx().listenPort()),
- "org.eclipse.jetty.jmx:name=rmiconnectorserver"));
- }
- }
-
- private static void configureJettyThreadpool(Server server, ServerConfig config) {
- QueuedThreadPool pool = (QueuedThreadPool) server.getThreadPool();
- pool.setMaxThreads(config.maxWorkerThreads());
- pool.setMinThreads(config.minWorkerThreads());
- }
-
- private static JMXServiceURL createJmxLoopbackOnlyServiceUrl(int port) {
- try {
- return new JMXServiceURL("rmi", "localhost", port, "/jndi/rmi://localhost:" + port + "/jmxrmi");
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
- }
-
- private HandlerCollection getHandlerCollection(ServerConfig serverConfig,
- ServletPathsConfig servletPathsConfig,
- List<JDiscServerConnector> connectors,
- ServletHolder jdiscServlet,
- ComponentRegistry<ServletHolder> servletHolders,
- FilterHolder jDiscFilterInvokerFilter) {
- 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());
- var secureRedirectHandler = new SecuredRedirectHandler(connectorConfigs);
- secureRedirectHandler.setHandler(servletContextHandler);
-
- var proxyHandler = new HealthCheckProxyHandler(connectors);
- proxyHandler.setHandler(secureRedirectHandler);
-
- var authEnforcer = new TlsClientAuthenticationEnforcer(connectorConfigs);
- authEnforcer.setHandler(proxyHandler);
-
- GzipHandler gzipHandler = newGzipHandler(serverConfig);
- gzipHandler.setHandler(authEnforcer);
-
- HttpResponseStatisticsCollector statisticsCollector =
- new HttpResponseStatisticsCollector(serverConfig.metric().monitoringHandlerPaths(),
- serverConfig.metric().searchHandlerPaths());
- statisticsCollector.setHandler(gzipHandler);
-
- StatisticsHandler statisticsHandler = newStatisticsHandler();
- statisticsHandler.setHandler(statisticsCollector);
-
- HandlerCollection handlerCollection = new HandlerCollection();
- handlerCollection.setHandlers(new Handler[] { statisticsHandler });
- 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("/");
- servletContextHandler.setDisplayName(getDisplayName(listenedPorts));
- return servletContextHandler;
- }
-
- private static String getDisplayName(List<Integer> ports) {
- return ports.stream().map(Object::toString).collect(Collectors.joining(":"));
- }
-
- // Separate threadpool for tasks that cannot be executed on the jdisc default threadpool due to risk of deadlock
- private static ExecutorService newJanitor() {
- int threadPoolSize = Math.max(1, Runtime.getRuntime().availableProcessors()/8);
- log.info("Creating janitor executor with " + threadPoolSize + " threads");
- return Executors.newFixedThreadPool(
- threadPoolSize,
- new DaemonThreadFactory(JettyHttpServer.class.getName() + "-Janitor-"));
- }
-
- @Override
- public void start() {
- try {
- server.start();
- metricsReporter.start();
- logEffectiveSslConfiguration();
- } catch (final Exception e) {
- if (e instanceof IOException && e.getCause() instanceof BindException) {
- throw new RuntimeException("Failed to start server due to BindException. ListenPorts = " + listenedPorts.toString(), e.getCause());
- }
- throw new RuntimeException("Failed to start server.", e);
- }
- }
-
- private void logEffectiveSslConfiguration() {
- if (!server.isStarted()) throw new IllegalStateException();
- for (Connector connector : server.getConnectors()) {
- ServerConnector serverConnector = (ServerConnector) connector;
- int localPort = serverConnector.getLocalPort();
- var sslConnectionFactory = serverConnector.getConnectionFactory(SslConnectionFactory.class);
- if (sslConnectionFactory != null) {
- var sslContextFactory = sslConnectionFactory.getSslContextFactory();
- log.info(String.format("Enabled SSL cipher suites for port '%d': %s",
- localPort, Arrays.toString(sslContextFactory.getSelectedCipherSuites())));
- log.info(String.format("Enabled SSL protocols for port '%d': %s",
- localPort, Arrays.toString(sslContextFactory.getSelectedProtocols())));
- }
- }
- }
-
- @Override
- public void close() {
- try {
- log.log(Level.INFO, String.format("Shutting down server (graceful=%b, timeout=%.1fs)", isGracefulShutdownEnabled(), server.getStopTimeout()/1000d));
- server.stop();
- log.log(Level.INFO, "Server shutdown completed");
- } catch (final Exception e) {
- log.log(Level.SEVERE, "Server shutdown threw an unexpected exception.", e);
- }
-
- metricsReporter.shutdown();
- janitor.shutdown();
- }
-
- private boolean isGracefulShutdownEnabled() {
- return server.getChildHandlersByClass(StatisticsHandler.class).length > 0 && server.getStopTimeout() > 0;
- }
-
- public int getListenPort() {
- return ((ServerConnector)server.getConnectors()[0]).getLocalPort();
- }
-
- Server server() { return server; }
-
- private StatisticsHandler newStatisticsHandler() {
- StatisticsHandler statisticsHandler = new StatisticsHandler();
- statisticsHandler.statsReset();
- return statisticsHandler;
- }
-
- private GzipHandler newGzipHandler(ServerConfig serverConfig) {
- GzipHandler gzipHandler = new GzipHandlerWithVaryHeaderFixed();
- gzipHandler.setCompressionLevel(serverConfig.responseCompressionLevel());
- gzipHandler.setInflateBufferSize(8 * 1024);
- gzipHandler.setIncludedMethods("GET", "POST", "PUT", "PATCH");
- return gzipHandler;
- }
-
- /** A subclass which overrides Jetty's default behavior of including user-agent in the vary field */
- private static class GzipHandlerWithVaryHeaderFixed extends GzipHandler {
-
- @Override
- public HttpField getVaryField() {
- return GzipHttpOutputInterceptor.VARY_ACCEPT_ENCODING;
- }
-
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/MetricDefinitions.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/MetricDefinitions.java
deleted file mode 100644
index 5e953179b53..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/MetricDefinitions.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-/**
- * Name and dimensions for jdisc/container metrics
- *
- * @author bjorncs
- */
-class MetricDefinitions {
- static final String NAME_DIMENSION = "serverName";
- static final String PORT_DIMENSION = "serverPort";
- static final String METHOD_DIMENSION = "httpMethod";
- static final String SCHEME_DIMENSION = "scheme";
- static final String REQUEST_TYPE_DIMENSION = "requestType";
- static final String CLIENT_IP_DIMENSION = "clientIp";
- static final String CLIENT_AUTHENTICATED_DIMENSION = "clientAuthenticated";
- static final String REQUEST_SERVER_NAME_DIMENSION = "requestServerName";
- static final String FILTER_CHAIN_ID_DIMENSION = "chainId";
-
- static final String NUM_OPEN_CONNECTIONS = "serverNumOpenConnections";
- static final String NUM_CONNECTIONS_OPEN_MAX = "serverConnectionsOpenMax";
- static final String CONNECTION_DURATION_MAX = "serverConnectionDurationMax";
- static final String CONNECTION_DURATION_MEAN = "serverConnectionDurationMean";
- static final String CONNECTION_DURATION_STD_DEV = "serverConnectionDurationStdDev";
- static final String NUM_PREMATURELY_CLOSED_CONNECTIONS = "jdisc.http.request.prematurely_closed";
-
- static final String NUM_BYTES_RECEIVED = "serverBytesReceived";
- static final String NUM_BYTES_SENT = "serverBytesSent";
-
- static final String NUM_CONNECTIONS = "serverNumConnections";
-
- /* For historical reasons, these are all aliases for the same metric. 'jdisc.http' should ideally be the only one. */
- static final String JDISC_HTTP_REQUESTS = "jdisc.http.requests";
- static final String NUM_REQUESTS = "serverNumRequests";
-
- static final String NUM_SUCCESSFUL_RESPONSES = "serverNumSuccessfulResponses";
- static final String NUM_FAILED_RESPONSES = "serverNumFailedResponses";
- static final String NUM_SUCCESSFUL_WRITES = "serverNumSuccessfulResponseWrites";
- static final String NUM_FAILED_WRITES = "serverNumFailedResponseWrites";
-
- static final String TOTAL_SUCCESSFUL_LATENCY = "serverTotalSuccessfulResponseLatency";
- static final String TOTAL_FAILED_LATENCY = "serverTotalFailedResponseLatency";
- static final String TIME_TO_FIRST_BYTE = "serverTimeToFirstByte";
-
- static final String RESPONSES_1XX = "http.status.1xx";
- static final String RESPONSES_2XX = "http.status.2xx";
- static final String RESPONSES_3XX = "http.status.3xx";
- static final String RESPONSES_4XX = "http.status.4xx";
- static final String RESPONSES_5XX = "http.status.5xx";
- static final String RESPONSES_401 = "http.status.401";
- static final String RESPONSES_403 = "http.status.403";
-
- static final String STARTED_MILLIS = "serverStartedMillis";
-
- static final String URI_LENGTH = "jdisc.http.request.uri_length";
- static final String CONTENT_SIZE = "jdisc.http.request.content_size";
-
- static final String SSL_HANDSHAKE_FAILURE_MISSING_CLIENT_CERT = "jdisc.http.ssl.handshake.failure.missing_client_cert";
- static final String SSL_HANDSHAKE_FAILURE_EXPIRED_CLIENT_CERT = "jdisc.http.ssl.handshake.failure.expired_client_cert";
- static final String SSL_HANDSHAKE_FAILURE_INVALID_CLIENT_CERT = "jdisc.http.ssl.handshake.failure.invalid_client_cert";
- static final String SSL_HANDSHAKE_FAILURE_INCOMPATIBLE_PROTOCOLS = "jdisc.http.ssl.handshake.failure.incompatible_protocols";
- static final String SSL_HANDSHAKE_FAILURE_INCOMPATIBLE_CIPHERS = "jdisc.http.ssl.handshake.failure.incompatible_ciphers";
- static final String SSL_HANDSHAKE_FAILURE_UNKNOWN = "jdisc.http.ssl.handshake.failure.unknown";
-
- static final String JETTY_THREADPOOL_MAX_THREADS = "jdisc.http.jetty.threadpool.thread.max";
- static final String JETTY_THREADPOOL_MIN_THREADS = "jdisc.http.jetty.threadpool.thread.min";
- static final String JETTY_THREADPOOL_RESERVED_THREADS = "jdisc.http.jetty.threadpool.thread.reserved";
- static final String JETTY_THREADPOOL_BUSY_THREADS = "jdisc.http.jetty.threadpool.thread.busy";
- static final String JETTY_THREADPOOL_IDLE_THREADS = "jdisc.http.jetty.threadpool.thread.idle";
- static final String JETTY_THREADPOOL_TOTAL_THREADS = "jdisc.http.jetty.threadpool.thread.total";
- static final String JETTY_THREADPOOL_QUEUE_SIZE = "jdisc.http.jetty.threadpool.queue.size";
-
- static final String FILTERING_REQUEST_HANDLED = "jdisc.http.filtering.request.handled";
- static final String FILTERING_REQUEST_UNHANDLED = "jdisc.http.filtering.request.unhandled";
- static final String FILTERING_RESPONSE_HANDLED = "jdisc.http.filtering.response.handled";
- static final String FILTERING_RESPONSE_UNHANDLED = "jdisc.http.filtering.response.unhandled";
-
- private MetricDefinitions() {}
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/OneTimeRunnable.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/OneTimeRunnable.java
deleted file mode 100644
index eb83d3d7d03..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/OneTimeRunnable.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ReferenceCountingRequestHandler.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ReferenceCountingRequestHandler.java
deleted file mode 100644
index f2bf5b56d5c..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ReferenceCountingRequestHandler.java
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.Request;
-import com.yahoo.jdisc.ResourceReference;
-import com.yahoo.jdisc.Response;
-import com.yahoo.jdisc.SharedResource;
-import com.yahoo.jdisc.handler.CompletionHandler;
-import com.yahoo.jdisc.handler.ContentChannel;
-import com.yahoo.jdisc.handler.NullContent;
-import com.yahoo.jdisc.handler.RequestHandler;
-import com.yahoo.jdisc.handler.ResponseHandler;
-
-import java.nio.ByteBuffer;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * This class wraps a request handler and does reference counting on the request for every object that depends on the
- * request, such as the response handler, content channels and completion handlers. This ensures that requests (and
- * hence the current container) will be referenced until the end of the request handling - even with async handling in
- * non-framework threads - without requiring the application to handle this tedious work.
- *
- * @author bakksjo
- */
-@SuppressWarnings("try")
-class ReferenceCountingRequestHandler implements RequestHandler {
-
- private static final Logger log = Logger.getLogger(ReferenceCountingRequestHandler.class.getName());
-
- final RequestHandler delegate;
-
- ReferenceCountingRequestHandler(RequestHandler delegate) {
- Objects.requireNonNull(delegate, "delegate");
- this.delegate = delegate;
- }
-
- @Override
- public ContentChannel handleRequest(Request request, ResponseHandler responseHandler) {
- try (final ResourceReference requestReference = request.refer()) {
- ContentChannel contentChannel;
- final ReferenceCountingResponseHandler referenceCountingResponseHandler
- = new ReferenceCountingResponseHandler(request, new NullContentResponseHandler(responseHandler));
- try {
- contentChannel = delegate.handleRequest(request, referenceCountingResponseHandler);
- Objects.requireNonNull(contentChannel, "contentChannel");
- } catch (Throwable t) {
- try {
- // The response handler might never be invoked, due to the exception thrown from handleRequest().
- referenceCountingResponseHandler.unrefer();
- } catch (Throwable thrownFromUnrefer) {
- log.log(Level.WARNING, "Unexpected problem", thrownFromUnrefer);
- }
- throw t;
- }
- return new ReferenceCountingContentChannel(request, contentChannel);
- }
- }
-
- @Override
- public void handleTimeout(Request request, ResponseHandler responseHandler) {
- delegate.handleTimeout(request, new NullContentResponseHandler(responseHandler));
- }
-
- @Override
- public ResourceReference refer() {
- return delegate.refer();
- }
-
- @Override
- public void release() {
- delegate.release();
- }
-
- @Override
- public String toString() {
- return delegate.toString();
- }
-
- private static class ReferenceCountingResponseHandler implements ResponseHandler {
-
- final SharedResource request;
- final ResourceReference requestReference;
- final ResponseHandler delegate;
- final AtomicBoolean closed = new AtomicBoolean(false);
-
- ReferenceCountingResponseHandler(SharedResource request, ResponseHandler delegate) {
- Objects.requireNonNull(request, "request");
- Objects.requireNonNull(delegate, "delegate");
- this.request = request;
- this.delegate = delegate;
- this.requestReference = request.refer();
- }
-
- @Override
- public ContentChannel handleResponse(Response response) {
- if (closed.getAndSet(true)) {
- throw new IllegalStateException(delegate + " is already called.");
- }
- try (final ResourceReference ref = requestReference) {
- ContentChannel contentChannel = delegate.handleResponse(response);
- Objects.requireNonNull(contentChannel, "contentChannel");
- return new ReferenceCountingContentChannel(request, contentChannel);
- }
- }
-
- @Override
- public String toString() {
- return delegate.toString();
- }
-
- /**
- * Close the reference that is normally closed by {@link #handleResponse(Response)}.
- *
- * This is to be used in error situations, where handleResponse() may not be invoked.
- */
- public void unrefer() {
- if (closed.getAndSet(true)) {
- // This simply means that handleResponse() has been run, in which case we are
- // guaranteed that the reference is closed.
- return;
- }
- requestReference.close();
- }
- }
-
- private static class ReferenceCountingContentChannel implements ContentChannel {
-
- final SharedResource request;
- final ResourceReference requestReference;
- final ContentChannel delegate;
-
- ReferenceCountingContentChannel(SharedResource request, ContentChannel delegate) {
- Objects.requireNonNull(request, "request");
- Objects.requireNonNull(delegate, "delegate");
- this.request = request;
- this.delegate = delegate;
- this.requestReference = request.refer();
- }
-
- @Override
- public void write(ByteBuffer buf, CompletionHandler completionHandler) {
- final CompletionHandler referenceCountingCompletionHandler
- = new ReferenceCountingCompletionHandler(request, completionHandler);
- try {
- delegate.write(buf, referenceCountingCompletionHandler);
- } catch (Throwable t) {
- try {
- referenceCountingCompletionHandler.failed(t);
- } catch (AlreadyCompletedException ignored) {
- } catch (Throwable failFailure) {
- log.log(Level.WARNING, "Failure during call to CompletionHandler.failed()", failFailure);
- }
- throw t;
- }
- }
-
- @Override
- public void close(CompletionHandler completionHandler) {
- final CompletionHandler referenceCountingCompletionHandler
- = new ReferenceCountingCompletionHandler(request, completionHandler);
- try (final ResourceReference ref = requestReference) {
- delegate.close(referenceCountingCompletionHandler);
- } catch (Throwable t) {
- try {
- referenceCountingCompletionHandler.failed(t);
- } catch (AlreadyCompletedException ignored) {
- } catch (Throwable failFailure) {
- log.log(Level.WARNING, "Failure during call to CompletionHandler.failed()", failFailure);
- }
- throw t;
- }
- }
-
- @Override
- public String toString() {
- return delegate.toString();
- }
- }
-
- private static class AlreadyCompletedException extends IllegalStateException {
- public AlreadyCompletedException(final CompletionHandler completionHandler) {
- super(completionHandler + " is already called.");
- }
- }
-
- private static class ReferenceCountingCompletionHandler implements CompletionHandler {
-
- final ResourceReference requestReference;
- final CompletionHandler delegate;
- final AtomicBoolean closed = new AtomicBoolean(false);
-
- public ReferenceCountingCompletionHandler(SharedResource request, CompletionHandler delegate) {
- this.delegate = delegate;
- this.requestReference = request.refer();
- }
-
- @Override
- public void completed() {
- if (closed.getAndSet(true)) {
- throw new AlreadyCompletedException(delegate);
- }
- try {
- if (delegate != null) {
- delegate.completed();
- }
- } finally {
- requestReference.close();
- }
- }
-
- @Override
- public void failed(Throwable t) {
- if (closed.getAndSet(true)) {
- throw new AlreadyCompletedException(delegate);
- }
- try (final ResourceReference ref = requestReference) {
- if (delegate != null) {
- delegate.failed(t);
- } else {
- log.log(Level.WARNING, "Uncaught completion failure.", t);
- }
- }
- }
-
- @Override
- public String toString() {
- return String.valueOf(delegate);
- }
- }
-
- private static class NullContentResponseHandler implements ResponseHandler {
-
- final ResponseHandler delegate;
-
- NullContentResponseHandler(ResponseHandler delegate) {
- Objects.requireNonNull(delegate, "delegate");
- this.delegate = delegate;
- }
-
- @Override
- public ContentChannel handleResponse(Response response) {
- ContentChannel contentChannel = delegate.handleResponse(response);
- if (contentChannel == null) {
- contentChannel = NullContent.INSTANCE;
- }
- return contentChannel;
- }
-
- @Override
- public String toString() {
- return delegate.toString();
- }
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestException.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestException.java
deleted file mode 100644
index eea69cd7f74..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestException.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-/**
- * This exception may be thrown from a request handler to fail a request with a given response code and message.
- * It is given some special treatment in {@link ServletResponseController}.
- *
- * @author bakksjo
- */
-class RequestException extends RuntimeException {
-
- private final int responseStatus;
-
- /**
- * @param responseStatus the response code to use for the http response
- * @param message exception message
- * @param cause chained throwable
- */
- public RequestException(final int responseStatus, final String message, final Throwable cause) {
- super(message, cause);
- this.responseStatus = responseStatus;
- }
-
- /**
- * @param responseStatus the response code to use for the http response
- * @param message exception message
- */
- public RequestException(final int responseStatus, final String message) {
- super(message);
- this.responseStatus = responseStatus;
- }
-
- /**
- * Returns the response code to use for the http response.
- */
- public int getResponseStatus() {
- return responseStatus;
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestMetricReporter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestMetricReporter.java
deleted file mode 100644
index 7596be0415a..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/RequestMetricReporter.java
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.Metric;
-import com.yahoo.jdisc.Metric.Context;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-
-/**
- * Responsible for metric reporting for JDisc http request handler support.
- * @author Tony Vaagenes
- */
-class RequestMetricReporter {
- private final Metric metric;
- private final Context context;
-
- private final long requestStartTime;
-
- //TODO: rename
- private final AtomicBoolean firstSetOfTimeToFirstByte = new AtomicBoolean(true);
-
-
- RequestMetricReporter(Metric metric, Context context, long requestStartTime) {
- this.metric = metric;
- this.context = context;
- this.requestStartTime = requestStartTime;
- }
-
- void successfulWrite(int numBytes) {
- setTimeToFirstByteFirstTime();
-
- metric.add(MetricDefinitions.NUM_SUCCESSFUL_WRITES, 1, context);
- metric.set(MetricDefinitions.NUM_BYTES_SENT, numBytes, context);
- }
-
- private void setTimeToFirstByteFirstTime() {
- boolean isFirstWrite = firstSetOfTimeToFirstByte.getAndSet(false);
- if (isFirstWrite) {
- long timeToFirstByte = getRequestLatency();
- metric.set(MetricDefinitions.TIME_TO_FIRST_BYTE, timeToFirstByte, context);
- }
- }
-
- void failedWrite() {
- metric.add(MetricDefinitions.NUM_FAILED_WRITES, 1, context);
- }
-
- void successfulResponse() {
- setTimeToFirstByteFirstTime();
-
- long requestLatency = getRequestLatency();
-
- metric.set(MetricDefinitions.TOTAL_SUCCESSFUL_LATENCY, requestLatency, context);
-
- metric.add(MetricDefinitions.NUM_SUCCESSFUL_RESPONSES, 1, context);
- }
-
- void failedResponse() {
- setTimeToFirstByteFirstTime();
-
- metric.set(MetricDefinitions.TOTAL_FAILED_LATENCY, getRequestLatency(), context);
- metric.add(MetricDefinitions.NUM_FAILED_RESPONSES, 1, context);
- }
-
- void prematurelyClosed() {
- metric.add(MetricDefinitions.NUM_PREMATURELY_CLOSED_CONNECTIONS, 1, context);
- }
-
- void successfulRead(int bytes_received) {
- metric.set(MetricDefinitions.NUM_BYTES_RECEIVED, bytes_received, context);
- }
-
- private long getRequestLatency() {
- return System.currentTimeMillis() - requestStartTime;
- }
-
- void uriLength(int length) {
- metric.set(MetricDefinitions.URI_LENGTH, length, context);
- }
-
- void contentSize(int size) {
- metric.set(MetricDefinitions.CONTENT_SIZE, size, context);
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SecuredRedirectHandler.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SecuredRedirectHandler.java
deleted file mode 100644
index e32c9d46deb..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SecuredRedirectHandler.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright Verizon Media. 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.http.ConnectorConfig;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.HandlerWrapper;
-import org.eclipse.jetty.util.URIUtil;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static com.yahoo.jdisc.http.server.jetty.HttpServletRequestUtils.getConnectorLocalPort;
-
-/**
- * A secure redirect handler inspired by {@link org.eclipse.jetty.server.handler.SecuredRedirectHandler}.
- *
- * @author bjorncs
- */
-class SecuredRedirectHandler extends HandlerWrapper {
-
- private static final String HEALTH_CHECK_PATH = "/status.html";
-
- private final Map<Integer, Integer> redirectMap;
-
- SecuredRedirectHandler(List<ConnectorConfig> connectorConfigs) {
- this.redirectMap = createRedirectMap(connectorConfigs);
- }
-
- @Override
- public void handle(String target, Request request, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, ServletException {
- int localPort = getConnectorLocalPort(servletRequest);
- if (!redirectMap.containsKey(localPort)) {
- _handler.handle(target, request, servletRequest, servletResponse);
- return;
- }
- servletResponse.setContentLength(0);
- if (!servletRequest.getRequestURI().equals(HEALTH_CHECK_PATH)) {
- servletResponse.sendRedirect(
- URIUtil.newURI("https", request.getServerName(), redirectMap.get(localPort), request.getRequestURI(), request.getQueryString()));
- }
- request.setHandled(true);
- }
-
- private static Map<Integer, Integer> createRedirectMap(List<ConnectorConfig> connectorConfigs) {
- var redirectMap = new HashMap<Integer, Integer>();
- for (ConnectorConfig connectorConfig : connectorConfigs) {
- if (connectorConfig.secureRedirect().enabled()) {
- redirectMap.put(connectorConfig.listenPort(), connectorConfig.secureRedirect().port());
- }
- }
- return redirectMap;
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServerMetricReporter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServerMetricReporter.java
deleted file mode 100644
index ba3694ffc2f..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServerMetricReporter.java
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright Verizon Media. 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.concurrent.DaemonThreadFactory;
-import com.yahoo.jdisc.Metric;
-import org.eclipse.jetty.io.ConnectionStatistics;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandlerContainer;
-import org.eclipse.jetty.server.handler.StatisticsHandler;
-import org.eclipse.jetty.util.thread.QueuedThreadPool;
-
-import java.time.Instant;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Reports server/connector specific metrics for Jdisc and Jetty
- *
- * @author bjorncs
- */
-class ServerMetricReporter {
-
- private final ScheduledExecutorService executor =
- Executors.newScheduledThreadPool(1, new DaemonThreadFactory("jdisc-jetty-metric-reporter-"));
- private final Metric metric;
- private final Server jetty;
-
- ServerMetricReporter(Metric metric, Server jetty) {
- this.metric = metric;
- this.jetty = jetty;
- }
-
- void start() {
- executor.scheduleAtFixedRate(new ReporterTask(), 0, 2, TimeUnit.SECONDS);
- }
-
- void shutdown() {
- try {
- executor.shutdownNow();
- executor.awaitTermination(10, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- private class ReporterTask implements Runnable {
-
- private final Instant timeStarted = Instant.now();
-
- @Override
- public void run() {
- HttpResponseStatisticsCollector statisticsCollector = ((AbstractHandlerContainer) jetty.getHandler())
- .getChildHandlerByClass(HttpResponseStatisticsCollector.class);
- if (statisticsCollector != null) {
- setServerMetrics(statisticsCollector);
- }
-
- // reset statisticsHandler to preserve earlier behavior
- StatisticsHandler statisticsHandler = ((AbstractHandlerContainer) jetty.getHandler())
- .getChildHandlerByClass(StatisticsHandler.class);
- if (statisticsHandler != null) {
- statisticsHandler.statsReset();
- }
-
- for (Connector connector : jetty.getConnectors()) {
- setConnectorMetrics((JDiscServerConnector)connector);
- }
-
- setJettyThreadpoolMetrics();
- }
-
- private void setServerMetrics(HttpResponseStatisticsCollector statisticsCollector) {
- long timeSinceStarted = System.currentTimeMillis() - timeStarted.toEpochMilli();
- metric.set(MetricDefinitions.STARTED_MILLIS, timeSinceStarted, null);
-
- addResponseMetrics(statisticsCollector);
- }
-
- private void addResponseMetrics(HttpResponseStatisticsCollector statisticsCollector) {
- for (var metricEntry : statisticsCollector.takeStatistics()) {
- Map<String, Object> dimensions = new HashMap<>();
- dimensions.put(MetricDefinitions.METHOD_DIMENSION, metricEntry.method);
- dimensions.put(MetricDefinitions.SCHEME_DIMENSION, metricEntry.scheme);
- dimensions.put(MetricDefinitions.REQUEST_TYPE_DIMENSION, metricEntry.requestType);
- metric.add(metricEntry.name, metricEntry.value, metric.createContext(dimensions));
- }
- }
-
- private void setJettyThreadpoolMetrics() {
- QueuedThreadPool threadpool = (QueuedThreadPool) jetty.getThreadPool();
- metric.set(MetricDefinitions.JETTY_THREADPOOL_MAX_THREADS, threadpool.getMaxThreads(), null);
- metric.set(MetricDefinitions.JETTY_THREADPOOL_MIN_THREADS, threadpool.getMinThreads(), null);
- metric.set(MetricDefinitions.JETTY_THREADPOOL_RESERVED_THREADS, threadpool.getReservedThreads(), null);
- metric.set(MetricDefinitions.JETTY_THREADPOOL_BUSY_THREADS, threadpool.getBusyThreads(), null);
- metric.set(MetricDefinitions.JETTY_THREADPOOL_IDLE_THREADS, threadpool.getIdleThreads(), null);
- metric.set(MetricDefinitions.JETTY_THREADPOOL_TOTAL_THREADS, threadpool.getThreads(), null);
- metric.set(MetricDefinitions.JETTY_THREADPOOL_QUEUE_SIZE, threadpool.getQueueSize(), null);
- }
-
- private void setConnectorMetrics(JDiscServerConnector connector) {
- ConnectionStatistics statistics = connector.getStatistics();
- metric.set(MetricDefinitions.NUM_CONNECTIONS, statistics.getConnectionsTotal(), connector.getConnectorMetricContext());
- metric.set(MetricDefinitions.NUM_OPEN_CONNECTIONS, statistics.getConnections(), connector.getConnectorMetricContext());
- metric.set(MetricDefinitions.NUM_CONNECTIONS_OPEN_MAX, statistics.getConnectionsMax(), connector.getConnectorMetricContext());
- metric.set(MetricDefinitions.CONNECTION_DURATION_MAX, statistics.getConnectionDurationMax(), connector.getConnectorMetricContext());
- metric.set(MetricDefinitions.CONNECTION_DURATION_MEAN, statistics.getConnectionDurationMean(), connector.getConnectorMetricContext());
- metric.set(MetricDefinitions.CONNECTION_DURATION_STD_DEV, statistics.getConnectionDurationStdDev(), connector.getConnectorMetricContext());
- }
-
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletOutputStreamWriter.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletOutputStreamWriter.java
deleted file mode 100644
index b4d03385c3b..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletOutputStreamWriter.java
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.CompletionHandler;
-
-import javax.servlet.ServletOutputStream;
-import javax.servlet.WriteListener;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Deque;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
-import java.util.function.Consumer;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import static com.yahoo.jdisc.http.server.jetty.CompletionHandlerUtils.NOOP_COMPLETION_HANDLER;
-
-/**
- * @author Tony Vaagenes
- * @author bjorncs
- */
-public class ServletOutputStreamWriter {
- /** Rules:
- * 1) Don't modify the output stream without isReady returning true (write/flush/close).
- * Multiple modification calls without interleaving isReady calls are not allowed.
- * 2) If isReady returned false, no other calls should be made until the write listener is invoked.
- * 3) If the write listener sees isReady == false, it must not do any modifications before its next invocation.
- */
-
-
- private enum State {
- NOT_STARTED,
- WAITING_FOR_WRITE_POSSIBLE_CALLBACK,
- WAITING_FOR_BUFFER,
- WRITING_BUFFERS,
- FINISHED_OR_ERROR
- }
-
- private static final Logger log = Logger.getLogger(ServletOutputStreamWriter.class.getName());
-
- // If so, application code could fake a close by writing such a byte buffer.
- // The problem can be solved by filtering out zero-length byte buffers from application code.
- // Other ways to express this are also possible, e.g. with a 'closed' state checked when queue goes empty.
- private static final ByteBuffer CLOSE_STREAM_BUFFER = ByteBuffer.allocate(0);
-
- private final Object monitor = new Object();
-
- // GuardedBy("monitor")
- private State state = State.NOT_STARTED;
-
- // GuardedBy("state")
- private final ServletOutputStream outputStream;
- private final Executor executor;
-
- // GuardedBy("monitor")
- private final Deque<ResponseContentPart> responseContentQueue = new ArrayDeque<>();
-
- private final RequestMetricReporter metricReporter;
-
- /**
- * When this future completes there will be no more calls against the servlet output stream or servlet response.
- * The framework is still allowed to invoke us though.
- *
- * The future might complete in the servlet framework thread, user thread or executor thread.
- */
- final CompletableFuture<Void> finishedFuture = new CompletableFuture<>();
-
-
- public ServletOutputStreamWriter(ServletOutputStream outputStream, Executor executor, RequestMetricReporter metricReporter) {
- this.outputStream = outputStream;
- this.executor = executor;
- this.metricReporter = metricReporter;
- }
-
- public void sendErrorContentAndCloseAsync(ByteBuffer errorContent) {
- synchronized (monitor) {
- // Assert that no content has been written as it is too late to write error response if the response is committed.
- assertStateIs(state, State.NOT_STARTED);
- queueErrorContent_holdingLock(errorContent);
- state = State.WAITING_FOR_WRITE_POSSIBLE_CALLBACK;
- outputStream.setWriteListener(writeListener);
- }
- }
-
- private void queueErrorContent_holdingLock(ByteBuffer errorContent) {
- responseContentQueue.addLast(new ResponseContentPart(errorContent, NOOP_COMPLETION_HANDLER));
- responseContentQueue.addLast(new ResponseContentPart(CLOSE_STREAM_BUFFER, NOOP_COMPLETION_HANDLER));
- }
-
- public void writeBuffer(ByteBuffer buf, CompletionHandler handler) {
- boolean thisThreadShouldWrite = false;
-
- synchronized (monitor) {
- if (state == State.FINISHED_OR_ERROR) {
- executor.execute(() -> handler.failed(new IllegalStateException("ContentChannel already closed.")));
- return;
- }
- responseContentQueue.addLast(new ResponseContentPart(buf, handler));
- switch (state) {
- case NOT_STARTED:
- state = State.WAITING_FOR_WRITE_POSSIBLE_CALLBACK;
- outputStream.setWriteListener(writeListener);
- break;
- case WAITING_FOR_WRITE_POSSIBLE_CALLBACK:
- case WRITING_BUFFERS:
- break;
- case WAITING_FOR_BUFFER:
- thisThreadShouldWrite = true;
- state = State.WRITING_BUFFERS;
- break;
- default:
- throw new IllegalStateException("Invalid state " + state);
- }
- }
-
- if (thisThreadShouldWrite) {
- writeBuffersInQueueToOutputStream();
- }
- }
-
- public void close(CompletionHandler handler) {
- writeBuffer(CLOSE_STREAM_BUFFER, handler);
- }
-
- public void close() {
- close(NOOP_COMPLETION_HANDLER);
- }
-
- private void writeBuffersInQueueToOutputStream() {
- boolean lastOperationWasFlush = false;
-
- while (true) {
- ResponseContentPart contentPart;
-
- synchronized (monitor) {
- if (state == State.FINISHED_OR_ERROR) {
- return;
- }
- assertStateIs(state, State.WRITING_BUFFERS);
-
- if (!outputStream.isReady()) {
- state = State.WAITING_FOR_WRITE_POSSIBLE_CALLBACK;
- return;
- }
-
- contentPart = responseContentQueue.pollFirst();
-
- if (contentPart == null && lastOperationWasFlush) {
- state = State.WAITING_FOR_BUFFER;
- return;
- }
- }
-
- try {
- boolean isFlush = contentPart == null;
- if (isFlush) {
- outputStream.flush();
- lastOperationWasFlush = true;
- continue;
- }
- lastOperationWasFlush = false;
-
- if (contentPart.buf == CLOSE_STREAM_BUFFER) {
- callCompletionHandlerWhenDone(contentPart.handler, outputStream::close);
- setFinished(Optional.empty());
- return;
- } else {
- writeBufferToOutputStream(contentPart);
- }
- } catch (Throwable e) {
- setFinished(Optional.of(e));
- return;
- }
- }
- }
-
- private void setFinished(Optional<Throwable> e) {
- synchronized (monitor) {
- state = State.FINISHED_OR_ERROR;
- if (!responseContentQueue.isEmpty()) {
- failAllParts_holdingLock(e.orElse(new IllegalStateException("ContentChannel closed.")));
- }
- }
-
- assert !Thread.holdsLock(monitor);
- if (e.isPresent()) {
- finishedFuture.completeExceptionally(e.get());
- } else {
- finishedFuture.complete(null);
- }
- }
-
- private void failAllParts_holdingLock(Throwable e) {
- assert Thread.holdsLock(monitor);
-
- ArrayList<ResponseContentPart> failedParts = new ArrayList<>(responseContentQueue);
- responseContentQueue.clear();
-
- @SuppressWarnings("ThrowableInstanceNeverThrown")
- RuntimeException failReason = new RuntimeException("Failing due to earlier ServletOutputStream write failure", e);
-
- Consumer<ResponseContentPart> failCompletionHandler = responseContentPart ->
- runCompletionHandler_logOnExceptions(
- () -> responseContentPart.handler.failed(failReason));
-
- executor.execute(
- () -> failedParts.forEach(failCompletionHandler));
- }
-
- private void writeBufferToOutputStream(ResponseContentPart contentPart) throws Throwable {
- callCompletionHandlerWhenDone(contentPart.handler, () -> {
- ByteBuffer buffer = contentPart.buf;
- final int bytesToSend = buffer.remaining();
- try {
- if (buffer.hasArray()) {
- outputStream.write(buffer.array(), buffer.arrayOffset(), buffer.remaining());
- } else {
- final byte[] array = new byte[buffer.remaining()];
- buffer.get(array);
- outputStream.write(array);
- }
- metricReporter.successfulWrite(bytesToSend);
- } catch (Throwable throwable) {
- metricReporter.failedWrite();
- throw throwable;
- }
- });
- }
-
- private static void callCompletionHandlerWhenDone(CompletionHandler handler, IORunnable runnable) throws Exception {
- try {
- runnable.run();
- } catch (Throwable e) {
- runCompletionHandler_logOnExceptions(() -> handler.failed(e));
- throw e;
- }
- handler.completed(); //Might throw an exception, handling in the enclosing scope.
- }
-
- private static void runCompletionHandler_logOnExceptions(Runnable runnable) {
- try {
- runnable.run();
- } catch (Throwable e) {
- log.log(Level.WARNING, "Unexpected exception from CompletionHandler.", e);
- }
- }
-
- private static void assertStateIs(State currentState, State expectedState) {
- if (currentState != expectedState) {
- AssertionError error = new AssertionError("Expected state " + expectedState + ", got state " + currentState);
- log.log(Level.WARNING, "Assertion failed.", error);
- throw error;
- }
- }
-
- public void fail(Throwable t) {
- setFinished(Optional.of(t));
- }
-
- private final WriteListener writeListener = new WriteListener() {
- @Override
- public void onWritePossible() throws IOException {
- synchronized (monitor) {
- if (state == State.FINISHED_OR_ERROR) {
- return;
- }
-
- assertStateIs(state, State.WAITING_FOR_WRITE_POSSIBLE_CALLBACK);
- state = State.WRITING_BUFFERS;
- }
-
- writeBuffersInQueueToOutputStream();
- }
-
- @Override
- public void onError(Throwable t) {
- setFinished(Optional.of(t));
- }
- };
-
- private static class ResponseContentPart {
- public final ByteBuffer buf;
- public final CompletionHandler handler;
-
- public ResponseContentPart(ByteBuffer buf, CompletionHandler handler) {
- this.buf = buf;
- this.handler = handler;
- }
- }
-
- @FunctionalInterface
- private interface IORunnable {
- void run() throws IOException;
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletRequestReader.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletRequestReader.java
deleted file mode 100644
index 1882448757a..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletRequestReader.java
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.common.base.Preconditions;
-import com.yahoo.jdisc.handler.CompletionHandler;
-import com.yahoo.jdisc.handler.ContentChannel;
-
-import javax.servlet.ReadListener;
-import javax.servlet.ServletInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Finished when either
- * 1) There was an error
- * 2) There is no more data AND the number of pending completion handler invocations is 0
- *
- * Stops reading when a failure has happened.
- *
- * The reason for not waiting for pending completions in error situations
- * is that if the error is reported through the finishedFuture,
- * error reporting might be async.
- * Since we have tests that first reports errors and then closes the response content,
- * it's important that errors are delivered synchronously.
- */
-class ServletRequestReader implements ReadListener {
-
- private enum State {
- READING, ALL_DATA_READ, REQUEST_CONTENT_CLOSED
- }
-
- private static final Logger log = Logger.getLogger(ServletRequestReader.class.getName());
-
- private static final int BUFFER_SIZE_BYTES = 8 * 1024;
-
- private final Object monitor = new Object();
-
- private final ServletInputStream servletInputStream;
- private final ContentChannel requestContentChannel;
-
- private final Executor executor;
- private final RequestMetricReporter metricReporter;
-
- private int bytesRead;
-
- /**
- * Rules:
- * 1. If state != State.READING, then numberOfOutstandingUserCalls must not increase
- * 2. The _first time_ (finishedFuture is completed OR all data is read) AND numberOfOutstandingUserCalls == 0,
- * the request content channel should be closed
- * 3. finishedFuture must not be completed when holding the monitor
- * 4. completing finishedFuture with an exception must be done synchronously
- * to prioritize failures being transported to the response.
- * 5. All completion handlers (both for write and complete) must not be
- * called from a user (request handler) owned thread
- * (i.e. when being called from user code, don't call back into user code.)
- */
- // GuardedBy("monitor")
- private State state = State.READING;
-
- /**
- * Number of calls that we're waiting for from user code.
- * There are two classes of such calls:
- * 1) calls to requestContentChannel.write that we're waiting for to complete
- * 2) completion handlers given to requestContentChannel.write that the user must call.
- *
- * As long as we're waiting for such calls, we're not allowed to:
- * - close the request content channel (currently only required by tests)
- * - complete the finished future non-exceptionally,
- * since then we would not be able to report writeCompletionHandler.failed(exception) calls
- */
- // GuardedBy("monitor")
- private int numberOfOutstandingUserCalls = 0;
-
- /**
- * When this future completes there will be no more calls against the servlet input stream.
- * The framework is still allowed to invoke us though.
- *
- * The future might complete in the servlet framework thread, user thread or executor thread.
- *
- * All completions of finishedFuture, except those done when closing the request content channel,
- * must be followed by calls to either onAllDataRead or decreasePendingAndCloseRequestContentChannelConditionally.
- * Those two functions will ensure that the request content channel is closed at the right time.
- * If calls to those methods does not close the request content channel immediately,
- * there is some outstanding completion callback that will later come in and complete the request.
- */
- final CompletableFuture<Void> finishedFuture = new CompletableFuture<>();
-
- public ServletRequestReader(
- ServletInputStream servletInputStream,
- ContentChannel requestContentChannel,
- Executor executor,
- RequestMetricReporter metricReporter) {
-
- Preconditions.checkNotNull(servletInputStream);
- Preconditions.checkNotNull(requestContentChannel);
- Preconditions.checkNotNull(executor);
- Preconditions.checkNotNull(metricReporter);
-
- this.servletInputStream = servletInputStream;
- this.requestContentChannel = requestContentChannel;
- this.executor = executor;
- this.metricReporter = metricReporter;
- }
-
- @Override
- public void onDataAvailable() throws IOException {
- while (servletInputStream.isReady()) {
- final byte[] buffer = new byte[BUFFER_SIZE_BYTES];
- int numBytesRead;
-
- synchronized (monitor) {
- numBytesRead = servletInputStream.read(buffer);
- if (numBytesRead < 0) {
- // End of stream; there should be no more data available, ever.
- return;
- }
- if (state != State.READING) {
- //We have a failure, so no point in giving the buffer to the user.
- assert finishedFuture.isCompletedExceptionally();
- return;
- }
- //wait for both
- // - requestContentChannel.write to finish
- // - the write completion handler to be called
- numberOfOutstandingUserCalls += 2;
- bytesRead += numBytesRead;
- }
-
- try {
- requestContentChannel.write(ByteBuffer.wrap(buffer, 0, numBytesRead), writeCompletionHandler);
- metricReporter.successfulRead(numBytesRead);
- }
- catch (Throwable t) {
- finishedFuture.completeExceptionally(t);
- }
- finally {
- //decrease due to this method completing.
- decreaseOutstandingUserCallsAndCloseRequestContentChannelConditionally();
- }
- }
- }
-
- private void decreaseOutstandingUserCallsAndCloseRequestContentChannelConditionally() {
- boolean shouldCloseRequestContentChannel;
-
- synchronized (monitor) {
- assertStateNotEquals(state, State.REQUEST_CONTENT_CLOSED);
-
-
- numberOfOutstandingUserCalls -= 1;
-
- shouldCloseRequestContentChannel = numberOfOutstandingUserCalls == 0 &&
- (finishedFuture.isDone() || state == State.ALL_DATA_READ);
-
- if (shouldCloseRequestContentChannel) {
- state = State.REQUEST_CONTENT_CLOSED;
- }
- }
-
- if (shouldCloseRequestContentChannel) {
- executor.execute(this::closeCompletionHandler_noThrow);
- }
- }
-
- private void assertStateNotEquals(State state, State notExpectedState) {
- if (state == notExpectedState) {
- AssertionError e = new AssertionError("State should not be " + notExpectedState);
- log.log(Level.WARNING,
- "Assertion failed. " +
- "numberOfOutstandingUserCalls = " + numberOfOutstandingUserCalls +
- ", isDone = " + finishedFuture.isDone(),
- e);
- throw e;
- }
- }
-
- @Override
- public void onAllDataRead() {
- doneReading();
- }
-
- private void doneReading() {
- final boolean shouldCloseRequestContentChannel;
-
- int bytesRead;
- synchronized (monitor) {
- if (state != State.READING) {
- return;
- }
-
- state = State.ALL_DATA_READ;
-
- shouldCloseRequestContentChannel = numberOfOutstandingUserCalls == 0;
- if (shouldCloseRequestContentChannel) {
- state = State.REQUEST_CONTENT_CLOSED;
- }
- bytesRead = this.bytesRead;
- }
-
- if (shouldCloseRequestContentChannel) {
- closeCompletionHandler_noThrow();
- }
-
- metricReporter.contentSize(bytesRead);
- }
-
- private void closeCompletionHandler_noThrow() {
- //Cannot complete finishedFuture directly in completed(), as any exceptions after this fact will be ignored.
- // E.g.
- // close(CompletionHandler completionHandler) {
- // completionHandler.completed();
- // throw new RuntimeException
- // }
-
- CompletableFuture<Void> completedCalledFuture = new CompletableFuture<>();
-
- CompletionHandler closeCompletionHandler = new CompletionHandler() {
- @Override
- public void completed() {
- completedCalledFuture.complete(null);
- }
-
- @Override
- public void failed(final Throwable t) {
- finishedFuture.completeExceptionally(t);
- }
- };
-
- try {
- requestContentChannel.close(closeCompletionHandler);
- //if close did not cause an exception,
- // is it safe to pipe the result of the completionHandlerInvokedFuture into finishedFuture
- completedCalledFuture.whenComplete(this::setFinishedFuture);
- } catch (final Throwable t) {
- finishedFuture.completeExceptionally(t);
- }
- }
-
- private void setFinishedFuture(Void result, Throwable throwable) {
- if (throwable != null) {
- finishedFuture.completeExceptionally(throwable);
- } else {
- finishedFuture.complete(null);
- }
- }
-
- @Override
- public void onError(final Throwable t) {
- finishedFuture.completeExceptionally(t);
- doneReading();
- }
-
- private final CompletionHandler writeCompletionHandler = new CompletionHandler() {
- @Override
- public void completed() {
- decreaseOutstandingUserCallsAndCloseRequestContentChannelConditionally();
- }
-
- @Override
- public void failed(final Throwable t) {
- finishedFuture.completeExceptionally(t);
- decreaseOutstandingUserCallsAndCloseRequestContentChannelConditionally();
- }
- };
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletResponseController.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletResponseController.java
deleted file mode 100644
index 60b7878156f..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/ServletResponseController.java
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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.Response;
-import com.yahoo.jdisc.handler.BindingNotFoundException;
-import com.yahoo.jdisc.handler.CompletionHandler;
-import com.yahoo.jdisc.handler.ContentChannel;
-import com.yahoo.jdisc.handler.ResponseHandler;
-import com.yahoo.jdisc.http.HttpHeaders;
-import com.yahoo.jdisc.http.HttpResponse;
-import com.yahoo.jdisc.service.BindingSetNotFoundException;
-import org.eclipse.jetty.http.MimeTypes;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.nio.ByteBuffer;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import static com.yahoo.jdisc.http.server.jetty.CompletionHandlerUtils.NOOP_COMPLETION_HANDLER;
-
-/**
- * @author Tony Vaagenes
- * @author bjorncs
- */
-public class ServletResponseController {
-
- private static Logger log = Logger.getLogger(ServletResponseController.class.getName());
-
- /**
- * The servlet spec does not require (Http)ServletResponse nor ServletOutputStream to be thread-safe. Therefore,
- * we must provide our own synchronization, since we may attempt to access these objects simultaneously from
- * different threads. (The typical cause of this is when one thread is writing a response while another thread
- * throws an exception, causing the request to fail with an error response).
- */
- private final Object monitor = new Object();
-
- //servletResponse must not be modified after the response has been committed.
- private final HttpServletRequest servletRequest;
- private final HttpServletResponse servletResponse;
- private final boolean developerMode;
- private final ErrorResponseContentCreator errorResponseContentCreator = new ErrorResponseContentCreator();
-
- //all calls to the servletOutputStreamWriter must hold the monitor first to ensure visibility of servletResponse changes.
- private final ServletOutputStreamWriter servletOutputStreamWriter;
-
- // GuardedBy("monitor")
- private boolean responseCommitted = false;
-
- public ServletResponseController(
- HttpServletRequest servletRequest,
- HttpServletResponse servletResponse,
- Executor executor,
- RequestMetricReporter metricReporter,
- boolean developerMode) throws IOException {
-
- this.servletRequest = servletRequest;
- this.servletResponse = servletResponse;
- this.developerMode = developerMode;
- this.servletOutputStreamWriter =
- new ServletOutputStreamWriter(servletResponse.getOutputStream(), executor, metricReporter);
- }
-
-
- private static int getStatusCode(Throwable t) {
- if (t instanceof BindingNotFoundException) {
- return HttpServletResponse.SC_NOT_FOUND;
- } else if (t instanceof BindingSetNotFoundException) {
- return HttpServletResponse.SC_NOT_FOUND;
- } else if (t instanceof RequestException) {
- return ((RequestException)t).getResponseStatus();
- } else {
- return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
- }
- }
-
- private static String getReasonPhrase(Throwable t, boolean developerMode) {
- if (developerMode) {
- final StringWriter out = new StringWriter();
- t.printStackTrace(new PrintWriter(out));
- return out.toString();
- } else if (t.getMessage() != null) {
- return t.getMessage();
- } else {
- return t.toString();
- }
- }
-
-
- public void trySendError(Throwable t) {
- final boolean responseWasCommitted;
- try {
- synchronized (monitor) {
- String reasonPhrase = getReasonPhrase(t, developerMode);
- int statusCode = getStatusCode(t);
- responseWasCommitted = responseCommitted;
- if (!responseCommitted) {
- responseCommitted = true;
- sendErrorAsync(statusCode, reasonPhrase);
- }
- }
- } catch (Throwable e) {
- servletOutputStreamWriter.fail(t);
- return;
- }
-
- //Must be evaluated after state transition for test purposes(See ConformanceTestException)
- //Done outside the monitor since it causes a callback in tests.
- if (responseWasCommitted) {
- RuntimeException exceptionWithStackTrace = new RuntimeException(t);
- log.log(Level.FINE, "Response already committed, can't change response code", exceptionWithStackTrace);
- // TODO: should always have failed here, but that breaks test assumptions. Doing soft close instead.
- //assert !Thread.holdsLock(monitor);
- //servletOutputStreamWriter.fail(t);
- servletOutputStreamWriter.close();
- }
-
- }
-
- /**
- * Async version of {@link org.eclipse.jetty.server.Response#sendError(int, String)}.
- */
- private void sendErrorAsync(int statusCode, String reasonPhrase) {
- servletResponse.setHeader(HttpHeaders.Names.EXPIRES, null);
- servletResponse.setHeader(HttpHeaders.Names.LAST_MODIFIED, null);
- servletResponse.setHeader(HttpHeaders.Names.CACHE_CONTROL, null);
- servletResponse.setHeader(HttpHeaders.Names.CONTENT_TYPE, null);
- servletResponse.setHeader(HttpHeaders.Names.CONTENT_LENGTH, null);
- setStatus(servletResponse, statusCode, Optional.of(reasonPhrase));
-
- // If we are allowed to have a body
- if (statusCode != HttpServletResponse.SC_NO_CONTENT &&
- statusCode != HttpServletResponse.SC_NOT_MODIFIED &&
- statusCode != HttpServletResponse.SC_PARTIAL_CONTENT &&
- statusCode >= HttpServletResponse.SC_OK) {
- servletResponse.setHeader(HttpHeaders.Names.CACHE_CONTROL, "must-revalidate,no-cache,no-store");
- servletResponse.setContentType(MimeTypes.Type.TEXT_HTML_8859_1.toString());
- byte[] errorContent = errorResponseContentCreator
- .createErrorContent(servletRequest.getRequestURI(), statusCode, Optional.ofNullable(reasonPhrase));
- servletResponse.setContentLength(errorContent.length);
- servletOutputStreamWriter.sendErrorContentAndCloseAsync(ByteBuffer.wrap(errorContent));
- } else {
- servletResponse.setContentLength(0);
- servletOutputStreamWriter.close();
- }
- }
-
- /**
- * When this future completes there will be no more calls against the servlet output stream or servlet response.
- * The framework is still allowed to invoke us though.
- *
- * The future might complete in the servlet framework thread, user thread or executor thread.
- */
- public CompletableFuture<Void> finishedFuture() {
- return servletOutputStreamWriter.finishedFuture;
- }
-
- private void setResponse(Response jdiscResponse) {
- synchronized (monitor) {
- servletRequest.setAttribute(HttpResponseStatisticsCollector.requestTypeAttribute, jdiscResponse.getRequestType());
- if (responseCommitted) {
- log.log(Level.FINE,
- jdiscResponse.getError(),
- () -> "Response already committed, can't change response code. " +
- "From: " + servletResponse.getStatus() + ", To: " + jdiscResponse.getStatus());
-
- //TODO: should throw an exception here, but this breaks unit tests.
- //The failures will now instead happen when writing buffers.
- servletOutputStreamWriter.close();
- return;
- }
-
- setStatus_holdingLock(jdiscResponse, servletResponse);
- setHeaders_holdingLock(jdiscResponse, servletResponse);
- }
- }
-
- private static void setHeaders_holdingLock(Response jdiscResponse, HttpServletResponse servletResponse) {
- for (final Map.Entry<String, String> entry : jdiscResponse.headers().entries()) {
- servletResponse.addHeader(entry.getKey(), entry.getValue());
- }
-
- if (servletResponse.getContentType() == null) {
- servletResponse.setContentType("text/plain;charset=utf-8");
- }
- }
-
- private static void setStatus_holdingLock(Response jdiscResponse, HttpServletResponse servletResponse) {
- if (jdiscResponse instanceof HttpResponse) {
- setStatus(servletResponse, jdiscResponse.getStatus(), Optional.ofNullable(((HttpResponse) jdiscResponse).getMessage()));
- } else {
- setStatus(servletResponse, jdiscResponse.getStatus(), getErrorMessage(jdiscResponse));
- }
- }
-
- @SuppressWarnings("deprecation")
- private static void setStatus(HttpServletResponse response, int statusCode, Optional<String> reasonPhrase) {
- if (reasonPhrase.isPresent()) {
- // Sets the status line: a status code along with a custom message.
- // Using a custom status message is deprecated in the Servlet API. No alternative exist.
- response.setStatus(statusCode, reasonPhrase.get()); // DEPRECATED
- } else {
- response.setStatus(statusCode);
- }
- }
-
- private static Optional<String> getErrorMessage(Response jdiscResponse) {
- return Optional.ofNullable(jdiscResponse.getError()).flatMap(
- error -> Optional.ofNullable(error.getMessage()));
- }
-
-
- private void commitResponse() {
- synchronized (monitor) {
- responseCommitted = true;
- }
- }
-
- public final ResponseHandler responseHandler = new ResponseHandler() {
- @Override
- public ContentChannel handleResponse(Response response) {
- setResponse(response);
- return responseContentChannel;
- }
- };
-
- public final ContentChannel responseContentChannel = new ContentChannel() {
- @Override
- public void write(ByteBuffer buf, CompletionHandler handler) {
- commitResponse();
- servletOutputStreamWriter.writeBuffer(buf, handlerOrNoopHandler(handler));
- }
-
- @Override
- public void close(CompletionHandler handler) {
- commitResponse();
- servletOutputStreamWriter.close(handlerOrNoopHandler(handler));
- }
-
- private CompletionHandler handlerOrNoopHandler(CompletionHandler handler) {
- return handler != null ? handler : NOOP_COMPLETION_HANDLER;
- }
- };
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailedListener.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailedListener.java
deleted file mode 100644
index 822e1c2ffb8..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailedListener.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2020 Oath Inc. 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.Metric;
-import org.eclipse.jetty.io.ssl.SslHandshakeListener;
-
-import javax.net.ssl.SSLHandshakeException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Predicate;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.regex.Pattern;
-
-/**
- * A {@link SslHandshakeListener} that reports metrics for SSL handshake failures.
- *
- * @author bjorncs
- */
-class SslHandshakeFailedListener implements SslHandshakeListener {
-
- private final static Logger log = Logger.getLogger(SslHandshakeFailedListener.class.getName());
-
- private final Metric metric;
- private final String connectorName;
- private final int listenPort;
-
- SslHandshakeFailedListener(Metric metric, String connectorName, int listenPort) {
- this.metric = metric;
- this.connectorName = connectorName;
- this.listenPort = listenPort;
- }
-
- @Override
- public void handshakeFailed(Event event, Throwable throwable) {
- log.log(Level.FINE, throwable, () -> "Ssl handshake failed: " + throwable.getMessage());
- String metricName = SslHandshakeFailure.fromSslHandshakeException((SSLHandshakeException) throwable)
- .map(SslHandshakeFailure::metricName)
- .orElse(MetricDefinitions.SSL_HANDSHAKE_FAILURE_UNKNOWN);
- metric.add(metricName, 1L, metric.createContext(createDimensions(event)));
- }
-
- private Map<String, Object> createDimensions(Event event) {
- Map<String, Object> dimensions = new HashMap<>();
- dimensions.put(MetricDefinitions.NAME_DIMENSION, connectorName);
- dimensions.put(MetricDefinitions.PORT_DIMENSION, listenPort);
- Optional.ofNullable(event.getSSLEngine().getPeerHost())
- .ifPresent(clientIp -> dimensions.put(MetricDefinitions.CLIENT_IP_DIMENSION, clientIp));
- return Map.copyOf(dimensions);
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailure.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailure.java
deleted file mode 100644
index 64f70564137..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/SslHandshakeFailure.java
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright Verizon Media. 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.net.ssl.SSLHandshakeException;
-import java.util.Optional;
-import java.util.function.Predicate;
-import java.util.regex.Pattern;
-
-/**
- * Categorizes instances of {@link SSLHandshakeException}
- *
- * @author bjorncs
- */
-enum SslHandshakeFailure {
- INCOMPATIBLE_PROTOCOLS(
- MetricDefinitions.SSL_HANDSHAKE_FAILURE_INCOMPATIBLE_PROTOCOLS,
- "INCOMPATIBLE_CLIENT_PROTOCOLS",
- "(Client requested protocol \\S+? is not enabled or supported in server context" +
- "|The client supported protocol versions \\[.+?\\] are not accepted by server preferences \\[.+?\\])"),
- INCOMPATIBLE_CIPHERS(
- MetricDefinitions.SSL_HANDSHAKE_FAILURE_INCOMPATIBLE_CIPHERS,
- "INCOMPATIBLE_CLIENT_CIPHER_SUITES",
- "no cipher suites in common"),
- MISSING_CLIENT_CERT(
- MetricDefinitions.SSL_HANDSHAKE_FAILURE_MISSING_CLIENT_CERT,
- "MISSING_CLIENT_CERTIFICATE",
- "Empty (server|client) certificate chain"),
- EXPIRED_CLIENT_CERTIFICATE(
- MetricDefinitions.SSL_HANDSHAKE_FAILURE_EXPIRED_CLIENT_CERT,
- "EXPIRED_CLIENT_CERTIFICATE",
- // Note: this pattern will match certificates with too late notBefore as well
- "PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed"),
- INVALID_CLIENT_CERT(
- MetricDefinitions.SSL_HANDSHAKE_FAILURE_INVALID_CLIENT_CERT, // Includes mismatch of client certificate and private key
- "INVALID_CLIENT_CERTIFICATE",
- "(PKIX path (building|validation) failed: .+)|(Invalid CertificateVerify signature)");
-
- private final String metricName;
- private final String failureType;
- private final Predicate<String> messageMatcher;
-
- SslHandshakeFailure(String metricName, String failureType, String messagePattern) {
- this.metricName = metricName;
- this.failureType = failureType;
- this.messageMatcher = Pattern.compile(messagePattern).asMatchPredicate();
- }
-
- String metricName() { return metricName; }
- String failureType() { return failureType; }
-
- static Optional<SslHandshakeFailure> fromSslHandshakeException(SSLHandshakeException exception) {
- String message = exception.getMessage();
- if (message == null || message.isBlank()) return Optional.empty();
- for (SslHandshakeFailure failure : values()) {
- if (failure.messageMatcher.test(message)) {
- return Optional.of(failure);
- }
- }
- return Optional.empty();
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/TlsClientAuthenticationEnforcer.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/TlsClientAuthenticationEnforcer.java
deleted file mode 100644
index 10a6c4702b5..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/TlsClientAuthenticationEnforcer.java
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2019 Oath Inc. 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.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;
-
-import javax.servlet.DispatcherType;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static com.yahoo.jdisc.http.server.jetty.HttpServletRequestUtils.getConnectorLocalPort;
-
-/**
- * A Jetty handler that enforces TLS client authentication with configurable white list.
- *
- * @author bjorncs
- */
-class TlsClientAuthenticationEnforcer extends HandlerWrapper {
-
- private final Map<Integer, List<String>> portToWhitelistedPathsMapping;
-
- TlsClientAuthenticationEnforcer(List<ConnectorConfig> connectorConfigs) {
- portToWhitelistedPathsMapping = createWhitelistMapping(connectorConfigs);
- }
-
- @Override
- public void handle(String target, Request request, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException, ServletException {
- if (isHttpsRequest(request)
- && !isRequestToWhitelistedBinding(servletRequest)
- && !isClientAuthenticated(servletRequest)) {
- servletResponse.sendError(
- Response.Status.UNAUTHORIZED,
- "Client did not present a x509 certificate, " +
- "or presented a certificate not issued by any of the CA certificates in trust store.");
- } else {
- _handler.handle(target, request, servletRequest, servletResponse);
- }
- }
-
- private static Map<Integer, List<String>> createWhitelistMapping(List<ConnectorConfig> connectorConfigs) {
- var mapping = new HashMap<Integer, List<String>>();
- for (ConnectorConfig connectorConfig : connectorConfigs) {
- var enforcerConfig = connectorConfig.tlsClientAuthEnforcer();
- if (enforcerConfig.enable()) {
- mapping.put(connectorConfig.listenPort(), enforcerConfig.pathWhitelist());
- }
- }
- return mapping;
- }
-
- private boolean isHttpsRequest(Request request) {
- return request.getDispatcherType() == DispatcherType.REQUEST && request.getScheme().equalsIgnoreCase("https");
- }
-
- private boolean isRequestToWhitelistedBinding(HttpServletRequest servletRequest) {
- int localPort = getConnectorLocalPort(servletRequest);
- List<String> whiteListedPaths = getWhitelistedPathsForPort(localPort);
- if (whiteListedPaths == null) {
- return true; // enforcer not enabled
- }
- // Note: Same path definition as HttpRequestFactory.getUri()
- return whiteListedPaths.contains(servletRequest.getRequestURI());
- }
-
- private List<String> getWhitelistedPathsForPort(int localPort) {
- if (portToWhitelistedPathsMapping.containsKey(0) && portToWhitelistedPathsMapping.size() == 1) {
- return portToWhitelistedPathsMapping.get(0); // for unit tests which uses 0 for listen port
- }
- return portToWhitelistedPathsMapping.get(localPort);
- }
-
- private boolean isClientAuthenticated(HttpServletRequest servletRequest) {
- return servletRequest.getAttribute(ServletRequest.SERVLET_REQUEST_X509CERT) != null;
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/UnsupportedFilterInvoker.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/UnsupportedFilterInvoker.java
deleted file mode 100644
index ce52bccf52d..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/UnsupportedFilterInvoker.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2017 Yahoo Holdings. 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/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/VoidConnectionLog.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/VoidConnectionLog.java
deleted file mode 100644
index 5d33cc0835e..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/VoidConnectionLog.java
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright Verizon Media. 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.ConnectionLog;
-import com.yahoo.container.logging.ConnectionLogEntry;
-
-/**
- * @author mortent
- */
-public class VoidConnectionLog implements ConnectionLog {
-
- @Override
- public void log(ConnectionLogEntry connectionLogEntry) {
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/VoidRequestLog.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/VoidRequestLog.java
deleted file mode 100644
index 9db5ba99115..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/VoidRequestLog.java
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright Verizon Media. 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.RequestLog;
-import com.yahoo.container.logging.RequestLogEntry;
-
-/**
- * @author bjorncs
- */
-public class VoidRequestLog implements RequestLog {
-
- @Override public void log(RequestLogEntry entry) {}
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/package-info.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/package-info.java
deleted file mode 100644
index 189751aa9c0..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/server/jetty/package-info.java
+++ /dev/null
@@ -1,3 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-@com.yahoo.osgi.annotation.ExportPackage
-package com.yahoo.jdisc.http.server.jetty;
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletOrJdiscHttpRequest.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletOrJdiscHttpRequest.java
deleted file mode 100644
index eaac2b1c415..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletOrJdiscHttpRequest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.servlet;
-
-import com.yahoo.jdisc.HeaderFields;
-import com.yahoo.jdisc.http.Cookie;
-import com.yahoo.jdisc.http.HttpRequest;
-
-import java.net.SocketAddress;
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Common interface for JDisc and servlet http requests.
- */
-public interface ServletOrJdiscHttpRequest {
-
- void copyHeaders(HeaderFields target);
-
- Map<String, List<String>> parameters();
-
- URI getUri();
-
- HttpRequest.Version getVersion();
-
- String getRemoteHostAddress();
- String getRemoteHostName();
- int getRemotePort();
-
- void setRemoteAddress(SocketAddress remoteAddress);
-
- Map<String, Object> context();
-
- List<Cookie> decodeCookieHeader();
-
- void encodeCookieHeader(List<Cookie> cookies);
-
- long getConnectedAt(TimeUnit unit);
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletOrJdiscHttpResponse.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletOrJdiscHttpResponse.java
deleted file mode 100644
index a24ada05b3d..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletOrJdiscHttpResponse.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.servlet;
-
-import com.yahoo.jdisc.HeaderFields;
-import com.yahoo.jdisc.http.Cookie;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Common interface for JDisc and servlet http responses.
- */
-public interface ServletOrJdiscHttpResponse {
-
- public void copyHeaders(HeaderFields target);
-
- public int getStatus();
-
- public Map<String, Object> context();
-
- public List<Cookie> decodeSetCookieHeader();
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletRequest.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletRequest.java
deleted file mode 100644
index c945dc6d8b6..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletRequest.java
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.servlet;
-
-import com.google.common.collect.ImmutableMap;
-import com.yahoo.jdisc.HeaderFields;
-import com.yahoo.jdisc.http.Cookie;
-import com.yahoo.jdisc.http.HttpHeaders;
-import com.yahoo.jdisc.http.HttpRequest;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.net.URI;
-import java.security.Principal;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-import static com.yahoo.jdisc.http.server.jetty.HttpServletRequestUtils.getConnection;
-
-/**
- * Mutable wrapper to use a {@link javax.servlet.http.HttpServletRequest}
- * with JDisc security filters.
- * <p>
- * You might find it tempting to remove e.g. the getParameter... methods,
- * but keep in mind that this IS-A servlet request and must provide the
- * full api of such a request for use outside the "JDisc filter world".
- */
-public class ServletRequest extends HttpServletRequestWrapper implements ServletOrJdiscHttpRequest {
-
- public static final String JDISC_REQUEST_PRINCIPAL = "jdisc.request.principal";
- 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";
- public static final String SERVLET_REQUEST_SSL_SESSION_ID = "javax.servlet.request.ssl_session_id";
- public static final String SERVLET_REQUEST_CIPHER_SUITE = "javax.servlet.request.cipher_suite";
-
- private final HttpServletRequest request;
- private final HeaderFields headerFields;
- private final Set<String> removedHeaders = new HashSet<>();
- private final Map<String, Object> context = new HashMap<>();
- private final Map<String, List<String>> parameters = new HashMap<>();
- private final long connectedAt;
-
- private URI uri;
- private String remoteHostAddress;
- private String remoteHostName;
- private int remotePort;
-
- public ServletRequest(HttpServletRequest request, URI uri) {
- super(request);
- this.request = request;
-
- this.uri = uri;
-
- super.getParameterMap().forEach(
- (key, values) -> parameters.put(key, Arrays.asList(values)));
-
- remoteHostAddress = request.getRemoteAddr();
- remoteHostName = request.getRemoteHost();
- remotePort = request.getRemotePort();
- connectedAt = getConnection(request).getCreatedTimeStamp();
-
- headerFields = new HeaderFields();
- Enumeration<String> parentHeaders = request.getHeaderNames();
- while (parentHeaders.hasMoreElements()) {
- String name = parentHeaders.nextElement();
- Enumeration<String> values = request.getHeaders(name);
- while (values.hasMoreElements()) {
- headerFields.add(name, values.nextElement());
- }
- }
- }
-
- public HttpServletRequest getRequest() {
- return request;
- }
-
- @Override
- public Map<String, List<String>> parameters() {
- return parameters;
- }
-
- /* We cannot just return the parameter map from the request, as the map
- * may have been modified by the JDisc filters. */
- @Override
- public Map<String, String[]> getParameterMap() {
- Map<String, String[]> parameterMap = new HashMap<>();
- parameters().forEach(
- (key, values) ->
- parameterMap.put(key, values.toArray(new String[values.size()]))
- );
- return ImmutableMap.copyOf(parameterMap);
- }
-
- @Override
- public String getParameter(String name) {
- return parameters().containsKey(name) ?
- parameters().get(name).get(0) :
- null;
- }
-
- @Override
- public Enumeration<String> getParameterNames() {
- return Collections.enumeration(parameters.keySet());
- }
-
- @Override
- public String[] getParameterValues(String name) {
- List<String> values = parameters().get(name);
- return values != null ?
- values.toArray(new String[values.size()]) :
- null;
- }
-
- @Override
- public void copyHeaders(HeaderFields target) {
- target.addAll(headerFields);
- }
-
- @Override
- public Enumeration<String> getHeaders(String name) {
- if (removedHeaders.contains(name))
- return null;
-
- /* We don't need to merge headerFields and the servlet request's headers
- * because setHeaders() replaces the old value. There is no 'addHeader(s)'. */
- List<String> headerFields = this.headerFields.get(name);
- return headerFields == null || headerFields.isEmpty() ?
- super.getHeaders(name) :
- Collections.enumeration(headerFields);
- }
-
- @Override
- public String getHeader(String name) {
- if (removedHeaders.contains(name))
- return null;
-
- String headerField = headerFields.getFirst(name);
- return headerField != null ?
- headerField :
- super.getHeader(name);
- }
-
- @Override
- public Enumeration<String> getHeaderNames() {
- Set<String> names = new HashSet<>(Collections.list(super.getHeaderNames()));
- names.addAll(headerFields.keySet());
- names.removeAll(removedHeaders);
- return Collections.enumeration(names);
- }
-
- public void addHeader(String name, String value) {
- headerFields.add(name, value);
- removedHeaders.remove(name);
- }
-
- public void setHeaders(String name, String value) {
- headerFields.put(name, value);
- removedHeaders.remove(name);
- }
-
- public void setHeaders(String name, List<String> values) {
- headerFields.put(name, values);
- removedHeaders.remove(name);
- }
-
- public void removeHeaders(String name) {
- headerFields.remove(name);
- removedHeaders.add(name);
- }
-
- @Override
- public URI getUri() {
- return uri;
- }
-
- public void setUri(URI uri) {
- this.uri = uri;
- }
-
- @Override
- public HttpRequest.Version getVersion() {
- String protocol = request.getProtocol();
- try {
- return HttpRequest.Version.fromString(protocol);
- } catch (NullPointerException | IllegalArgumentException e) {
- throw new RuntimeException("Servlet request protocol '" + protocol +
- "' could not be mapped to a JDisc http version.", e);
- }
- }
-
- @Override
- public String getRemoteHostAddress() {
- return remoteHostAddress;
- }
-
- @Override
- public String getRemoteHostName() {
- return remoteHostName;
- }
-
- @Override
- public int getRemotePort() {
- return remotePort;
- }
-
- @Override
- public void setRemoteAddress(SocketAddress remoteAddress) {
- if (remoteAddress instanceof InetSocketAddress) {
- remoteHostAddress = ((InetSocketAddress) remoteAddress).getAddress().getHostAddress();
- remoteHostName = ((InetSocketAddress) remoteAddress).getAddress().getHostName();
- remotePort = ((InetSocketAddress) remoteAddress).getPort();
- } else
- throw new RuntimeException("Unknown SocketAddress class: " + remoteHostAddress.getClass().getName());
-
- }
-
- @Override
- public Map<String, Object> context() {
- return context;
- }
-
- @Override
- public javax.servlet.http.Cookie[] getCookies() {
- return decodeCookieHeader().stream().
- map(jdiscCookie -> new javax.servlet.http.Cookie(jdiscCookie.getName(), jdiscCookie.getValue())).
- toArray(javax.servlet.http.Cookie[]::new);
- }
-
- @Override
- public List<Cookie> decodeCookieHeader() {
- Enumeration<String> cookies = getHeaders(HttpHeaders.Names.COOKIE);
- if (cookies == null)
- return Collections.emptyList();
-
- List<Cookie> ret = new LinkedList<>();
- while(cookies.hasMoreElements())
- ret.addAll(Cookie.fromCookieHeader(cookies.nextElement()));
-
- return ret;
- }
-
- @Override
- public void encodeCookieHeader(List<Cookie> cookies) {
- setHeaders(HttpHeaders.Names.COOKIE, Cookie.toCookieHeader(cookies));
- }
-
- @Override
- public long getConnectedAt(TimeUnit unit) {
- return unit.convert(connectedAt, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public Principal getUserPrincipal() {
- // NOTE: The principal from the underlying servlet request is ignored. JDisc filters are the source-of-truth.
- return (Principal) request.getAttribute(JDISC_REQUEST_PRINCIPAL);
- }
-
- public void setUserPrincipal(Principal principal) {
- request.setAttribute(JDISC_REQUEST_PRINCIPAL, principal);
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletResponse.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletResponse.java
deleted file mode 100644
index 48c8f577de9..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/ServletResponse.java
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.servlet;
-
-import com.yahoo.jdisc.HeaderFields;
-import com.yahoo.jdisc.http.Cookie;
-import com.yahoo.jdisc.http.HttpHeaders;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * JDisc wrapper to use a {@link javax.servlet.http.HttpServletResponse}
- * with JDisc security filters.
- */
-public class ServletResponse extends HttpServletResponseWrapper implements ServletOrJdiscHttpResponse {
-
- private final HttpServletResponse response;
- private final Map<String, Object> context = new HashMap<>();
-
- public ServletResponse(HttpServletResponse response) {
- super(response);
- this.response = response;
- }
-
- public HttpServletResponse getResponse() {
- return response;
- }
-
- @Override
- public int getStatus() {
- return response.getStatus();
- }
-
- @Override
- public Map<String, Object> context() {
- return context;
- }
-
- @Override
- public void copyHeaders(HeaderFields target) {
- response.getHeaderNames().forEach( header ->
- target.add(header, new ArrayList<>(response.getHeaders(header)))
- );
- }
-
- @Override
- public List<Cookie> decodeSetCookieHeader() {
- Collection<String> cookies = getHeaders(HttpHeaders.Names.SET_COOKIE);
- if (cookies == null) {
- return Collections.emptyList();
- }
- List<Cookie> ret = new LinkedList<>();
- for (String cookie : cookies) {
- ret.add(Cookie.fromSetCookieHeader(cookie));
- }
- return ret;
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/package-info.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/package-info.java
deleted file mode 100644
index 0120f164cae..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/servlet/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-@ExportPackage
-package com.yahoo.jdisc.http.servlet;
-
-import com.yahoo.osgi.annotation.ExportPackage;
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslContextFactoryProvider.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslContextFactoryProvider.java
deleted file mode 100644
index c364116e0af..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/SslContextFactoryProvider.java
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.ssl;
-
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-/**
- * A provider that is used to configure SSL connectors in JDisc
- *
- * @author bjorncs
- */
-public interface SslContextFactoryProvider extends AutoCloseable {
-
- /**
- * This method is called once for each SSL connector.
- *
- * @return returns an instance of {@link SslContextFactory} for a given JDisc http server
- */
- SslContextFactory getInstance(String containerId, int port);
-
- @Override default void close() {}
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/ConfiguredSslContextFactoryProvider.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/ConfiguredSslContextFactoryProvider.java
deleted file mode 100644
index 90848f1dfd4..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/ConfiguredSslContextFactoryProvider.java
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.ssl.impl;
-
-import com.yahoo.jdisc.http.ConnectorConfig;
-import com.yahoo.jdisc.http.ConnectorConfig.Ssl.ClientAuth;
-import com.yahoo.jdisc.http.ssl.SslContextFactoryProvider;
-import com.yahoo.security.KeyUtils;
-import com.yahoo.security.SslContextBuilder;
-import com.yahoo.security.X509CertificateUtils;
-import com.yahoo.security.tls.AutoReloadingX509KeyManager;
-import com.yahoo.security.tls.TlsContext;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-import javax.net.ssl.SSLContext;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-
-import static com.yahoo.jdisc.http.ssl.impl.SslContextFactoryUtils.setEnabledCipherSuites;
-import static com.yahoo.jdisc.http.ssl.impl.SslContextFactoryUtils.setEnabledProtocols;
-
-/**
- * An implementation of {@link SslContextFactoryProvider} that uses the {@link ConnectorConfig} to construct a {@link SslContextFactory}.
- *
- * @author bjorncs
- */
-public class ConfiguredSslContextFactoryProvider implements SslContextFactoryProvider {
-
- private volatile AutoReloadingX509KeyManager keyManager;
- private final ConnectorConfig connectorConfig;
-
- public ConfiguredSslContextFactoryProvider(ConnectorConfig connectorConfig) {
- validateConfig(connectorConfig.ssl());
- this.connectorConfig = connectorConfig;
- }
-
- @Override
- public SslContextFactory getInstance(String containerId, int port) {
- ConnectorConfig.Ssl sslConfig = connectorConfig.ssl();
- if (!sslConfig.enabled()) throw new IllegalStateException();
-
- SslContextBuilder builder = new SslContextBuilder();
- if (sslConfig.certificateFile().isBlank() || sslConfig.privateKeyFile().isBlank()) {
- PrivateKey privateKey = KeyUtils.fromPemEncodedPrivateKey(getPrivateKey(sslConfig));
- List<X509Certificate> certificates = X509CertificateUtils.certificateListFromPem(getCertificate(sslConfig));
- builder.withKeyStore(privateKey, certificates);
- } else {
- keyManager = AutoReloadingX509KeyManager.fromPemFiles(Paths.get(sslConfig.privateKeyFile()), Paths.get(sslConfig.certificateFile()));
- builder.withKeyManager(keyManager);
- }
- List<X509Certificate> caCertificates = getCaCertificates(sslConfig)
- .map(X509CertificateUtils::certificateListFromPem)
- .orElse(List.of());
- builder.withTrustStore(caCertificates);
-
- SSLContext sslContext = builder.build();
-
- SslContextFactory.Server factory = new SslContextFactory.Server();
- factory.setSslContext(sslContext);
-
- factory.setNeedClientAuth(sslConfig.clientAuth() == ClientAuth.Enum.NEED_AUTH);
- factory.setWantClientAuth(sslConfig.clientAuth() == ClientAuth.Enum.WANT_AUTH);
-
- List<String> protocols = !sslConfig.enabledProtocols().isEmpty()
- ? sslConfig.enabledProtocols()
- : new ArrayList<>(TlsContext.getAllowedProtocols(sslContext));
- setEnabledProtocols(factory, sslContext, protocols);
-
- List<String> ciphers = !sslConfig.enabledCipherSuites().isEmpty()
- ? sslConfig.enabledCipherSuites()
- : new ArrayList<>(TlsContext.getAllowedCipherSuites(sslContext));
- setEnabledCipherSuites(factory, sslContext, ciphers);
-
- return factory;
- }
-
- @Override
- public void close() {
- if (keyManager != null) {
- keyManager.close();
- }
- }
-
- private static void validateConfig(ConnectorConfig.Ssl config) {
- if (!config.enabled()) return;
-
- if(hasBoth(config.certificate(), config.certificateFile()))
- throw new IllegalArgumentException("Specified both certificate and certificate file.");
-
- if(hasBoth(config.privateKey(), config.privateKeyFile()))
- throw new IllegalArgumentException("Specified both private key and private key file.");
-
- if(hasNeither(config.certificate(), config.certificateFile()))
- throw new IllegalArgumentException("Specified neither certificate or certificate file.");
-
- if(hasNeither(config.privateKey(), config.privateKeyFile()))
- throw new IllegalArgumentException("Specified neither private key or private key file.");
- }
-
- private static boolean hasBoth(String a, String b) { return !a.isBlank() && !b.isBlank(); }
- private static boolean hasNeither(String a, String b) { return a.isBlank() && b.isBlank(); }
-
- private static Optional<String> getCaCertificates(ConnectorConfig.Ssl sslConfig) {
- if (!sslConfig.caCertificate().isBlank()) {
- return Optional.of(sslConfig.caCertificate());
- } else if (!sslConfig.caCertificateFile().isBlank()) {
- return Optional.of(readToString(sslConfig.caCertificateFile()));
- } else {
- return Optional.empty();
- }
- }
-
- private static String getPrivateKey(ConnectorConfig.Ssl config) {
- if(!config.privateKey().isBlank()) return config.privateKey();
- return readToString(config.privateKeyFile());
- }
-
- private static String getCertificate(ConnectorConfig.Ssl config) {
- if(!config.certificate().isBlank()) return config.certificate();
- return readToString(config.certificateFile());
- }
-
- private static String readToString(String filename) {
- try {
- return Files.readString(Paths.get(filename), StandardCharsets.UTF_8);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/DefaultSslContextFactoryProvider.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/DefaultSslContextFactoryProvider.java
deleted file mode 100644
index 7395d2307af..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/DefaultSslContextFactoryProvider.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.ssl.impl;
-
-import com.google.inject.Inject;
-import com.yahoo.component.AbstractComponent;
-import com.yahoo.jdisc.http.ConnectorConfig;
-import com.yahoo.jdisc.http.ssl.SslContextFactoryProvider;
-import com.yahoo.security.tls.ConfigFileBasedTlsContext;
-import com.yahoo.security.tls.PeerAuthentication;
-import com.yahoo.security.tls.TlsContext;
-import com.yahoo.security.tls.TransportSecurityUtils;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-import java.nio.file.Path;
-
-/**
- * The default implementation of {@link SslContextFactoryProvider} to be injected into connectors without explicit ssl configuration.
- *
- * @author bjorncs
- */
-public class DefaultSslContextFactoryProvider extends AbstractComponent implements SslContextFactoryProvider {
-
- private final SslContextFactoryProvider instance;
-
- @Inject
- public DefaultSslContextFactoryProvider(ConnectorConfig connectorConfig) {
- this.instance = TransportSecurityUtils.getConfigFile()
- .map(configFile -> createTlsContextBasedProvider(connectorConfig, configFile))
- .orElseGet(ThrowingSslContextFactoryProvider::new);
- }
-
- private static SslContextFactoryProvider createTlsContextBasedProvider(ConnectorConfig connectorConfig, Path configFile) {
- return new StaticTlsContextBasedProvider(
- new ConfigFileBasedTlsContext(
- configFile, TransportSecurityUtils.getInsecureAuthorizationMode(), getPeerAuthenticationMode(connectorConfig)));
- }
-
- /**
- * Allows white-listing of user provided uri paths.
- * JDisc will delegate the enforcement of peer authentication from the TLS to the HTTP layer if {@link ConnectorConfig.TlsClientAuthEnforcer#enable()} is true.
- */
- private static PeerAuthentication getPeerAuthenticationMode(ConnectorConfig connectorConfig) {
- return connectorConfig.tlsClientAuthEnforcer().enable()
- ? PeerAuthentication.WANT
- : PeerAuthentication.NEED;
- }
-
- @Override
- public SslContextFactory getInstance(String containerId, int port) {
- return instance.getInstance(containerId, port);
- }
-
- @Override
- public void deconstruct() {
- instance.close();
- }
-
- private static class ThrowingSslContextFactoryProvider implements SslContextFactoryProvider {
- @Override
- public SslContextFactory getInstance(String containerId, int port) {
- throw new UnsupportedOperationException();
- }
- }
-
- private static class StaticTlsContextBasedProvider extends TlsContextBasedProvider {
- final TlsContext tlsContext;
-
- StaticTlsContextBasedProvider(TlsContext tlsContext) {
- this.tlsContext = tlsContext;
- }
-
- @Override
- protected TlsContext getTlsContext(String containerId, int port) {
- return tlsContext;
- }
-
- @Override public void deconstruct() { tlsContext.close(); }
- }
-} \ No newline at end of file
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/JDiscSslContextFactory.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/JDiscSslContextFactory.java
deleted file mode 100644
index 006a282e1e0..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/JDiscSslContextFactory.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.ssl.impl;
-
-import org.eclipse.jetty.util.resource.Resource;
-import org.eclipse.jetty.util.security.CertificateUtils;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-import java.security.KeyStore;
-import java.util.Objects;
-
-/**
- * A modified {@link SslContextFactory} that allows passwordless truststore in combination with password protected keystore.
- *
- * @author bjorncs
- */
-class JDiscSslContextFactory extends SslContextFactory.Server {
-
- private String trustStorePassword;
-
- @Override
- public void setTrustStorePassword(String password) {
- super.setTrustStorePassword(password);
- this.trustStorePassword = password;
- }
-
-
- // Overriden to stop Jetty from using the keystore password if no truststore password is specified.
- @Override
- protected KeyStore loadTrustStore(Resource resource) throws Exception {
- return CertificateUtils.getKeyStore(
- resource != null ? resource : getKeyStoreResource(),
- Objects.toString(getTrustStoreType(), getKeyStoreType()),
- Objects.toString(getTrustStoreProvider(), getKeyStoreProvider()),
- trustStorePassword);
- }
-
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/SslContextFactoryUtils.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/SslContextFactoryUtils.java
deleted file mode 100644
index a0172668cbb..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/SslContextFactoryUtils.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.ssl.impl;
-
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-import javax.net.ssl.SSLContext;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author bjorncs
- */
-class SslContextFactoryUtils {
-
- static void setEnabledCipherSuites(SslContextFactory factory, SSLContext sslContext, List<String> enabledCiphers) {
- String[] supportedCiphers = sslContext.getSupportedSSLParameters().getCipherSuites();
- factory.setIncludeCipherSuites(enabledCiphers.toArray(String[]::new));
- factory.setExcludeCipherSuites(createExclusionList(enabledCiphers, supportedCiphers));
- }
-
- static void setEnabledProtocols(SslContextFactory factory, SSLContext sslContext, List<String> enabledProtocols) {
- String[] supportedProtocols = sslContext.getSupportedSSLParameters().getProtocols();
- factory.setIncludeProtocols(enabledProtocols.toArray(String[]::new));
- factory.setExcludeProtocols(createExclusionList(enabledProtocols, supportedProtocols));
- }
-
- private static String[] createExclusionList(List<String> enabledValues, String[] supportedValues) {
- return Arrays.stream(supportedValues)
- .filter(supportedValue -> !enabledValues.contains(supportedValue))
- .toArray(String[]::new);
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/TlsContextBasedProvider.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/TlsContextBasedProvider.java
deleted file mode 100644
index 93d4f1dca3f..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/TlsContextBasedProvider.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.ssl.impl;
-
-import com.yahoo.component.AbstractComponent;
-import com.yahoo.jdisc.http.ssl.SslContextFactoryProvider;
-import com.yahoo.security.tls.TlsContext;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLParameters;
-import java.util.List;
-
-import static com.yahoo.jdisc.http.ssl.impl.SslContextFactoryUtils.setEnabledCipherSuites;
-import static com.yahoo.jdisc.http.ssl.impl.SslContextFactoryUtils.setEnabledProtocols;
-
-/**
- * A {@link SslContextFactoryProvider} that creates {@link SslContextFactory} instances from {@link TlsContext} instances.
- *
- * @author bjorncs
- */
-public abstract class TlsContextBasedProvider extends AbstractComponent implements SslContextFactoryProvider {
-
- protected abstract TlsContext getTlsContext(String containerId, int port);
-
- @Override
- public final SslContextFactory getInstance(String containerId, int port) {
- TlsContext tlsContext = getTlsContext(containerId, port);
- SSLContext sslContext = tlsContext.context();
- SSLParameters parameters = tlsContext.parameters();
-
- SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
- sslContextFactory.setSslContext(sslContext);
-
- sslContextFactory.setNeedClientAuth(parameters.getNeedClientAuth());
- sslContextFactory.setWantClientAuth(parameters.getWantClientAuth());
-
- setEnabledProtocols(sslContextFactory, sslContext, List.of(parameters.getProtocols()));
- setEnabledCipherSuites(sslContextFactory, sslContext, List.of(parameters.getCipherSuites()));
-
- return sslContextFactory;
- }
-}
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/package-info.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/package-info.java
deleted file mode 100644
index f337e9d010b..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/impl/package-info.java
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-/**
- * @author bjorncs
- */
-@ExportPackage
-package com.yahoo.jdisc.http.ssl.impl;
-
-import com.yahoo.osgi.annotation.ExportPackage; \ No newline at end of file
diff --git a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/package-info.java b/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/package-info.java
deleted file mode 100644
index 085e9dedf20..00000000000
--- a/jdisc_http_service/src/main/java/com/yahoo/jdisc/http/ssl/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-/**
- * @author bjorncs
- */
-@PublicApi
-@ExportPackage
-package com.yahoo.jdisc.http.ssl;
-
-import com.yahoo.api.annotations.PublicApi;
-import com.yahoo.osgi.annotation.ExportPackage;