You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2023/10/02 12:02:30 UTC
[tomcat] 02/03: Remove support for HTTP/2 server push
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit d28d6836b80d0709c56a3ab24d515788498c760e
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Oct 2 11:56:41 2023 +0100
Remove support for HTTP/2 server push
---
java/org/apache/catalina/connector/Request.java | 19 -
.../apache/catalina/connector/RequestFacade.java | 14 -
.../catalina/core/ApplicationHttpRequest.java | 18 -
.../catalina/core/ApplicationPushBuilder.java | 427 ---------------------
.../apache/catalina/core/LocalStrings.properties | 5 -
.../catalina/core/LocalStrings_fr.properties | 5 -
.../catalina/core/LocalStrings_ja.properties | 5 -
.../catalina/core/LocalStrings_ko.properties | 5 -
.../catalina/core/LocalStrings_zh_CN.properties | 5 -
.../apache/catalina/filters/RemoteIpFilter.java | 16 -
.../catalina/core/TestApplicationPushBuilder.java | 72 ----
.../catalina/filters/TesterHttpServletRequest.java | 6 -
.../apache/coyote/http2/TestHttp2Section_6_6.java | 127 ------
webapps/docs/changelog.xml | 5 +
.../WEB-INF/classes/http2/SimpleImagePush.java | 59 ---
webapps/examples/WEB-INF/web.xml | 10 -
webapps/examples/servlets/index.html | 11 -
17 files changed, 5 insertions(+), 804 deletions(-)
diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java
index 8e800464be..cc9a515f96 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -65,7 +65,6 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpUpgradeHandler;
import jakarta.servlet.http.Part;
-import jakarta.servlet.http.PushBuilder;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
@@ -79,7 +78,6 @@ import org.apache.catalina.Wrapper;
import org.apache.catalina.core.ApplicationFilterChain;
import org.apache.catalina.core.ApplicationMapping;
import org.apache.catalina.core.ApplicationPart;
-import org.apache.catalina.core.ApplicationPushBuilder;
import org.apache.catalina.core.ApplicationSessionCookieConfig;
import org.apache.catalina.core.AsyncContextImpl;
import org.apache.catalina.mapper.MappingData;
@@ -1866,23 +1864,6 @@ public class Request implements HttpServletRequest {
}
- @Override
- public PushBuilder newPushBuilder() {
- return newPushBuilder(this);
- }
-
-
- public PushBuilder newPushBuilder(HttpServletRequest request) {
- AtomicBoolean result = new AtomicBoolean();
- coyoteRequest.action(ActionCode.IS_PUSH_SUPPORTED, result);
- if (result.get()) {
- return new ApplicationPushBuilder(this, request);
- } else {
- return null;
- }
- }
-
-
@SuppressWarnings("unchecked")
@Override
public <T extends HttpUpgradeHandler> T upgrade(Class<T> httpUpgradeHandlerClass)
diff --git a/java/org/apache/catalina/connector/RequestFacade.java b/java/org/apache/catalina/connector/RequestFacade.java
index 956790888f..1a2f335076 100644
--- a/java/org/apache/catalina/connector/RequestFacade.java
+++ b/java/org/apache/catalina/connector/RequestFacade.java
@@ -40,7 +40,6 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpUpgradeHandler;
import jakarta.servlet.http.Part;
-import jakarta.servlet.http.PushBuilder;
import org.apache.tomcat.util.res.StringManager;
@@ -573,19 +572,6 @@ public class RequestFacade implements HttpServletRequest {
}
- @Override
- public PushBuilder newPushBuilder() {
- checkFacade();
- return request.newPushBuilder();
- }
-
-
- public PushBuilder newPushBuilder(HttpServletRequest request) {
- checkFacade();
- return this.request.newPushBuilder(request);
- }
-
-
@Override
public boolean isTrailerFieldsReady() {
checkFacade();
diff --git a/java/org/apache/catalina/core/ApplicationHttpRequest.java b/java/org/apache/catalina/core/ApplicationHttpRequest.java
index 1b93479d32..14f0855b9e 100644
--- a/java/org/apache/catalina/core/ApplicationHttpRequest.java
+++ b/java/org/apache/catalina/core/ApplicationHttpRequest.java
@@ -32,19 +32,15 @@ import java.util.NoSuchElementException;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
-import jakarta.servlet.ServletRequest;
-import jakarta.servlet.ServletRequestWrapper;
import jakarta.servlet.http.HttpServletMapping;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpSession;
-import jakarta.servlet.http.PushBuilder;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.Manager;
import org.apache.catalina.Session;
-import org.apache.catalina.connector.RequestFacade;
import org.apache.catalina.util.ParameterMap;
import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.URLEncoder;
@@ -597,20 +593,6 @@ class ApplicationHttpRequest extends HttpServletRequestWrapper {
}
- @Override
- public PushBuilder newPushBuilder() {
- ServletRequest current = getRequest();
- while (current instanceof ServletRequestWrapper) {
- current = ((ServletRequestWrapper) current).getRequest();
- }
- if (current instanceof RequestFacade) {
- return ((RequestFacade) current).newPushBuilder(this);
- } else {
- return null;
- }
- }
-
-
// -------------------------------------------------------- Package Methods
/**
diff --git a/java/org/apache/catalina/core/ApplicationPushBuilder.java b/java/org/apache/catalina/core/ApplicationPushBuilder.java
deleted file mode 100644
index 90250326ac..0000000000
--- a/java/org/apache/catalina/core/ApplicationPushBuilder.java
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.catalina.core;
-
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import jakarta.servlet.SessionTrackingMode;
-import jakarta.servlet.http.Cookie;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpSession;
-import jakarta.servlet.http.PushBuilder;
-
-import org.apache.catalina.Context;
-import org.apache.catalina.authenticator.AuthenticatorBase;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.util.SessionConfig;
-import org.apache.coyote.ActionCode;
-import org.apache.tomcat.util.buf.HexUtils;
-import org.apache.tomcat.util.buf.MessageBytes;
-import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
-import org.apache.tomcat.util.http.CookieProcessor;
-import org.apache.tomcat.util.http.parser.HttpParser;
-import org.apache.tomcat.util.res.StringManager;
-
-public class ApplicationPushBuilder implements PushBuilder {
-
- private static final StringManager sm = StringManager.getManager(ApplicationPushBuilder.class);
- private static final Set<String> DISALLOWED_METHODS = new HashSet<>();
-
- static {
- DISALLOWED_METHODS.add("POST");
- DISALLOWED_METHODS.add("PUT");
- DISALLOWED_METHODS.add("DELETE");
- DISALLOWED_METHODS.add("CONNECT");
- DISALLOWED_METHODS.add("OPTIONS");
- DISALLOWED_METHODS.add("TRACE");
- }
-
- private final HttpServletRequest baseRequest;
- private final Request catalinaRequest;
- private final org.apache.coyote.Request coyoteRequest;
- private final String sessionCookieName;
- private final String sessionPathParameterName;
- private final boolean addSessionCookie;
- private final boolean addSessionPathParameter;
-
- private final Map<String,List<String>> headers = new CaseInsensitiveKeyMap<>();
- private final List<Cookie> cookies = new ArrayList<>();
- private String method = "GET";
- private String path;
- private String queryString;
- private String sessionId;
- private String userName;
-
-
- public ApplicationPushBuilder(Request catalinaRequest, HttpServletRequest request) {
-
- baseRequest = request;
- this.catalinaRequest = catalinaRequest;
- coyoteRequest = catalinaRequest.getCoyoteRequest();
-
- // Populate the initial list of HTTP headers
- Enumeration<String> headerNames = request.getHeaderNames();
- while (headerNames.hasMoreElements()) {
- String headerName = headerNames.nextElement();
- List<String> values = new ArrayList<>();
- headers.put(headerName, values);
- Enumeration<String> headerValues = request.getHeaders(headerName);
- while (headerValues.hasMoreElements()) {
- values.add(headerValues.nextElement());
- }
- }
-
- // Remove the headers
- headers.remove("if-match");
- headers.remove("if-none-match");
- headers.remove("if-modified-since");
- headers.remove("if-unmodified-since");
- headers.remove("if-range");
- headers.remove("range");
- headers.remove("expect");
- headers.remove("authorization");
- headers.remove("referer");
- // Also remove the cookie header since it will be regenerated
- headers.remove("cookie");
-
- // set the referer header
- StringBuffer referer = request.getRequestURL();
- if (request.getQueryString() != null) {
- referer.append('?');
- referer.append(request.getQueryString());
- }
- addHeader("referer", referer.toString());
-
- // Session
- Context context = catalinaRequest.getContext();
- sessionCookieName = SessionConfig.getSessionCookieName(context);
- sessionPathParameterName = SessionConfig.getSessionUriParamName(context);
-
- HttpSession session = request.getSession(false);
- if (session != null) {
- sessionId = session.getId();
- }
- if (sessionId == null) {
- sessionId = request.getRequestedSessionId();
- }
- if (!request.isRequestedSessionIdFromCookie() && !request.isRequestedSessionIdFromURL() && sessionId != null) {
- Set<SessionTrackingMode> sessionTrackingModes =
- request.getServletContext().getEffectiveSessionTrackingModes();
- addSessionCookie = sessionTrackingModes.contains(SessionTrackingMode.COOKIE);
- addSessionPathParameter = sessionTrackingModes.contains(SessionTrackingMode.URL);
- } else {
- addSessionCookie = request.isRequestedSessionIdFromCookie();
- addSessionPathParameter = request.isRequestedSessionIdFromURL();
- }
-
- // Cookies
- if (request.getCookies() != null) {
- cookies.addAll(Arrays.asList(request.getCookies()));
- }
- for (Cookie responseCookie : catalinaRequest.getResponse().getCookies()) {
- if (responseCookie.getMaxAge() < 0) {
- // Path information not available so can only remove based on
- // name.
- cookies.removeIf(cookie -> cookie.getName().equals(responseCookie.getName()));
- } else {
- cookies.add(new Cookie(responseCookie.getName(), responseCookie.getValue()));
- }
- }
- if (cookies.size() > 0) {
- List<String> cookieValues = new ArrayList<>(1);
- cookieValues.add(generateCookieHeader(cookies, catalinaRequest.getContext().getCookieProcessor()));
- headers.put("cookie", cookieValues);
- }
-
- // Authentication
- if (catalinaRequest.getPrincipal() != null) {
- if ((session == null) || catalinaRequest.getSessionInternal(false).getPrincipal() == null ||
- !(context.getAuthenticator() instanceof AuthenticatorBase) ||
- !((AuthenticatorBase) context.getAuthenticator()).getCache()) {
- // Set a username only if there is no session cache for the principal
- userName = catalinaRequest.getPrincipal().getName();
- }
- setHeader("authorization", "x-push");
- }
- }
-
- @Override
- public PushBuilder path(String path) {
- if (path.startsWith("/")) {
- this.path = path;
- } else {
- String contextPath = baseRequest.getContextPath();
- int len = contextPath.length() + path.length() + 1;
- StringBuilder sb = new StringBuilder(len);
- sb.append(contextPath);
- sb.append('/');
- sb.append(path);
- this.path = sb.toString();
- }
- return this;
- }
-
-
- @Override
- public String getPath() {
- return path;
- }
-
-
- @Override
- public PushBuilder method(String method) {
- String upperMethod = method.trim().toUpperCase(Locale.ENGLISH);
- if (DISALLOWED_METHODS.contains(upperMethod) || upperMethod.length() == 0) {
- throw new IllegalArgumentException(sm.getString("applicationPushBuilder.methodInvalid", upperMethod));
- }
- // Check a token was supplied
- if (!HttpParser.isToken(upperMethod)) {
- throw new IllegalArgumentException(sm.getString("applicationPushBuilder.methodNotToken", upperMethod));
- }
- this.method = method;
- return this;
- }
-
-
- @Override
- public String getMethod() {
- return method;
- }
-
-
- @Override
- public PushBuilder queryString(String queryString) {
- this.queryString = queryString;
- return this;
- }
-
-
- @Override
- public String getQueryString() {
- return queryString;
- }
-
-
- @Override
- public PushBuilder sessionId(String sessionId) {
- this.sessionId = sessionId;
- return this;
- }
-
-
- @Override
- public String getSessionId() {
- return sessionId;
- }
-
-
- @Override
- public PushBuilder addHeader(String name, String value) {
- headers.computeIfAbsent(name, k -> new ArrayList<>()).add(value);
- return this;
- }
-
-
- @Override
- public PushBuilder setHeader(String name, String value) {
- List<String> values = headers.get(name);
- if (values == null) {
- values = new ArrayList<>();
- headers.put(name, values);
- } else {
- values.clear();
- }
- values.add(value);
-
- return this;
- }
-
-
- @Override
- public PushBuilder removeHeader(String name) {
- headers.remove(name);
-
- return this;
- }
-
-
- @Override
- public Set<String> getHeaderNames() {
- return Collections.unmodifiableSet(headers.keySet());
- }
-
-
- @Override
- public String getHeader(String name) {
- List<String> values = headers.get(name);
- if (values == null) {
- return null;
- } else {
- return values.get(0);
- }
- }
-
-
- @Override
- public void push() {
- if (path == null) {
- throw new IllegalStateException(sm.getString("pushBuilder.noPath"));
- }
-
- org.apache.coyote.Request pushTarget = new org.apache.coyote.Request();
-
- pushTarget.method().setString(method);
- // The next three are implied by the Javadoc getPath()
- pushTarget.serverName().setString(baseRequest.getServerName());
- pushTarget.setServerPort(baseRequest.getServerPort());
- pushTarget.scheme().setString(baseRequest.getScheme());
-
- // Copy headers
- for (Map.Entry<String,List<String>> header : headers.entrySet()) {
- for (String value : header.getValue()) {
- pushTarget.getMimeHeaders().addValue(header.getKey()).setString(value);
- }
- }
-
- // Path and query string
- int queryIndex = path.indexOf('?');
- String pushPath;
- String pushQueryString = null;
- if (queryIndex > -1) {
- pushPath = path.substring(0, queryIndex);
- if (queryIndex + 1 < path.length()) {
- pushQueryString = path.substring(queryIndex + 1);
- }
- } else {
- pushPath = path;
- }
-
- // Session ID (do this before setting the path since it may change it)
- if (sessionId != null) {
- if (addSessionPathParameter) {
- pushPath = pushPath + ";" + sessionPathParameterName + "=" + sessionId;
- pushTarget.addPathParameter(sessionPathParameterName, sessionId);
- }
- if (addSessionCookie) {
- String sessionCookieHeader = sessionCookieName + "=" + sessionId;
- MessageBytes mb = pushTarget.getMimeHeaders().getValue("cookie");
- if (mb == null) {
- mb = pushTarget.getMimeHeaders().addValue("cookie");
- mb.setString(sessionCookieHeader);
- } else {
- mb.setString(mb.getString() + ";" + sessionCookieHeader);
- }
- }
- }
-
- // Undecoded path - just %nn encoded
- pushTarget.requestURI().setString(pushPath);
- pushTarget.decodedURI().setString(decode(pushPath, catalinaRequest.getConnector().getURICharset()));
-
- // Query string
- if (pushQueryString == null && queryString != null) {
- pushTarget.queryString().setString(queryString);
- } else if (pushQueryString != null && queryString == null) {
- pushTarget.queryString().setString(pushQueryString);
- } else if (pushQueryString != null && queryString != null) {
- pushTarget.queryString().setString(pushQueryString + "&" + queryString);
- }
-
- // Authorization
- if (userName != null) {
- pushTarget.getRemoteUser().setString(userName);
- pushTarget.setRemoteUserNeedsAuthorization(true);
- }
-
- coyoteRequest.action(ActionCode.PUSH_REQUEST, pushTarget);
-
- // Reset for next call to this method
- path = null;
- headers.remove("if-none-match");
- headers.remove("if-modified-since");
- }
-
-
- // Package private so it can be tested. charsetName must be in lower case.
- static String decode(String input, Charset charset) {
- int start = input.indexOf('%');
- int end = 0;
-
- // Shortcut
- if (start == -1) {
- return input;
- }
-
- StringBuilder result = new StringBuilder(input.length());
- while (start != -1) {
- // Found the start of a %nn sequence. Copy everything from the last
- // end to this start to the output.
- result.append(input.substring(end, start));
- // Advance the end 3 characters: %nn
- end = start + 3;
- while (end < input.length() && input.charAt(end) == '%') {
- end += 3;
- }
- result.append(decodePercentSequence(input.substring(start, end), charset));
- start = input.indexOf('%', end);
- }
- // Append the remaining text
- result.append(input.substring(end));
-
- return result.toString();
- }
-
-
- private static String decodePercentSequence(String sequence, Charset charset) {
- byte[] bytes = new byte[sequence.length() / 3];
- for (int i = 0; i < bytes.length; i += 3) {
- bytes[i] = (byte) ((HexUtils.getDec(sequence.charAt(1 + 3 * i)) << 4) +
- HexUtils.getDec(sequence.charAt(2 + 3 * i)));
- }
-
- return new String(bytes, charset);
- }
-
-
- private static String generateCookieHeader(List<Cookie> cookies, CookieProcessor cookieProcessor) {
- StringBuilder result = new StringBuilder();
- boolean first = true;
- for (Cookie cookie : cookies) {
- if (first) {
- first = false;
- } else {
- result.append(';');
- }
- // The cookie header value generated by the CookieProcessor was
- // originally intended for the Set-Cookie header on the response.
- // However, if passed a Cookie with just a name and value set it
- // will generate an appropriate header for the Cookie header on the
- // pushed request.
- result.append(cookieProcessor.generateHeader(cookie, null));
- }
- return result.toString();
- }
-}
diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties
index fd59aa65dc..d3d47814d0 100644
--- a/java/org/apache/catalina/core/LocalStrings.properties
+++ b/java/org/apache/catalina/core/LocalStrings.properties
@@ -60,9 +60,6 @@ applicationFilterRegistration.nullInitParams=Unable to set initialisation parame
applicationHttpRequest.fragmentInDispatchPath=The fragment in dispatch path [{0}] has been removed
-applicationPushBuilder.methodInvalid=The HTTP method for a push request must be both cacheable and safe but [{0}] is not
-applicationPushBuilder.methodNotToken=HTTP methods must be tokens but [{0}] contains a non-token character
-
applicationServletRegistration.setServletSecurity.iae=Null constraint specified for servlet [{0}] deployed to context with name [{1}]
applicationServletRegistration.setServletSecurity.ise=Security constraints can''t be added to servlet [{0}] deployed to context with name [{1}] as the context has already been initialised
@@ -162,8 +159,6 @@ naming.wsdlFailed=Failed to find wsdl file: [{0}]
noPluggabilityServletContext.notAllowed=Section 4.4 of the Servlet 3.0 specification does not permit this method to be called from a ServletContextListener that was not defined in web.xml, a web-fragment.xml file nor annotated with @WebListener
-pushBuilder.noPath=It is illegal to call push() before setting a path
-
propertiesRoleMappingListener.roleMappingFileNull=Role mapping file cannot be null
propertiesRoleMappingListener.roleMappingFileEmpty=Role mapping file cannot be empty
propertiesRoleMappingListener.roleMappingFileFail=Failed to load role mapping file [{0}]
diff --git a/java/org/apache/catalina/core/LocalStrings_fr.properties b/java/org/apache/catalina/core/LocalStrings_fr.properties
index f77785045b..cd627970f9 100644
--- a/java/org/apache/catalina/core/LocalStrings_fr.properties
+++ b/java/org/apache/catalina/core/LocalStrings_fr.properties
@@ -60,9 +60,6 @@ applicationFilterRegistration.nullInitParams=Impossible de fixer les paramètres
applicationHttpRequest.fragmentInDispatchPath=Le fragment dans le chemin de dispatch [{0}] a été enlevé
-applicationPushBuilder.methodInvalid=La méthode HTTP pour une requête push doit être à la fois être sans danger et pouvoir être mise en cache, mais [{0}] ne correspond pas
-applicationPushBuilder.methodNotToken=Les méthodes HTTP doivent être des "token", mais [{0}] contient un caractère invalide dans un token.
-
applicationServletRegistration.setServletSecurity.iae=Contrainte nulle spécifiée pour le Servlet [{0}] déployé dans le contexte avec le nom [{1}]
applicationServletRegistration.setServletSecurity.ise=Les contraintes de sécurité ne peuvent pas être ajoutées au Servlet [{0}] déployé dans le contexte [{1}] car le contexte a déjà été initialisé
@@ -168,8 +165,6 @@ propertiesRoleMappingListener.roleMappingFileEmpty=Le fichier d'association de r
propertiesRoleMappingListener.roleMappingFileFail=Erreur de chargement du fichier d''association de rôles [{0}]
propertiesRoleMappingListener.roleMappingFileNull=Le fichier d'association de rôles ne peut être null
-pushBuilder.noPath=Il est interdit d'appeler push() avant de fixer un chemin
-
standardContext.applicationListener=Erreur lors de la configuration de la classe d''écoute de l''application (application listener) [{0}]
standardContext.applicationSkipped=L'installation des écouteurs (listeners) de l'application a été sautée suite aux erreurs précédentes
standardContext.backgroundProcess.instanceManager=Exception lors du traitement d''arrière plan du gestionnaire d''instances [{0}]
diff --git a/java/org/apache/catalina/core/LocalStrings_ja.properties b/java/org/apache/catalina/core/LocalStrings_ja.properties
index 40006c8836..7faf8abedc 100644
--- a/java/org/apache/catalina/core/LocalStrings_ja.properties
+++ b/java/org/apache/catalina/core/LocalStrings_ja.properties
@@ -60,9 +60,6 @@ applicationFilterRegistration.nullInitParams=キー [{0}] または値 [{1}] の
applicationHttpRequest.fragmentInDispatchPath=ディスパッチパス [{0}] 中のフラグメントは除去されました
-applicationPushBuilder.methodInvalid=プッシュリクエストの HTTP メソッドはキャッシュ可能、かつ、安全でなければなりません。[{0}] は指定できません。
-applicationPushBuilder.methodNotToken=HTTP メソッド [{0}] にトークンとして利用できない文字が含まれています。
-
applicationServletRegistration.setServletSecurity.iae=サーブレット [{0}] に指定されたNULL制約が、名前 [{1}] のコンテキストに配備されました
applicationServletRegistration.setServletSecurity.ise=コンテキストが既に初期化されているため、名前 [{1}] のコンテキストに配備されたサーブレット [{0}] にセキュリティ制約を追加できません
@@ -168,8 +165,6 @@ propertiesRoleMappingListener.roleMappingFileEmpty=ロール マッピング フ
propertiesRoleMappingListener.roleMappingFileFail=ロール マッピング ファイル [{0}] のロードに失敗しました
propertiesRoleMappingListener.roleMappingFileNull=ロール マッピング ファイルを null にすることはできません
-pushBuilder.noPath=path を設定する前に push() を呼び出すことはできません。
-
standardContext.applicationListener=クラス [{0}] のアプリケーションリスナの設定中にエラーが発生しました
standardContext.applicationSkipped=前のエラーのためにアプリケーションリスナのインストールをスキップします
standardContext.backgroundProcess.instanceManager=インスタンスマネージャ [{0}] のバックグラウンドプロセス処理中の例外
diff --git a/java/org/apache/catalina/core/LocalStrings_ko.properties b/java/org/apache/catalina/core/LocalStrings_ko.properties
index 6d735f15cb..6ed9a1005d 100644
--- a/java/org/apache/catalina/core/LocalStrings_ko.properties
+++ b/java/org/apache/catalina/core/LocalStrings_ko.properties
@@ -60,9 +60,6 @@ applicationFilterRegistration.nullInitParams=널인 이름 또는 값 때문에,
applicationHttpRequest.fragmentInDispatchPath=디스패치 경로 [{0}](으)로부터 URI fragment를 제거했습니다.
-applicationPushBuilder.methodInvalid=PUSH 요청을 위한 HTTP 메소드는 반드시 캐시 가능하고 안전해야 하는데, [{0}]은(는) 그렇지 않습니다.
-applicationPushBuilder.methodNotToken=HTTP 메소드들은 토큰들이어야 하지만, [{0}]은(는) 토큰이 아닌 문자를 포함하고 있습니다.
-
applicationServletRegistration.setServletSecurity.iae=[{1}](이)라는 이름의 컨텍스트에 배치된 서블릿 [{0}]을(를) 위해, 널 constraint가 지정되었습니다.
applicationServletRegistration.setServletSecurity.ise=컨텍스트가 이미 초기화되었기에, [{1}](이)라는 이름의 컨텍스트에 배치된 서블릿 [{0}]에 security constraint들이 추가될 수 없습니다.
@@ -159,8 +156,6 @@ naming.wsdlFailed=wsdl 파일을 찾지 못했습니다: [{0}]
noPluggabilityServletContext.notAllowed=Servlet 3.0 스펙의 4.4 장에 따르면, web.xml 또는 web-fragment.xml 파일에 정의되지 않거나 @WebListener로 annotate되지 않은, ServletContextListener에서 이 메소드를 호출하는 것은 허용되지 않습니다.
-pushBuilder.noPath=경로를 설정하기 전에 push()를 호출하는 것은 불허됩니다.
-
standardContext.applicationListener=클래스 [{0}]의 애플리케이션 리스너를 설정하는 중 오류 발생
standardContext.applicationSkipped=이전 오류(들)로 인하여, 애플리케이션 리스너들을 설치하는 것을 건너뛰었습니다.
standardContext.backgroundProcess.instanceManager=인스턴스 매니저 [{0}]을(를) 백그라운드 프로세스에서 처리 중 예외 발생
diff --git a/java/org/apache/catalina/core/LocalStrings_zh_CN.properties b/java/org/apache/catalina/core/LocalStrings_zh_CN.properties
index 1ce8fc779b..534134732a 100644
--- a/java/org/apache/catalina/core/LocalStrings_zh_CN.properties
+++ b/java/org/apache/catalina/core/LocalStrings_zh_CN.properties
@@ -61,9 +61,6 @@ applicationFilterRegistration.nullInitParams=由于name和(或)value为null,
applicationHttpRequest.fragmentInDispatchPath=调度路径[{0}]中的片段已被删除
-applicationPushBuilder.methodInvalid=推送请求的HTTP方法必须既可缓存又安全,但是[{0}]不是
-applicationPushBuilder.methodNotToken=HTTP方法必须是令牌(token),但 [{0}] 包含非令牌字符
-
applicationServletRegistration.setServletSecurity.iae=为部署到名为[{1}]的上下文的Servlet[{0}]指定的空约束
applicationServletRegistration.setServletSecurity.ise=无法将安全性约束添加到已部署到名称为[{1}]的上下文的servlet [{0}]中,因为上下文已被初始化
@@ -164,8 +161,6 @@ propertiesRoleMappingListener.roleMappingFileEmpty=角色映射文件不能为
propertiesRoleMappingListener.roleMappingFileFail=加载角色映射文件[{0}]失败
propertiesRoleMappingListener.roleMappingFileNull=角色映射文件不能为NULL
-pushBuilder.noPath=在设置路径之前调用push()是非法的
-
standardContext.applicationListener=配置应用程序监听器[{0}]错误
standardContext.applicationSkipped=由于以前的错误,已跳过安装应用程序侦听器
standardContext.backgroundProcess.instanceManager=异常处理实例管理器[{0}]后台进程
diff --git a/java/org/apache/catalina/filters/RemoteIpFilter.java b/java/org/apache/catalina/filters/RemoteIpFilter.java
index 13a0eb7bf9..038f4a95b7 100644
--- a/java/org/apache/catalina/filters/RemoteIpFilter.java
+++ b/java/org/apache/catalina/filters/RemoteIpFilter.java
@@ -34,16 +34,13 @@ import jakarta.servlet.FilterChain;
import jakarta.servlet.GenericFilter;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
-import jakarta.servlet.ServletRequestWrapper;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.PushBuilder;
import org.apache.catalina.AccessLog;
import org.apache.catalina.Globals;
-import org.apache.catalina.connector.RequestFacade;
import org.apache.catalina.util.RequestUtil;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
@@ -640,19 +637,6 @@ public class RemoteIpFilter extends GenericFilter {
public StringBuffer getRequestURL() {
return RequestUtil.getRequestURL(this);
}
-
- @Override
- public PushBuilder newPushBuilder() {
- ServletRequest current = getRequest();
- while (current instanceof ServletRequestWrapper) {
- current = ((ServletRequestWrapper) current).getRequest();
- }
- if (current instanceof RequestFacade) {
- return ((RequestFacade) current).newPushBuilder(this);
- } else {
- return null;
- }
- }
}
diff --git a/test/org/apache/catalina/core/TestApplicationPushBuilder.java b/test/org/apache/catalina/core/TestApplicationPushBuilder.java
deleted file mode 100644
index e939084b64..0000000000
--- a/test/org/apache/catalina/core/TestApplicationPushBuilder.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.catalina.core;
-
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestApplicationPushBuilder {
-
- @Test
- public void test01() {
- doTest("foo", StandardCharsets.UTF_8, "foo");
- }
-
- @Test
- public void test02() {
- doTest("/foo", StandardCharsets.UTF_8, "/foo");
- }
-
- @Test
- public void test03() {
- doTest("%20foo", StandardCharsets.UTF_8, " foo");
- }
-
- @Test
- public void test04() {
- doTest("fo%20o", StandardCharsets.UTF_8, "fo o");
- }
-
- @Test
- public void test05() {
- doTest("foo%20", StandardCharsets.UTF_8, "foo ");
- }
-
- @Test
- public void test06() {
- doTest("%21foo", StandardCharsets.UTF_8, "!foo");
- }
-
- @Test
- public void test07() {
- doTest("fo%21o", StandardCharsets.UTF_8, "fo!o");
- }
-
- @Test
- public void test08() {
- doTest("foo%21", StandardCharsets.UTF_8, "foo!");
- }
-
-
- private void doTest(String input, Charset charset, String expected) {
- String result = ApplicationPushBuilder.decode(input, charset);
- Assert.assertEquals(expected, result);
- }
-}
diff --git a/test/org/apache/catalina/filters/TesterHttpServletRequest.java b/test/org/apache/catalina/filters/TesterHttpServletRequest.java
index 449963e6ec..e03737b83a 100644
--- a/test/org/apache/catalina/filters/TesterHttpServletRequest.java
+++ b/test/org/apache/catalina/filters/TesterHttpServletRequest.java
@@ -45,7 +45,6 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpUpgradeHandler;
import jakarta.servlet.http.Part;
-import jakarta.servlet.http.PushBuilder;
public class TesterHttpServletRequest implements HttpServletRequest {
@@ -431,11 +430,6 @@ public class TesterHttpServletRequest implements HttpServletRequest {
throw new RuntimeException("Not implemented");
}
- @Override
- public PushBuilder newPushBuilder() {
- throw new RuntimeException("Not implemented");
- }
-
@Override
public boolean isTrailerFieldsReady() {
throw new RuntimeException("Not implemented");
diff --git a/test/org/apache/coyote/http2/TestHttp2Section_6_6.java b/test/org/apache/coyote/http2/TestHttp2Section_6_6.java
deleted file mode 100644
index ae61fd31f1..0000000000
--- a/test/org/apache/coyote/http2/TestHttp2Section_6_6.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.coyote.http2;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServlet;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.PushBuilder;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.apache.catalina.Context;
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.startup.Tomcat;
-
-/**
- * Unit tests for Section 6.5 of <a href="https://tools.ietf.org/html/rfc7540">RFC 7540</a>.
- */
-public class TestHttp2Section_6_6 extends Http2TestBase {
-
-
- @Test
- public void testPushPromise() throws Exception {
- http2Connect();
-
- // Build the push request
- byte[] frameHeader = new byte[9];
- ByteBuffer headersPayload = ByteBuffer.allocate(128);
-
- List<Header> headers = new ArrayList<>(4);
- headers.add(new Header(":method", "GET"));
- headers.add(new Header(":scheme", "http"));
- headers.add(new Header(":path", "/push"));
- headers.add(new Header(":authority", "localhost:" + getPort()));
-
- buildGetRequest(frameHeader, headersPayload, null, headers, 3);
-
- // Send the request
- writeFrame(frameHeader, headersPayload);
-
- // Read the response
- // push promise
- parser.readFrame();
- // stream 3 response headers
- parser.readFrame();
- // stream 3 response body
- parser.readFrame();
- // stream 2 response headers
- parser.readFrame();
- // stream 2 response body
- parser.readFrame();
-
- String trace = output.getTrace();
-
- Assert.assertTrue(trace, trace.contains("3-PushPromise-2"));
- Assert.assertTrue(trace, trace.contains("2-Header-[:status]-[200]"));
- Assert.assertTrue(trace, trace.contains("2-Body-8192"));
- Assert.assertTrue(trace, trace.contains("3-Header-[:status]-[200]"));
- Assert.assertTrue(trace, trace.contains("3-Body-1024"));
- }
-
-
- @Override
- protected void configureAndStartWebApplication() throws LifecycleException {
- Tomcat tomcat = getTomcatInstance();
-
- Context ctxt = tomcat.addContext("", null);
-
- Tomcat.addServlet(ctxt, "simple", new SimpleServlet());
- ctxt.addServletMappingDecoded("/simple", "simple");
-
- Tomcat.addServlet(ctxt, "push", new PushServlet());
- ctxt.addServletMappingDecoded("/push", "push");
-
- tomcat.start();
- }
-
-
- private static class PushServlet extends HttpServlet {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- PushBuilder pb = req.newPushBuilder();
- pb.path("/simple").push();
-
- // Generate content with a simple known format.
- resp.setContentType("application/octet-stream");
-
- int count = 512;
-
- // Two bytes per entry (1k data)
- resp.setContentLengthLong(count * 2);
-
- OutputStream os = resp.getOutputStream();
- byte[] data = new byte[2];
- for (int i = 0; i < count; i++) {
- data[0] = (byte) (i & 0xFF);
- data[1] = (byte) ((i >> 8) & 0xFF);
- os.write(data);
- }
- }
- }
-}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 0addab5e1f..9b1c426bfd 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -165,6 +165,11 @@
for the Servlet 6.1 specification. It will be replaced in a future
Tomcat 11 milestone with support for 103 early hints. (markt)
</update>
+ <update>
+ Remove support for HTTP/2 server push. Calls to
+ <code>newPushBuilder()</code> will always return <code>null</code>.
+ (markt)
+ </update>
</changelog>
</subsection>
<subsection name="Jasper">
diff --git a/webapps/examples/WEB-INF/classes/http2/SimpleImagePush.java b/webapps/examples/WEB-INF/classes/http2/SimpleImagePush.java
deleted file mode 100644
index 3da6895904..0000000000
--- a/webapps/examples/WEB-INF/classes/http2/SimpleImagePush.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package http2;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServlet;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.PushBuilder;
-
-public class SimpleImagePush extends HttpServlet {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
-
- resp.setCharacterEncoding("UTF-8");
- resp.setContentType("text/html");
- PrintWriter pw = resp.getWriter();
-
- PushBuilder pb = req.newPushBuilder();
- if (pb != null) {
- pb.path("servlets/images/code.gif");
- pb.push();
- pw.println("<html>");
- pw.println("<body>");
- pw.println("<p>The following image was provided via a push request.</p>");
- pw.println("<img src=\"" + getServletContext().getContextPath() + "/servlets/images/code.gif\"/>");
- pw.println("</body>");
- pw.println("</html>");
- pw.flush();
- } else {
- pw.println("<html>");
- pw.println("<body>");
- pw.println("<p>Server push requests are not supported by this protocol.</p>");
- pw.println("</body>");
- pw.println("</html>");
- }
- }
-}
diff --git a/webapps/examples/WEB-INF/web.xml b/webapps/examples/WEB-INF/web.xml
index 12d865ef2d..442aa032e8 100644
--- a/webapps/examples/WEB-INF/web.xml
+++ b/webapps/examples/WEB-INF/web.xml
@@ -383,16 +383,6 @@
<url-pattern>/servlets/nonblocking/numberwriter</url-pattern>
</servlet-mapping>
- <!-- Server Push examples -->
- <servlet>
- <servlet-name>simpleimagepush</servlet-name>
- <servlet-class>http2.SimpleImagePush</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>simpleimagepush</servlet-name>
- <url-pattern>/servlets/serverpush/simpleimage</url-pattern>
- </servlet-mapping>
-
<!-- Trailer examples -->
<servlet>
<servlet-name>responsetrailer</servlet-name>
diff --git a/webapps/examples/servlets/index.html b/webapps/examples/servlets/index.html
index d07a277e9c..5a36096d17 100644
--- a/webapps/examples/servlets/index.html
+++ b/webapps/examples/servlets/index.html
@@ -165,17 +165,6 @@ for clarity.</p>
<td style="width: 30%;"></td>
</tr>
-<tr>
- <th colspan="3">Servlet 4.0 Server Push examples</th>
-</tr>
-<tr>
- <td>Simple image push</td>
- <td style="width: 30%;">
- <a href="serverpush/simpleimage"><img src="images/execute.gif" alt=""> Execute</a>
- </td>
- <td style="width: 30%;"></td>
-</tr>
-
<tr>
<th colspan="3">Servlet 4.0 Trailer Field examples</th>
</tr>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org