You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by wu...@apache.org on 2022/11/26 08:08:45 UTC
[ambari] branch trunk updated: AMBARI-25552: Improve stack-trace disablement on HTTP 500 error response from the server (#3573)
This is an automated email from the ASF dual-hosted git repository.
wuzhiguo pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push:
new fb752e20e3 AMBARI-25552: Improve stack-trace disablement on HTTP 500 error response from the server (#3573)
fb752e20e3 is described below
commit fb752e20e3f295d19237b0eef342b3b4df0e0a85
Author: Yu Hou <52...@qq.com>
AuthorDate: Sat Nov 26 16:08:37 2022 +0800
AMBARI-25552: Improve stack-trace disablement on HTTP 500 error response from the server (#3573)
---
.../ambari/server/api/AmbariErrorHandler.java | 35 +++++
.../server/api/AmbariViewErrorHandlerProxy.java | 118 ++++++++++++++++
.../server/controller/AmbariHandlerList.java | 43 ++++--
.../ambari/server/controller/AmbariServer.java | 6 +-
...rHandlerTest.java => AmbariErrorHandlerIT.java} | 15 +-
.../ambari/server/api/AmbariErrorHandlerTest.java | 151 +++++++++++++--------
.../api/AmbariViewErrorHandlerProxyTest.java | 117 ++++++++++++++++
.../server/controller/AmbariHandlerListTest.java | 2 +-
8 files changed, 410 insertions(+), 77 deletions(-)
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java
index 9f69c60c73..b1bd658ea6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java
@@ -19,15 +19,20 @@
package org.apache.ambari.server.api;
import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.UUID;
+import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.ambari.server.security.authentication.jwt.JwtAuthenticationProperties;
import org.apache.ambari.server.security.authentication.jwt.JwtAuthenticationPropertiesProvider;
import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.HttpChannel;
@@ -73,6 +78,23 @@ public class AmbariErrorHandler extends ErrorHandler {
}
errorMap.put("message", message);
+
+ Throwable th = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
+ if (th != null) {
+ if (code == org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR) {
+ UUID requestId = UUID.randomUUID();
+ message = "Internal server error, please refer the exception by " + requestId + " in the server log file";
+ errorMap.put("message", message);
+ LOG.error(message + ", requestURI: " + request.getRequestURI(), th);
+ }
+
+ if (this.isShowStacks()) {
+ StringWriter writer = new StringWriter();
+ writeErrorPageStacks(request, writer);
+ errorMap.put("reason:", writer.toString());
+ }
+ }
+
if ((code == HttpServletResponse.SC_FORBIDDEN) || (code == HttpServletResponse.SC_UNAUTHORIZED)) {
//if SSO is configured we should provide info about it in case of access error
JwtAuthenticationProperties jwtProperties = jwtAuthenticationPropertiesProvider.get();
@@ -92,4 +114,17 @@ public class AmbariErrorHandler extends ErrorHandler {
gson.toJson(errorMap, response.getWriter());
}
+
+ @Override
+ protected void writeErrorPageStacks(HttpServletRequest request, Writer writer)
+ throws IOException {
+ Throwable th = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
+
+ while (th != null) {
+ writer.write("Caused by:\n");
+ write(writer, ExceptionUtils.getStackTrace(th));
+ writer.write("\n");
+ th = th.getCause();
+ }
+ }
}
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariViewErrorHandlerProxy.java b/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariViewErrorHandlerProxy.java
new file mode 100644
index 0000000000..e4d95d9106
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariViewErrorHandlerProxy.java
@@ -0,0 +1,118 @@
+/*
+ * 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.ambari.server.api;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.http.HttpStatus;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.ErrorHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javassist.util.proxy.MethodHandler;
+
+/**
+ * Wraps the given ErrorHandler to log the error stacks
+ */
+public class AmbariViewErrorHandlerProxy extends ErrorHandler implements MethodHandler {
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(AmbariViewErrorHandlerProxy.class);
+
+ private final ErrorHandler webAppErrorHandler;
+ private final AmbariErrorHandler ambariErrorHandler;
+
+ public AmbariViewErrorHandlerProxy(ErrorHandler webAppErrorHandler, AmbariErrorHandler ambariErrorHandler) {
+ this.webAppErrorHandler = webAppErrorHandler;
+ this.ambariErrorHandler = ambariErrorHandler;
+ }
+
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException {
+
+ if (isInternalError(request, response)) {
+ //invoke the ambari error handler
+ ambariErrorHandler.handle(target, baseRequest, request, response);
+ } else {
+ //invoke the original errorhandler
+ webAppErrorHandler.handle(target, baseRequest, request, response);
+ }
+ }
+
+ @Override
+ public void doError(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException {
+
+ if (isInternalError(request, response)) {
+ //invoke the ambari error handler
+ ambariErrorHandler.handle(target, baseRequest, request, response);
+ } else {
+ //invoke the original errorhandler
+ webAppErrorHandler.doError(target, baseRequest, request, response);
+ }
+ }
+
+ private boolean isInternalError(HttpServletRequest request, HttpServletResponse response) {
+ Throwable th = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
+ return null != th && response.getStatus() == HttpStatus.SC_INTERNAL_SERVER_ERROR;
+ }
+
+ @Override
+ public void setShowStacks(boolean showStacks) {
+ ambariErrorHandler.setShowStacks(showStacks);
+ webAppErrorHandler.setShowStacks(showStacks);
+ }
+
+ @Override
+ public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
+ LOGGER.debug("invoked method: " + thisMethod.getName());
+ Method m = findDeclaredMethod(this.getClass(), thisMethod);
+ if (m != null) {
+ return m.invoke(this, args);
+ }
+ m = findMethod(webAppErrorHandler.getClass(), thisMethod);
+ if (m != null) {
+ return m.invoke(webAppErrorHandler, args);
+ }
+ return null;
+ }
+
+ private Method findDeclaredMethod(Class<?> clazz, Method method) {
+ try {
+ return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+ private Method findMethod(Class<?> clazz, Method method) {
+ try {
+ return clazz.getMethod(method.getName(), method.getParameterTypes());
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+
+}
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariHandlerList.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariHandlerList.java
index 663592e2a9..f8a99f6da4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariHandlerList.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariHandlerList.java
@@ -32,7 +32,9 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.ambari.server.api.AmbariErrorHandler;
import org.apache.ambari.server.api.AmbariPersistFilter;
+import org.apache.ambari.server.api.AmbariViewErrorHandlerProxy;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.orm.entities.ViewEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
@@ -44,6 +46,7 @@ import org.apache.ambari.view.SystemException;
import org.apache.ambari.view.ViewContext;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.session.SessionCache;
import org.eclipse.jetty.server.session.SessionHandler;
@@ -53,6 +56,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.filter.DelegatingFilterProxy;
+import javassist.util.proxy.ProxyFactory;
+
/**
* An Ambari specific extension of the FailsafeHandlerList that allows for the addition
* of view instances as handlers.
@@ -108,6 +113,10 @@ public class AmbariHandlerList extends HandlerCollection implements ViewInstance
@Inject
Configuration configuration;
+ @Inject
+ AmbariErrorHandler ambariErrorHandler;
+
+
/**
* Mapping of view instance entities to handlers.
*/
@@ -173,7 +182,7 @@ public class AmbariHandlerList extends HandlerCollection implements ViewInstance
viewHandlerMap.put(viewInstanceDefinition, handler);
super.addHandler(handler);
// if this is running then start the handler being added...
- if(!isStopped() && !isStopping()) {
+ if (!isStopped() && !isStopping()) {
try {
handler.start();
} catch (Exception e) {
@@ -233,17 +242,15 @@ public class AmbariHandlerList extends HandlerCollection implements ViewInstance
/**
* Get a Handler for the given view instance.
*
- * @param viewInstanceDefinition the view instance definition
- *
+ * @param viewInstanceDefinition the view instance definition
* @return a handler
- *
* @throws org.apache.ambari.view.SystemException if an handler can not be obtained for the given view instance
*/
private WebAppContext getHandler(ViewInstanceEntity viewInstanceDefinition)
throws SystemException {
- ViewEntity viewDefinition = viewInstanceDefinition.getViewEntity();
- WebAppContext webAppContext = webAppContextProvider.get();
+ ViewEntity viewDefinition = viewInstanceDefinition.getViewEntity();
+ WebAppContext webAppContext = webAppContextProvider.get();
webAppContext.setWar(viewDefinition.getArchive());
webAppContext.setContextPath(viewInstanceDefinition.getContextPath());
@@ -255,18 +262,36 @@ public class AmbariHandlerList extends HandlerCollection implements ViewInstance
webAppContext.addFilter(new FilterHolder(springSecurityFilter), "/*", AmbariServer.DISPATCHER_TYPES);
webAppContext.setAllowNullPathInfo(true);
+
if (webAppContext.getErrorHandler() != null) {
+ ErrorHandler errorHandlerProxy = createAmbariViewErrorHandlerProxy(webAppContext.getErrorHandler());
+ if (errorHandlerProxy != null) {
+ webAppContext.setErrorHandler(errorHandlerProxy);
+ }
webAppContext.getErrorHandler().setShowStacks(configuration.isServerShowErrorStacks());
}
return webAppContext;
}
+ private ErrorHandler createAmbariViewErrorHandlerProxy(ErrorHandler errorHandler) {
+ ErrorHandler proxy = null;
+ try {
+ ProxyFactory proxyFactory = new ProxyFactory();
+ proxyFactory.setSuperclass(ErrorHandler.class);
+ proxy = (ErrorHandler) proxyFactory.create(new Class[0],
+ new Object[0],
+ new AmbariViewErrorHandlerProxy(errorHandler, ambariErrorHandler));
+ } catch (Exception e) {
+ LOG.error("An error occurred while instantiating the error handler proxy instance", e);
+ }
+ return proxy;
+ }
+
/**
* Get the view that is the target of the request; null if not a view request.
*
- * @param target the target of the request
- *
+ * @param target the target of the request
* @return the view target; null if none
*/
private ViewEntity getTargetView(String target) {
@@ -289,7 +314,7 @@ public class AmbariHandlerList extends HandlerCollection implements ViewInstance
/**
* Construct a SharedSessionHandler.
*
- * @param sessionHandler the shared session manager.
+ * @param sessionHandler the shared session manager.
*/
public SharedSessionHandler(SessionHandler sessionHandler) {
setSessionIdManager(sessionHandler.getSessionIdManager());
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index a2b66e4a34..6ac11c42e3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -826,7 +826,11 @@ public class AmbariServer {
configureHandlerCompression(root);
configureAdditionalContentTypes(root);
root.setContextPath(CONTEXT_PATH);
- root.setErrorHandler(injector.getInstance(AmbariErrorHandler.class));
+
+ AmbariErrorHandler ambariErrorHandler = injector.getInstance(AmbariErrorHandler.class);
+ ambariErrorHandler.setShowStacks(configs.isServerShowErrorStacks());
+ root.setErrorHandler(ambariErrorHandler);
+
root.setMaxFormContentSize(-1);
/* Configure web app context */
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerIT.java
similarity index 93%
copy from ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java
copy to ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerIT.java
index 827d0d9e55..d2c23c1038 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerIT.java
@@ -45,14 +45,8 @@ import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
-public class AmbariErrorHandlerTest extends EasyMockSupport {
- Gson gson = new Gson();
-
-
- @Test
- public void testHandle() throws Exception {
-
- }
+public class AmbariErrorHandlerIT extends EasyMockSupport {
+ private Gson gson = new Gson();
@Test
public void testErrorWithJetty() throws Exception {
@@ -71,7 +65,7 @@ public class AmbariErrorHandlerTest extends EasyMockSupport {
server.start();
- int localPort = ((ServerConnector)server.getConnectors()[0]).getLocalPort();
+ int localPort = ((ServerConnector) server.getConnectors()[0]).getLocalPort();
Client client = new Client();
WebResource resource = client.resource("http://localhost:" + localPort + "/");
@@ -96,7 +90,7 @@ public class AmbariErrorHandlerTest extends EasyMockSupport {
fail("Incorrect response");
}
- server.stop();
+ server.stop();
verifyAll();
}
@@ -112,4 +106,5 @@ public class AmbariErrorHandlerTest extends EasyMockSupport {
}
}
+
}
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java
index 827d0d9e55..ed00b0705f 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java
@@ -18,98 +18,137 @@
package org.apache.ambari.server.api;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
import java.io.IOException;
-import java.util.Map;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.UUID;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
+import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.ambari.server.security.authentication.jwt.JwtAuthenticationPropertiesProvider;
+import org.apache.http.HttpStatus;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
import org.easymock.EasyMockSupport;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.servlet.DefaultServlet;
-import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.server.HttpChannel;
+import org.eclipse.jetty.server.HttpConnection;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
-import com.google.gson.JsonSyntaxException;
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.WebResource;
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({AmbariErrorHandler.class, LoggerFactory.class, HttpConnection.class, UUID.class})
public class AmbariErrorHandlerTest extends EasyMockSupport {
- Gson gson = new Gson();
+ private Gson gson = new Gson();
+ private Logger logger = createNiceMock(Logger.class);
- @Test
- public void testHandle() throws Exception {
+ private HttpConnection httpConnection = createNiceMock(HttpConnection.class);
+ private HttpChannel httpChannel = createNiceMock(HttpChannel.class);
- }
+ private Response response = createNiceMock(Response.class);
+ private Request request = createNiceMock(Request.class);
- @Test
- public void testErrorWithJetty() throws Exception {
- Server server = new Server(0);
- JwtAuthenticationPropertiesProvider propertiesProvider = createNiceMock(JwtAuthenticationPropertiesProvider.class);
- expect(propertiesProvider.get()).andReturn(null).anyTimes();
+ private HttpServletResponse httpServletResponse = createNiceMock(HttpServletResponse.class);
+ private HttpServletRequest httpServletRequest = createNiceMock(HttpServletRequest.class);
- replayAll();
+ private JwtAuthenticationPropertiesProvider propertiesProvider = createNiceMock(JwtAuthenticationPropertiesProvider.class);
- ServletContextHandler root = new ServletContextHandler(server, "/",
- ServletContextHandler.SECURITY | ServletContextHandler.SESSIONS);
+ final String target = "target";
- root.addServlet(HelloServlet.class, "/hello");
- root.addServlet(DefaultServlet.class, "/");
- root.setErrorHandler(new AmbariErrorHandler(gson, propertiesProvider));
+ @Test
+ public void testHandleInternalServerError() throws IOException {
+ //given
+ final UUID requestId = UUID.fromString("4db659b2-7902-477b-b8e6-c35261d3334a");
- server.start();
+ mockStatic(HttpConnection.class, UUID.class, LoggerFactory.class);
+ when(HttpConnection.getCurrentConnection()).thenReturn(httpConnection);
+ when(UUID.randomUUID()).thenReturn(requestId);
+ when(LoggerFactory.getLogger(AmbariErrorHandler.class)).thenReturn(logger);
- int localPort = ((ServerConnector)server.getConnectors()[0]).getLocalPort();
+ Throwable th = createNiceMock(Throwable.class);
- Client client = new Client();
- WebResource resource = client.resource("http://localhost:" + localPort + "/");
+ Capture<String> captureLogMessage = EasyMock.newCapture();
+ logger.error(capture(captureLogMessage), eq(th));
+ expectLastCall();
+ expect(httpConnection.getHttpChannel()).andReturn(httpChannel);
+ expect(httpChannel.getRequest()).andReturn(request);
+ expect(httpChannel.getResponse()).andReturn(response).times(2);
+ expect(response.getStatus()).andReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR);
- ClientResponse successResponse = resource.path("hello").get(ClientResponse.class);
- assertEquals(HttpServletResponse.SC_OK, successResponse.getStatus());
+ final String requestUri = "/path/to/target";
+ expect(httpServletRequest.getRequestURI()).andReturn(requestUri);
+ expect(httpServletRequest.getAttribute(RequestDispatcher.ERROR_EXCEPTION)).andReturn(th);
- ClientResponse failResponse = resource.path("fail").get(ClientResponse.class);
+ final StringWriter writer = new StringWriter();
+ expect(httpServletResponse.getWriter()).andReturn(new PrintWriter(writer));
- assertEquals(HttpServletResponse.SC_NOT_FOUND, failResponse.getStatus());
+ expect(propertiesProvider.get()).andReturn(null).anyTimes();
+
+ replayAll();
- try {
- String response = failResponse.getEntity(String.class);
- System.out.println(response);
- Map map;
- map = gson.fromJson(response, Map.class);
- System.out.println(map);
- assertNotNull("Incorrect response status", map.get("status"));
- assertNotNull("Incorrect response message", map.get("message"));
- } catch (JsonSyntaxException e1) {
- fail("Incorrect response");
- }
+ final String expectedResponse = "{\"status\":500,\"message\":\"Internal server error, please refer the exception by " + requestId + " in the server log file\"}";
+ final String expectedErrorMessage = "Internal server error, please refer the exception by " + requestId + " in the server log file, requestURI: " + requestUri;
- server.stop();
+ AmbariErrorHandler ambariErrorHandler = new AmbariErrorHandler(gson, propertiesProvider);
+ ambariErrorHandler.setShowStacks(false);
+ //when
+ ambariErrorHandler.handle(target, request, httpServletRequest, httpServletResponse);
+
+ //then
+ assertEquals(expectedResponse, writer.toString());
+ assertEquals(expectedErrorMessage, captureLogMessage.getValue());
verifyAll();
}
+ @Test
+ public void testHandleGeneralError() throws Exception {
- @SuppressWarnings("serial")
- public static class HelloServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- response.setContentType("text/html");
- response.setStatus(HttpServletResponse.SC_OK);
- response.getWriter().println("hello");
- }
+ //given
+ mockStatic(HttpConnection.class);
+ when(HttpConnection.getCurrentConnection()).thenReturn(httpConnection);
+ expect(httpConnection.getHttpChannel()).andReturn(httpChannel);
+ expect(httpChannel.getRequest()).andReturn(request);
+ expect(httpChannel.getResponse()).andReturn(response).anyTimes();
+ expect(response.getStatus()).andReturn(HttpStatus.SC_BAD_REQUEST);
+
+ final StringWriter writer = new StringWriter();
+ expect(httpServletResponse.getWriter()).andReturn(new PrintWriter(writer));
+
+ expect(propertiesProvider.get()).andReturn(null).anyTimes();
+
+ replayAll();
+
+ final String expectedResponse = "{\"status\":400,\"message\":\"Bad Request\"}";
+
+ AmbariErrorHandler ambariErrorHandler = new AmbariErrorHandler(gson, propertiesProvider);
+
+ //when
+ ambariErrorHandler.handle(target, request, httpServletRequest, httpServletResponse);
+ System.out.println(writer.toString());
+
+ //then
+ assertEquals(expectedResponse, writer.toString());
+ verifyAll();
}
}
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariViewErrorHandlerProxyTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariViewErrorHandlerProxyTest.java
new file mode 100644
index 0000000000..8718bbf4f6
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariViewErrorHandlerProxyTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.ambari.server.api;
+
+import static junit.framework.Assert.assertTrue;
+import static org.easymock.EasyMock.captureBoolean;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.http.HttpStatus;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.ErrorHandler;
+import org.junit.Test;
+
+public class AmbariViewErrorHandlerProxyTest {
+
+ final AmbariErrorHandler ambariErrorHandler = createNiceMock(AmbariErrorHandler.class);
+ final ErrorHandler errorHandler = createNiceMock(ErrorHandler.class);
+
+ final HttpServletRequest httpServletRequest = createNiceMock(HttpServletRequest.class);
+ final HttpServletResponse httpServletResponse = createNiceMock(HttpServletResponse.class);
+ final Request request = createNiceMock(Request.class);
+
+ final String target = "test/target/uri";
+
+ @Test
+ public void testHandleInternalServerError() throws Throwable {
+ //given
+ Throwable th = createNiceMock(Throwable.class);
+ expect(httpServletRequest.getAttribute(RequestDispatcher.ERROR_EXCEPTION)).andReturn(th).anyTimes();
+ expect(httpServletResponse.getStatus()).andReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR).anyTimes();
+
+ ambariErrorHandler.handle(target, request, httpServletRequest, httpServletResponse);
+ expectLastCall();
+
+ replay(ambariErrorHandler, errorHandler, httpServletRequest, httpServletResponse, th);
+
+ //when
+ AmbariViewErrorHandlerProxy proxy = new AmbariViewErrorHandlerProxy(errorHandler, ambariErrorHandler);
+ proxy.handle(target, request, httpServletRequest, httpServletResponse);
+
+ //then
+ verify(ambariErrorHandler, errorHandler, httpServletRequest, httpServletResponse, th);
+ }
+
+ @Test
+ public void testHandleGeneralError() throws Throwable {
+ //given
+ Throwable th = createNiceMock(Throwable.class);
+ expect(httpServletRequest.getAttribute(RequestDispatcher.ERROR_EXCEPTION)).andReturn(th).anyTimes();
+ expect(httpServletResponse.getStatus()).andReturn(HttpStatus.SC_BAD_REQUEST).anyTimes();
+
+ errorHandler.handle(target, request, httpServletRequest, httpServletResponse);
+ expectLastCall();
+
+ replay(ambariErrorHandler, errorHandler, httpServletRequest, httpServletResponse, th);
+
+ //when
+ AmbariViewErrorHandlerProxy proxy = new AmbariViewErrorHandlerProxy(errorHandler, ambariErrorHandler);
+ proxy.handle(target, request, httpServletRequest, httpServletResponse);
+
+ //then
+ verify(ambariErrorHandler, errorHandler, httpServletRequest, httpServletResponse, th);
+ }
+
+ @Test
+ public void testShowStacks() {
+
+ //given
+ Capture<Boolean> captureShowStacksErrorHandler = EasyMock.newCapture();
+ errorHandler.setShowStacks(captureBoolean(captureShowStacksErrorHandler));
+ expectLastCall();
+
+ Capture<Boolean> captureShowStacksAmbariErrorHandler = EasyMock.newCapture();
+ ambariErrorHandler.setShowStacks(captureBoolean(captureShowStacksAmbariErrorHandler));
+ expectLastCall();
+
+ replay(errorHandler, ambariErrorHandler);
+
+
+ //when
+ AmbariViewErrorHandlerProxy proxy = new AmbariViewErrorHandlerProxy(errorHandler, ambariErrorHandler);
+ proxy.setShowStacks(true);
+
+ //then
+ assertTrue(captureShowStacksErrorHandler.getValue());
+ assertTrue(captureShowStacksAmbariErrorHandler.getValue());
+
+ verify(errorHandler, ambariErrorHandler);
+
+ }
+}
\ No newline at end of file
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariHandlerListTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariHandlerListTest.java
index 37e7bb4d3f..b6d5555c30 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariHandlerListTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariHandlerListTest.java
@@ -99,7 +99,7 @@ public class AmbariHandlerListTest {
Capture<Boolean> showStackCapture = EasyMock.newCapture();
errorHandler.setShowStacks(EasyMock.captureBoolean(showStackCapture));
- expect(handler.getErrorHandler()).andReturn(errorHandler).times(2);
+ expect(handler.getErrorHandler()).andReturn(errorHandler).times(3);
replay(handler, server, sessionHandler, configuration, errorHandler);
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ambari.apache.org
For additional commands, e-mail: commits-help@ambari.apache.org