-
Notifications
You must be signed in to change notification settings - Fork 3.4k
HBASE-29226 Migrate to jetty 12 with EE8 and bump java servlet to 4.0.1 #6783
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0731eaf
84b40cb
840c0db
c1aa3fc
be3457c
b98a44a
4f6e62b
ef20ec0
abb677a
a7519ad
1f54e07
25ec195
527d27e
dbff9fa
8c496dc
d4a9346
1c8dfa1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -72,6 +72,12 @@ | |
| import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; | ||
| import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableMap; | ||
| import org.apache.hbase.thirdparty.com.google.common.collect.Lists; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.ee8.servlet.DefaultServlet; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.ee8.servlet.FilterHolder; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.ee8.servlet.FilterMapping; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.ee8.servlet.ServletContextHandler; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.ee8.servlet.ServletHolder; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.ee8.webapp.WebAppContext; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.http.HttpVersion; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.server.Handler; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.server.HttpConfiguration; | ||
|
|
@@ -84,18 +90,10 @@ | |
| import org.apache.hbase.thirdparty.org.eclipse.jetty.server.SymlinkAllowedResourceAliasChecker; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.server.handler.ContextHandlerCollection; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.server.handler.ErrorHandler; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.server.handler.HandlerCollection; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.server.handler.RequestLogHandler; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.server.handler.gzip.GzipHandler; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.servlet.DefaultServlet; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.servlet.FilterHolder; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.servlet.FilterMapping; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.servlet.ServletContextHandler; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.servlet.ServletHolder; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.util.MultiException; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.util.ExceptionUtil; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.util.ssl.SslContextFactory; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.util.thread.QueuedThreadPool; | ||
| import org.apache.hbase.thirdparty.org.eclipse.jetty.webapp.WebAppContext; | ||
| import org.apache.hbase.thirdparty.org.glassfish.jersey.server.ResourceConfig; | ||
| import org.apache.hbase.thirdparty.org.glassfish.jersey.servlet.ServletContainer; | ||
|
|
||
|
|
@@ -654,23 +652,21 @@ private void initializeWebServer(String name, String hostName, Configuration con | |
|
|
||
| Preconditions.checkNotNull(webAppContext); | ||
|
|
||
| HandlerCollection handlerCollection = new HandlerCollection(); | ||
| Handler.Sequence handlers = new Handler.Sequence(); | ||
|
|
||
| ContextHandlerCollection contexts = new ContextHandlerCollection(); | ||
| RequestLog requestLog = HttpRequestLog.getRequestLog(name); | ||
|
|
||
| if (requestLog != null) { | ||
| RequestLogHandler requestLogHandler = new RequestLogHandler(); | ||
| requestLogHandler.setRequestLog(requestLog); | ||
| handlerCollection.addHandler(requestLogHandler); | ||
| webServer.setRequestLog(requestLog); | ||
| } | ||
|
|
||
| final String appDir = getWebAppsPath(name); | ||
|
|
||
| handlerCollection.addHandler(contexts); | ||
| handlerCollection.addHandler(webAppContext); | ||
| handlers.addHandler(contexts); | ||
| handlers.addHandler(webAppContext); | ||
|
|
||
| webServer.setHandler(handlerCollection); | ||
| webServer.setHandler(handlers); | ||
|
|
||
| webAppContext.setAttribute(ADMINS_ACL, adminsAcl); | ||
|
|
||
|
|
@@ -715,8 +711,9 @@ private void initializeWebServer(String name, String hostName, Configuration con | |
| // Check if disable stack trace property is configured | ||
| if (!conf.getBoolean(HTTP_UI_SHOW_STACKTRACE_KEY, true)) { | ||
| // Disable stack traces for server errors in UI | ||
| webServer.setErrorHandler(new ErrorHandler()); | ||
| webServer.getErrorHandler().setShowStacks(false); | ||
| ErrorHandler errorHandler = new ErrorHandler(); | ||
| errorHandler.setShowStacks(false); | ||
| webServer.setErrorHandler(errorHandler); | ||
| // Disable stack traces for web app errors in UI | ||
| webAppContext.getErrorHandler().setShowStacks(false); | ||
| } | ||
|
|
@@ -841,7 +838,8 @@ private void configureAliasChecks(ServletContextHandler context, boolean shouldS | |
| if (context.getAliasChecks().stream().anyMatch(aliasCheckerClass::isInstance)) { | ||
| LOG.debug("{} is already part of alias check list", aliasCheckerClass.getName()); | ||
| } else { | ||
| context.addAliasCheck(new SymlinkAllowedResourceAliasChecker(context)); | ||
| context | ||
| .addAliasCheck(new SymlinkAllowedResourceAliasChecker(context.getCoreContextHandler())); | ||
| LOG.debug("{} added to the alias check list", aliasCheckerClass.getName()); | ||
| } | ||
| LOG.info("Serving aliases allowed for /logs context"); | ||
|
|
@@ -1258,14 +1256,14 @@ public void start() throws IOException { | |
| } catch (IOException ex) { | ||
| LOG.info("HttpServer.start() threw a non Bind IOException", ex); | ||
| throw ex; | ||
| } catch (MultiException ex) { | ||
| LOG.info("HttpServer.start() threw a MultiException", ex); | ||
| } catch (Exception ex) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So Jetty just throws Exception here ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah dug a little harder found alternate for old exception, let me fall back to that and revet to old logic: https://github.com/jetty/jetty.project/blob/ccdbe1742eac511914869a53f0efc2075775d0b8/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/ExceptionUtil.java#L251 vs https://github.com/jetty/jetty.project/blob/jetty-9.4.x/jetty-util/src/main/java/org/eclipse/jetty/util/MultiException.java
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. HBase uses Jetty's method to check and throw as below. Older impl:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should catch Error as well now? WDYT?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only value we add here is logging.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or don't catch and rely on the other catch block ? |
||
| LOG.info("HttpServer.start() threw a Exception", ex); | ||
| throw ex; | ||
| } | ||
| // Make sure there is no handler failures. | ||
| Handler[] handlers = webServer.getHandlers(); | ||
| for (int i = 0; i < handlers.length; i++) { | ||
| if (handlers[i].isFailed()) { | ||
| List<Handler> handlers = webServer.getHandlers(); | ||
| for (Handler handler : handlers) { | ||
| if (handler.isFailed()) { | ||
| throw new IOException("Problem in starting http server. Server handlers failed"); | ||
| } | ||
| } | ||
|
|
@@ -1335,7 +1333,7 @@ void openListeners() throws Exception { | |
| * stop the server | ||
| */ | ||
| public void stop() throws Exception { | ||
| MultiException exception = null; | ||
| ExceptionUtil.MultiException exception = null; | ||
| for (ListenerInfo li : listeners) { | ||
| if (!li.isManaged) { | ||
| continue; | ||
|
|
@@ -1372,9 +1370,10 @@ public void stop() throws Exception { | |
|
|
||
| } | ||
|
|
||
| private MultiException addMultiException(MultiException exception, Exception e) { | ||
| private ExceptionUtil.MultiException addMultiException(ExceptionUtil.MultiException exception, | ||
| Exception e) { | ||
| if (exception == null) { | ||
| exception = new MultiException(); | ||
| exception = new ExceptionUtil.MultiException(); | ||
| } | ||
| exception.add(e); | ||
| return exception; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| /* | ||
| * 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.hadoop.hbase.http.log; | ||
|
|
||
| import java.io.BufferedReader; | ||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.io.InputStreamReader; | ||
| import java.net.HttpURLConnection; | ||
| import java.nio.charset.StandardCharsets; | ||
| import java.util.regex.Matcher; | ||
| import java.util.regex.Pattern; | ||
| import java.util.stream.Collectors; | ||
| import org.apache.yetus.audience.InterfaceAudience; | ||
|
|
||
| /** | ||
| * HTTP utility class to help propagate server side exception in log level servlet to the client | ||
| * over HTTP (HTML payload) It parses HTTP client connections and recreates the exception. | ||
| */ | ||
| @InterfaceAudience.Private | ||
| public class LogLevelExceptionUtils { | ||
|
|
||
| private static void throwEx(Throwable ex) { | ||
| LogLevelExceptionUtils.<RuntimeException> throwException(ex); | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| private static <E extends Throwable> void throwException(Throwable ex) throws E { | ||
| throw (E) ex; | ||
| } | ||
|
|
||
| /** | ||
| * Validates the status of an <code>HttpURLConnection</code> against an expected HTTP status code. | ||
| * If the current status code is not the expected one it throws an exception with a detail message | ||
| * using Server side error messages if available. | ||
| * <p> | ||
| * <b>NOTE: This is an adapted version of the original method in HttpServerUtil.java of Hadoop, | ||
| * but we handle for HTML response. | ||
| * @param conn the <code>HttpURLConnection</code>. | ||
| * @param expectedStatus the expected HTTP status code. | ||
| * @throws IOException thrown if the current status code does not match the expected one. | ||
| */ | ||
| @SuppressWarnings("unchecked") | ||
| public static void validateResponse(HttpURLConnection conn, int expectedStatus) | ||
| throws IOException { | ||
| if (conn.getResponseCode() != expectedStatus) { | ||
| Exception toThrow = null; | ||
|
|
||
| try (InputStream es = conn.getErrorStream()) { | ||
| if (es != null) { | ||
| try (InputStreamReader isr = new InputStreamReader(es, StandardCharsets.UTF_8); | ||
| BufferedReader reader = new BufferedReader(isr)) { | ||
| final String errorAsHtml = reader.lines().collect(Collectors.joining("\n")); | ||
|
|
||
| final String status = extractValue(errorAsHtml, "<th>STATUS:</th><td>(\\d+)</td>"); | ||
| final String message = extractValue(errorAsHtml, "<th>MESSAGE:</th><td>([^<]+)</td>"); | ||
| final String uri = extractValue(errorAsHtml, "<th>URI:</th><td>([^<]+)</td>"); | ||
| final String exception = extractValue(errorAsHtml, "<title>([^<]+)</title>"); | ||
|
|
||
| toThrow = new IOException( | ||
| String.format("HTTP status [%s], message [%s], URL [%s], exception [%s]", status, | ||
| message, uri, exception)); | ||
| } | ||
| } | ||
| } catch (Exception ex) { | ||
| toThrow = | ||
| new IOException(String.format("HTTP status [%d], message [%s], URL [%s], exception [%s]", | ||
| conn.getResponseCode(), conn.getResponseMessage(), conn.getURL(), ex), ex); | ||
| } | ||
| if (toThrow != null) { | ||
| throwEx(toThrow); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static String extractValue(String html, String regex) { | ||
| Pattern pattern = Pattern.compile(regex); | ||
| Matcher matcher = pattern.matcher(html); | ||
| if (matcher.find()) { | ||
| return matcher.group(1); | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| } |
Uh oh!
There was an error while loading. Please reload this page.