Skip to content

Commit 428d7eb

Browse files
authored
Merge pull request #267 from adrienlauer/undertow-error-pages
Add support for Undertow error pages
2 parents d75af53 + eae8ff1 commit 428d7eb

File tree

9 files changed

+155
-0
lines changed

9 files changed

+155
-0
lines changed

web/specs/src/main/java/org/seedstack/seed/web/WebConfig.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* License, v. 2.0. If a copy of the MPL was not distributed with this
66
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
77
*/
8+
89
package org.seedstack.seed.web;
910

1011
import java.util.ArrayList;
@@ -161,6 +162,7 @@ public static class ServerConfig {
161162
private boolean http2 = DEFAULT_HTTP2_ACTIVATION;
162163
private boolean https = DEFAULT_HTTPS_ACTIVATION;
163164
private List<String> welcomeFiles = new ArrayList<>();
165+
private List<ErrorPage> errorPages = new ArrayList<>();
164166

165167
public ServerConfig() {
166168
addWelcomeFile(DEFAULT_WELCOME_FILE);
@@ -236,6 +238,20 @@ public ServerConfig addWelcomeFile(String welcomeFile) {
236238
return this;
237239
}
238240

241+
public List<ErrorPage> getErrorPages() {
242+
return Collections.unmodifiableList(errorPages);
243+
}
244+
245+
public ServerConfig setErrorPages(List<ErrorPage> errorPages) {
246+
this.errorPages = errorPages;
247+
return this;
248+
}
249+
250+
public ServerConfig addErrorPage(ErrorPage errorPage) {
251+
this.errorPages.add(errorPage);
252+
return this;
253+
}
254+
239255
@Config("sessions")
240256
public static class SessionsConfig {
241257
private static final int DEFAULT_SESSION_TIMEOUT = 1000 * 60 * 15;
@@ -251,5 +267,42 @@ public SessionsConfig setTimeout(int timeout) {
251267
return this;
252268
}
253269
}
270+
271+
public static class ErrorPage {
272+
private String location;
273+
private Integer errorCode;
274+
private Class<? extends Exception> exceptionType;
275+
276+
public String getLocation() {
277+
return location;
278+
}
279+
280+
public ErrorPage setLocation(String location) {
281+
this.location = location;
282+
return this;
283+
}
284+
285+
public Integer getErrorCode() {
286+
return errorCode;
287+
}
288+
289+
public ErrorPage setErrorCode(Integer errorCode) {
290+
this.errorCode = errorCode;
291+
return this;
292+
}
293+
294+
public Class<? extends Throwable> getExceptionType() {
295+
return exceptionType;
296+
}
297+
298+
public ErrorPage setExceptionType(Class<? extends Exception> exceptionType) {
299+
this.exceptionType = exceptionType;
300+
return this;
301+
}
302+
303+
public boolean isDefault() {
304+
return exceptionType == null && errorCode == null;
305+
}
306+
}
254307
}
255308
}

web/undertow/src/main/java/org/seedstack/seed/undertow/internal/DeploymentManagerFactory.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* License, v. 2.0. If a copy of the MPL was not distributed with this
66
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
77
*/
8+
89
package org.seedstack.seed.undertow.internal;
910

1011
import static org.seedstack.shed.ClassLoaders.findMostCompleteClassLoader;
@@ -14,10 +15,14 @@
1415
import io.undertow.servlet.Servlets;
1516
import io.undertow.servlet.api.DeploymentInfo;
1617
import io.undertow.servlet.api.DeploymentManager;
18+
import io.undertow.servlet.api.ErrorPage;
1719
import io.undertow.servlet.api.ServletContainerInitializerInfo;
1820
import io.undertow.servlet.util.ImmediateInstanceHandle;
1921
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
22+
import java.util.ArrayList;
23+
import java.util.Collection;
2024
import java.util.HashSet;
25+
import java.util.List;
2126
import java.util.Map;
2227
import java.util.ServiceLoader;
2328
import java.util.Set;
@@ -59,6 +64,7 @@ private DeploymentInfo configureDeploymentInfo() {
5964
.setDefaultSessionTimeout(serverConfig.sessions().getTimeout())
6065
.setResourceManager(new ClassPathResourceManager(mostCompleteClassLoader, META_INF_RESOURCES))
6166
.addWelcomePages(serverConfig.getWelcomeFiles())
67+
.addErrorPages(buildUndertowErrorPages(serverConfig.getErrorPages()))
6268
.addServletContextAttribute(
6369
WebSocketDeploymentInfo.ATTRIBUTE_NAME,
6470
new WebSocketDeploymentInfo()
@@ -81,6 +87,20 @@ private DeploymentInfo configureDeploymentInfo() {
8187
return deploymentInfo;
8288
}
8389

90+
private Collection<ErrorPage> buildUndertowErrorPages(List<WebConfig.ServerConfig.ErrorPage> errorPages) {
91+
List<ErrorPage> undertowErrorPages = new ArrayList<>();
92+
for (WebConfig.ServerConfig.ErrorPage errorPage : errorPages) {
93+
if (errorPage.getExceptionType() != null) {
94+
undertowErrorPages.add(new ErrorPage(errorPage.getLocation(), errorPage.getExceptionType()));
95+
} else if (errorPage.getErrorCode() != null) {
96+
undertowErrorPages.add(new ErrorPage(errorPage.getLocation(), errorPage.getErrorCode()));
97+
} else {
98+
undertowErrorPages.add(new ErrorPage(errorPage.getLocation()));
99+
}
100+
}
101+
return undertowErrorPages;
102+
}
103+
84104
private <T extends ServletContainerInitializer> ServletContainerInitializerInfo
85105
createServletContainerInitializerInfo(
86106
final T servletContainerInitializer) {

web/undertow/src/test/java/org/seedstack/seed/undertow/AbstractUndertowIT.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* License, v. 2.0. If a copy of the MPL was not distributed with this
66
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
77
*/
8+
89
package org.seedstack.seed.undertow;
910

1011
import io.restassured.response.Response;
@@ -91,5 +92,30 @@ public void explicitSubdirWelcomeFiles() {
9192
.get(baseUrl + "/welcome");
9293
}
9394

95+
@Test
96+
@ConfigurationProfiles("errorPages")
97+
public void errorPages() {
98+
expect()
99+
.statusCode(404)
100+
.body(Matchers.containsString("<h1>Not found!</h1>"))
101+
.when()
102+
.get(baseUrl + "/error?code=404");
103+
expect()
104+
.statusCode(415)
105+
.body(Matchers.containsString("<h1>Unsupported media type!</h1>"))
106+
.when()
107+
.get(baseUrl + "/error?code=415");
108+
expect()
109+
.statusCode(403)
110+
.body(Matchers.containsString("<h1>An error occurred!</h1>"))
111+
.when()
112+
.get(baseUrl + "/error?code=403");
113+
expect()
114+
.statusCode(500)
115+
.body(Matchers.containsString("<h1>An error occurred!</h1>"))
116+
.when()
117+
.get(baseUrl + "/exceptionError");
118+
}
119+
94120
abstract ResponseSpecification expect();
95121
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright © 2013-2019, The SeedStack authors <http://seedstack.org>
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
*/
8+
package org.seedstack.seed.undertow.fixtures;
9+
10+
import java.io.IOException;
11+
import javax.servlet.ServletException;
12+
import javax.servlet.annotation.WebServlet;
13+
import javax.servlet.http.HttpServlet;
14+
import javax.servlet.http.HttpServletRequest;
15+
import javax.servlet.http.HttpServletResponse;
16+
17+
@WebServlet(value = {"/error"})
18+
public class ErrorServlet extends HttpServlet {
19+
@Override
20+
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
21+
int code = Integer.parseInt(req.getParameter("code"));
22+
resp.sendError(code);
23+
}
24+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright © 2013-2019, The SeedStack authors <http://seedstack.org>
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
*/
8+
package org.seedstack.seed.undertow.fixtures;
9+
10+
import java.io.IOException;
11+
import javax.servlet.ServletException;
12+
import javax.servlet.annotation.WebServlet;
13+
import javax.servlet.http.HttpServlet;
14+
import javax.servlet.http.HttpServletRequest;
15+
import javax.servlet.http.HttpServletResponse;
16+
17+
@WebServlet(value = {"/exceptionError"})
18+
public class ExceptionErrorServlet extends HttpServlet {
19+
@Override
20+
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
21+
throw new IllegalStateException("ERROR!");
22+
}
23+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>Not found!</h1>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>Unsupported media type!</h1>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>An error occurred!</h1>

web/undertow/src/test/resources/application.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ web:
1515
contextPath: context/ # keep this strange form to test for context path normalization
1616
https<https>: true
1717
welcomeFiles<welcome>: [ 'welcome1.html', 'welcome2.html' ]
18+
errorPages<errorPages>:
19+
- location: /errors/404.html
20+
errorCode: 404
21+
- location: /errors/415.html
22+
errorCode: 415
23+
- location: /errors/default.html
1824
server<refresh>:
1925
port: ${sys.customUndertowPort:'9001'}
2026

0 commit comments

Comments
 (0)