ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/catalina/valves/LoadBalancerDrainingValve.java

Path
ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/catalina/valves/LoadBalancerDrainingValve.java
Status
scanned
Type
file
Name
LoadBalancerDrainingValve.java
Extension
.java
Programming language
Java
Mime type
text/html
File type
HTML document, ASCII text, with CRLF line terminators
Tag

      
    
Rootfs path

      
    
Size
10267 (10.0 KB)
MD5
35e7491b429d8df13a6780bf3ceaf3be
SHA1
d7cb04484add6bb5f29745137f98fc88930df58d
SHA256
2fe3e326041af19f58be3d8468fd53c44d00bf321103c9288e91a351b9d5b75a
SHA512

      
    
SHA1_git
106ae79fea1927098c57dbea2ed91e28a1637495
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
LoadBalancerDrainingValve.java | 10.0 KB |

/* * 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.valves; import java.io.IOException; import jakarta.servlet.ServletException; import jakarta.servlet.SessionCookieConfig; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletResponse; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.util.SessionConfig; /** * <p> * A Valve to detect situations where a load-balanced node receiving a request has been deactivated by the load balancer * (JK_LB_ACTIVATION=DIS) and the incoming request has no valid session. * </p> * <p> * In these cases, the user's session cookie should be removed if it exists, any ";jsessionid" parameter should be * removed from the request URI, and the client should be redirected to the same URI. This will cause the load-balanced * to re-balance the client to another server. * </p> * <p> * All this work is required because when the activation state of a node is DISABLED, the load-balancer will still send * requests to the node if they appear to have a session on that node. Since mod_jk doesn't actually know whether the * session id is valid, it will send the request blindly to the disabled node, which makes it take much longer to drain * the node than strictly necessary. * </p> * <p> * For testing purposes, a special cookie can be configured and used by a client to ignore the normal behavior of this * Valve and allow a client to get a new session on a DISABLED node. See {@link #setIgnoreCookieName} and * {@link #setIgnoreCookieValue} to configure those values. * </p> * <p> * This Valve should be installed earlier in the Valve pipeline than any authentication valves, as the redirection * should take place before an authentication valve would save a request to a protected resource. * </p> * * @see <a href="https://tomcat.apache.org/connectors-doc/generic_howto/loadbalancers.html">Load balancer * documentation</a> */ public class LoadBalancerDrainingValve extends ValveBase { /** * The request attribute key where the load-balancer's activation state can be found. */ public static final String ATTRIBUTE_KEY_JK_LB_ACTIVATION = "JK_LB_ACTIVATION"; /** * The HTTP response code that will be used to redirect the request back to the load-balancer for re-balancing. * Defaults to 307 (TEMPORARY_REDIRECT). HTTP status code 305 (USE_PROXY) might be an option, here. too. */ private int _redirectStatusCode = HttpServletResponse.SC_TEMPORARY_REDIRECT; /** * The name of the cookie which can be set to ignore the "draining" action of this Filter. This will allow a client * to contact the server without being re-balanced to another server. The expected cookie value can be set in the * {@link #_ignoreCookieValue}. The cookie name and value must match to avoid being re-balanced. */ private String _ignoreCookieName; /** * The value of the cookie which can be set to ignore the "draining" action of this Filter. This will allow a client * to contact the server without being re-balanced to another server. The expected cookie name can be set in the * {@link #_ignoreCookieName}. The cookie name and value must match to avoid being re-balanced. */ private String _ignoreCookieValue; public LoadBalancerDrainingValve() { super(true); // Supports async } // // Configuration parameters // /** * Sets the HTTP response code that will be used to redirect the request back to the load-balancer for re-balancing. * Defaults to 307 (TEMPORARY_REDIRECT). * * @param code The code to use for the redirect */ public void setRedirectStatusCode(int code) { _redirectStatusCode = code; } /** * Gets the name of the cookie that can be used to override the re-balancing behavior of this Valve when the current * node is in the DISABLED activation state. * * @return The cookie name used to ignore normal processing rules. * * @see #setIgnoreCookieValue */ public String getIgnoreCookieName() { return _ignoreCookieName; } /** * Sets the name of the cookie that can be used to override the re-balancing behavior of this Valve when the current * node is in the DISABLED activation state. There is no default value for this setting: the ability to override the * re-balancing behavior of this Valve is <i>disabled</i> by default. * * @param cookieName The cookie name to use to ignore normal processing rules. * * @see #getIgnoreCookieValue */ public void setIgnoreCookieName(String cookieName) { _ignoreCookieName = cookieName; } /** * Gets the expected value of the cookie that can be used to override the re-balancing behavior of this Valve when * the current node is in the DISABLED activation state. * * @return The cookie value used to ignore normal processing rules. * * @see #setIgnoreCookieValue */ public String getIgnoreCookieValue() { return _ignoreCookieValue; } /** * Sets the expected value of the cookie that can be used to override the re-balancing behavior of this Valve when * the current node is in the DISABLED activation state. The "ignore" cookie's value <b>must</b> be exactly equal to * this value in order to allow the client to override the re-balancing behavior. * * @param cookieValue The cookie value to use to ignore normal processing rules. * * @see #getIgnoreCookieValue */ public void setIgnoreCookieValue(String cookieValue) { _ignoreCookieValue = cookieValue; } @Override public void invoke(Request request, Response response) throws IOException, ServletException { if ("DIS".equals(request.getAttribute(ATTRIBUTE_KEY_JK_LB_ACTIVATION)) && !request.isRequestedSessionIdValid()) { if (containerLog.isDebugEnabled()) { containerLog.debug(sm.getString("loadBalancerDrainingValve.draining")); } boolean ignoreRebalance = false; Cookie sessionCookie = null; final Cookie[] cookies = request.getCookies(); final String sessionCookieName = SessionConfig.getSessionCookieName(request.getContext()); if (null != cookies) { for (Cookie cookie : cookies) { final String cookieName = cookie.getName(); if (containerLog.isTraceEnabled()) { containerLog.trace("Checking cookie " + cookieName + "=" + cookie.getValue()); } if (sessionCookieName.equals(cookieName) && request.getRequestedSessionId().equals(cookie.getValue())) { sessionCookie = cookie; } else if (null != _ignoreCookieName && _ignoreCookieName.equals(cookieName) && null != _ignoreCookieValue && _ignoreCookieValue.equals(cookie.getValue())) { // The client presenting a valid ignore-cookie value? ignoreRebalance = true; } } } if (ignoreRebalance) { if (containerLog.isDebugEnabled()) { containerLog.debug(sm.getString("loadBalancerDrainingValve.skip", _ignoreCookieName)); } getNext().invoke(request, response); return; } // Kill any session cookie that was found // TODO: Consider implications of SSO cookies if (null != sessionCookie) { sessionCookie.setPath(SessionConfig.getSessionCookiePath(request.getContext())); sessionCookie.setMaxAge(0); // Delete sessionCookie.setValue(""); // Purge the cookie's value // Replicate logic used to set secure attribute for session cookies SessionCookieConfig sessionCookieConfig = request.getContext().getServletContext().getSessionCookieConfig(); sessionCookie.setSecure(request.isSecure() || sessionCookieConfig.isSecure()); response.addCookie(sessionCookie); } // Re-write the URI if it contains a ;jsessionid parameter String uri = request.getRequestURI(); String sessionURIParamName = SessionConfig.getSessionUriParamName(request.getContext()); if (uri.contains(";" + sessionURIParamName + "=")) { uri = uri.replaceFirst(";" + sessionURIParamName + "=[^&?]*", ""); } String queryString = request.getQueryString(); if (null != queryString) { uri = uri + "?" + queryString; } // NOTE: Do not call response.encodeRedirectURL or the bad // sessionid will be restored response.setHeader("Location", uri); response.setStatus(_redirectStatusCode); } else { getNext().invoke(request, response); } } }
Detected license expression
apache-2.0
Detected license expression (SPDX)
Apache-2.0
Percentage of license text
10.62
Copyrights

      
    
Holders

      
    
Authors

      
    
License detections License expression License expression SPDX
apache_2_0-4bde3f57-78aa-4201-96bf-531cba09e7de apache-2.0 Apache-2.0
URL Start line End line
http://www.apache.org/licenses/LICENSE-2.0 9 9
https://tomcat.apache.org/connectors-doc/generic_howto/loadbalancers.html 56 56