|
25 | 25 | import com.google.apphosting.runtime.jetty.EE10SessionManagerHandler; |
26 | 26 | import com.google.common.flogger.GoogleLogger; |
27 | 27 | import com.google.common.html.HtmlEscapers; |
28 | | -import jakarta.servlet.RequestDispatcher; |
29 | | -import jakarta.servlet.ServletContext; |
30 | 28 | import jakarta.servlet.ServletException; |
31 | | -import jakarta.servlet.http.HttpServletRequest; |
32 | | -import jakarta.servlet.http.HttpServletResponse; |
33 | 29 | import java.io.File; |
34 | | -import java.io.IOException; |
35 | 30 | import java.io.PrintWriter; |
36 | 31 | import javax.servlet.jsp.JspFactory; |
37 | 32 | import org.eclipse.jetty.ee10.annotations.AnnotationConfiguration; |
38 | 33 | import org.eclipse.jetty.ee10.quickstart.QuickStartConfiguration; |
39 | | -import org.eclipse.jetty.ee10.servlet.Dispatcher; |
40 | 34 | import org.eclipse.jetty.ee10.servlet.ErrorHandler; |
41 | 35 | import org.eclipse.jetty.ee10.servlet.ErrorPageErrorHandler; |
42 | | -import org.eclipse.jetty.ee10.servlet.ServletContextRequest; |
43 | 36 | import org.eclipse.jetty.ee10.webapp.FragmentConfiguration; |
44 | 37 | import org.eclipse.jetty.ee10.webapp.MetaInfConfiguration; |
45 | 38 | import org.eclipse.jetty.ee10.webapp.WebInfConfiguration; |
@@ -77,12 +70,6 @@ public class EE10AppVersionHandlerFactory implements AppVersionHandlerFactory { |
77 | 70 | */ |
78 | 71 | private static final String USE_ANNOTATION_SCANNING = "use.annotationscanning"; |
79 | 72 |
|
80 | | - /** |
81 | | - * A "private" request attribute to indicate if the dispatch to a most recent error page has run |
82 | | - * to completion. Note an error page itself may generate errors. |
83 | | - */ |
84 | | - static final String ERROR_PAGE_HANDLED = ErrorHandler.ERROR_PAGE + ".handled"; |
85 | | - |
86 | 73 | private final Server server; |
87 | 74 | private final String serverInfo; |
88 | 75 | private final boolean useJettyErrorPageHandler; |
@@ -223,93 +210,38 @@ public void exitScope(Context context, Request request) { |
223 | 210 | } |
224 | 211 | } |
225 | 212 |
|
226 | | - /** |
227 | | - * {@code NullErrorHandler} does nothing when an error occurs. The exception is already stored in |
228 | | - * an attribute of {@code request}, but we don't do any rendering of it into the response, UNLESS |
229 | | - * the webapp has a designated error page (servlet, jsp, or static html) for the current error |
230 | | - * condition (exception type or error code). |
231 | | - */ |
232 | 213 | private static class NullErrorHandler extends ErrorPageErrorHandler { |
233 | | - @Override |
234 | | - public boolean handle(Request request, Response response, Callback callback) throws Exception { |
235 | | - logger.atFine().log("Custom Jetty ErrorHandler received an error notification."); |
236 | | - mayHandleByErrorPage(request, response, callback); |
237 | | - // We don't want Jetty to do anything further. |
238 | | - return true; |
239 | | - } |
240 | 214 |
|
241 | 215 | /** |
242 | | - * Try to invoke a custom error page if a handler is available. If not, render a simple HTML |
243 | | - * response for {@link HttpServletResponse#sendError} calls, but do nothing for unhandled |
244 | | - * exceptions. |
245 | | - * |
246 | | - * <p>This is loosely based on {@link ErrorPageErrorHandler#handle} but has been modified to add |
247 | | - * a fallback simple HTML response (because Jetty's default response is not satisfactory) and to |
248 | | - * set a special {@code ERROR_PAGE_HANDLED} attribute that disables our default behavior of |
249 | | - * returning the exception to the appserver for rendering. |
| 216 | + * Override the response generation when not mapped to a servlet error page. |
250 | 217 | */ |
251 | | - private void mayHandleByErrorPage(Request request, Response response, Callback callback) |
252 | | - throws IOException { |
253 | | - ServletContextRequest contextRequest = Request.as(request, ServletContextRequest.class); |
254 | | - HttpServletRequest httpServletRequest = contextRequest.getServletApiRequest(); |
255 | | - HttpServletResponse httpServletResponse = contextRequest.getHttpServletResponse(); |
256 | | - // Extract some error handling info from Jetty's proprietary attributes. |
257 | | - Throwable error = (Throwable) contextRequest.getAttribute(RequestDispatcher.ERROR_EXCEPTION); |
258 | | - Integer code = (Integer) contextRequest.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); |
259 | | - String message = (String) contextRequest.getAttribute(RequestDispatcher.ERROR_MESSAGE); |
260 | | - // Now try to find an error handler... |
261 | | - String errorPage = getErrorPage(httpServletRequest); |
262 | | - // If we found an error handler, dispatch to it. |
263 | | - if (errorPage != null) { |
264 | | - // Check for reentry into the same error page. |
265 | | - String oldErrorPage = (String) request.getAttribute(ErrorHandler.ERROR_PAGE); |
266 | | - if (oldErrorPage == null || !oldErrorPage.equals(errorPage)) { |
267 | | - request.setAttribute(ErrorHandler.ERROR_PAGE, errorPage); |
268 | | - ServletContext servletContext = httpServletRequest.getServletContext(); |
269 | | - Dispatcher dispatcher = (Dispatcher) servletContext.getRequestDispatcher(errorPage); |
270 | | - try { |
271 | | - if (dispatcher != null) { |
272 | | - dispatcher.error(httpServletRequest, httpServletResponse); |
273 | | - // Set this special attribute iff the dispatch actually works! |
274 | | - // We use this attribute to decide if we want to keep the response content |
275 | | - // or let the Runtime generate the default error page |
276 | | - // TODO: an invalid html dispatch (404) will mask the exception |
277 | | - request.setAttribute(ERROR_PAGE_HANDLED, errorPage); |
278 | | - callback.succeeded(); |
279 | | - return; |
280 | | - } else { |
281 | | - logger.atWarning().log("No error page %s", errorPage); |
282 | | - } |
283 | | - } catch (ServletException e) { |
284 | | - logger.atWarning().withCause(e).log("Failed to handle error page."); |
285 | | - } |
286 | | - } |
287 | | - } |
| 218 | + @Override |
| 219 | + protected void generateResponse( |
| 220 | + Request request, |
| 221 | + Response response, |
| 222 | + int code, |
| 223 | + String message, |
| 224 | + Throwable cause, |
| 225 | + Callback callback) { |
288 | 226 | // If we got an error code (e.g. this is a call to HttpServletResponse#sendError), |
289 | 227 | // then render our own HTML. XFE has logic to do this, but the PFE only invokes it |
290 | 228 | // for error conditions that it or the AppServer detect. |
291 | | - if (code != null && message != null) { |
292 | | - // This template is based on the default XFE error response. |
293 | | - response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/html; charset=UTF-8"); |
294 | | - String messageEscaped = HtmlEscapers.htmlEscaper().escape(message); |
295 | | - try (PrintWriter writer = new PrintWriter(Content.Sink.asOutputStream(response))) { |
296 | | - writer.println("<html><head>"); |
297 | | - writer.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">"); |
298 | | - writer.println("<title>" + code + " " + messageEscaped + "</title>"); |
299 | | - writer.println("</head>"); |
300 | | - writer.println("<body text=#000000 bgcolor=#ffffff>"); |
301 | | - writer.println("<h1>Error: " + messageEscaped + "</h1>"); |
302 | | - writer.println("</body></html>"); |
303 | | - writer.close(); |
304 | | - callback.succeeded(); |
305 | | - } catch (Throwable t) { |
306 | | - callback.failed(t); |
307 | | - } |
308 | | - return; |
| 229 | + // This template is based on the default XFE error response. |
| 230 | + response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/html; charset=UTF-8"); |
| 231 | + String messageEscaped = HtmlEscapers.htmlEscaper().escape(message); |
| 232 | + try (PrintWriter writer = new PrintWriter(Content.Sink.asOutputStream(response))) { |
| 233 | + writer.println("<html><head>"); |
| 234 | + writer.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">"); |
| 235 | + writer.println("<title>" + code + " " + messageEscaped + "</title>"); |
| 236 | + writer.println("</head>"); |
| 237 | + writer.println("<body text=#000000 bgcolor=#ffffff>"); |
| 238 | + writer.println("<h1>Error: " + messageEscaped + "</h1>"); |
| 239 | + writer.println("</body></html>"); |
| 240 | + writer.close(); |
| 241 | + callback.succeeded(); |
| 242 | + } catch (Throwable t) { |
| 243 | + callback.failed(t); |
309 | 244 | } |
310 | | - // If we got this far and *did* have an exception, it will be |
311 | | - // retrieved and thrown at the end of JettyServletEngineAdapter#serviceRequest. |
312 | | - throw new IllegalStateException(error); |
313 | 245 | } |
314 | 246 | } |
315 | 247 | } |
0 commit comments