Skip to content

Commit

Permalink
[UNDERTOW-1747] Provide a mechanism for a predicate in return a servl…
Browse files Browse the repository at this point in the history
…et error page
  • Loading branch information
bdw429s authored and fl4via committed Sep 13, 2020
1 parent 6337a0e commit b533f8d
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 0 deletions.
13 changes: 13 additions & 0 deletions core/src/main/java/io/undertow/Handlers.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.undertow.server.HttpHandler;
import io.undertow.server.JvmRouteHandler;
import io.undertow.server.RoutingHandler;
import io.undertow.server.handlers.SetErrorHandler;
import io.undertow.server.handlers.AccessControlListHandler;
import io.undertow.server.handlers.LearningPushHandler;
import io.undertow.server.handlers.DateHandler;
Expand Down Expand Up @@ -562,6 +563,18 @@ public static LearningPushHandler learningPushHandler(int maxEntries, int maxAge
return new LearningPushHandler(maxEntries, maxAge, next);
}

/**
* A handler that sets response code but continues the exchange so the servlet's
* error page can be returned.
*
* @param responseCode The response code to set
* @param next The next handler
* @return A Set Error handler
*/
public static SetErrorHandler setErrorHandler(int responseCode, HttpHandler next) {
return new SetErrorHandler(next, responseCode);
}

/**
* Creates a handler that automatically learns which resources to push based on the referer header
*
Expand Down
111 changes: 111 additions & 0 deletions core/src/main/java/io/undertow/server/handlers/SetErrorHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2020 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed 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 io.undertow.server.handlers;

import io.undertow.server.HandlerWrapper;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.builder.HandlerBuilder;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
* A handler that sets response code but continues the exchange so the servlet's
* error page can be returned.
*
* @author Brad Wood
*/
public class SetErrorHandler implements HttpHandler {

private final int responseCode;
private final HttpHandler next;

/**
* Construct a new instance.
*
* @param responseCode the response code to set
*/
public SetErrorHandler(HttpHandler next, final int responseCode) {
this.next = next;
this.responseCode = responseCode;
}

@Override
public void handleRequest(final HttpServerExchange exchange) throws Exception {
exchange.setStatusCode(responseCode);
next.handleRequest(exchange);
}

@Override
public String toString() {
return "set-error( " + responseCode + " )";
}


public static class Builder implements HandlerBuilder {

@Override
public String name() {
return "set-error";
}

@Override
public Map<String, Class<?>> parameters() {
Map<String, Class<?>> params = new HashMap<>();
params.put("response-code", Integer.class);
return params;
}

@Override
public Set<String> requiredParameters() {
final Set<String> req = new HashSet<>();
req.add("response-code");
return req;
}

@Override
public String defaultParameter() {
return "response-code";
}

@Override
public HandlerWrapper build(Map<String, Object> config) {
return new Wrapper((Integer) config.get("response-code"));
}

}

private static class Wrapper implements HandlerWrapper {

private final Integer responseCode;

private Wrapper(Integer responseCode) {
this.responseCode = responseCode;
}

@Override
public HttpHandler wrap(HttpHandler handler) {
return new SetErrorHandler(handler, responseCode);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ io.undertow.server.handlers.ForwardedHandler$Builder
io.undertow.server.handlers.HttpContinueAcceptingHandler$Builder
io.undertow.server.handlers.form.EagerFormParsingHandler$Builder
io.undertow.server.handlers.SameSiteCookieHandler$Builder
io.undertow.server.handlers.SetErrorHandler$Builder
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import io.undertow.servlet.api.WebResourceCollection;
import io.undertow.servlet.handlers.CrawlerSessionManagerHandler;
import io.undertow.servlet.handlers.RedirectDirHandler;
import io.undertow.servlet.handlers.SendErrorPageHandler;
import io.undertow.servlet.handlers.ServletDispatchingHandler;
import io.undertow.servlet.handlers.ServletHandler;
import io.undertow.servlet.handlers.ServletInitialHandler;
Expand Down Expand Up @@ -226,6 +227,7 @@ public Void call(HttpServerExchange exchange, Object ignore) throws Exception {
wrappedHandlers = new PredicateHandler(DispatcherTypePredicate.REQUEST, securityHandler, wrappedHandlers);
}
HttpHandler outerHandlers = wrapHandlers(wrappedHandlers, deploymentInfo.getOuterHandlerChainWrappers());
outerHandlers = new SendErrorPageHandler(outerHandlers);
wrappedHandlers = new PredicateHandler(DispatcherTypePredicate.REQUEST, outerHandlers, wrappedHandlers);
wrappedHandlers = handleDevelopmentModePersistentSessions(wrappedHandlers, deploymentInfo, deployment.getSessionManager(), servletContext);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2020 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed 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 io.undertow.servlet.handlers;

import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;

import javax.servlet.http.HttpServletResponse;

/**
* A handler that sends the servlet's error page if the status code is greater than 399
*
* @author Brad Wood
*/
public class SendErrorPageHandler implements HttpHandler {

private final HttpHandler next;

/**
* Construct a new instance.
*
* @param next The next handler to call if there is no error response
*/
public SendErrorPageHandler(HttpHandler next) {
this.next = next;
}

@Override
public void handleRequest(final HttpServerExchange exchange) throws Exception {
ServletRequestContext src = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);

// If the servlet is available and the status code has been set to an error, return the error page
if( src != null && exchange.getStatusCode() > 399 && !exchange.isResponseStarted() ) {
((HttpServletResponse)src.getServletResponse()).sendError(exchange.getStatusCode());
} else {
next.handleRequest(exchange);
}
}

}

0 comments on commit b533f8d

Please sign in to comment.