diff --git a/build.savant b/build.savant
index c7351a7..dd70019 100644
--- a/build.savant
+++ b/build.savant
@@ -18,7 +18,7 @@ restifyVersion = "4.2.1"
slf4jVersion = "2.0.17"
testngVersion = "7.11.0"
-project(group: "io.fusionauth", name: "java-http", version: "1.1.2", licenses: ["ApacheV2_0"]) {
+project(group: "io.fusionauth", name: "java-http", version: "1.2.0", licenses: ["ApacheV2_0"]) {
workflow {
fetch {
// Dependency resolution order:
diff --git a/pom.xml b/pom.xml
index 4a813d0..426fdfa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
+ * This allows you to customize the status code and logging behavior. + *
+ * Must not be null. + * + * @param unexpectedExceptionHandler The unexpected exception handler. + * @return This. + */ + default T withUnexpectedExceptionHandler(HTTPUnexpectedExceptionHandler unexpectedExceptionHandler) { + configuration().withUnexpectedExceptionHandler(unexpectedExceptionHandler); + return (T) this; + } + /** * This configures the duration of the initial delay before calculating and enforcing the minimum write throughput. Defaults to 5 * seconds. diff --git a/src/main/java/io/fusionauth/http/server/DefaultHTTPUnexpectedExceptionHandler.java b/src/main/java/io/fusionauth/http/server/DefaultHTTPUnexpectedExceptionHandler.java new file mode 100644 index 0000000..e6db6e6 --- /dev/null +++ b/src/main/java/io/fusionauth/http/server/DefaultHTTPUnexpectedExceptionHandler.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025, FusionAuth, All Rights Reserved + * + * 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.fusionauth.http.server; + +/** + * THe default HTTP unexpected exception handler. + * + * @author Daniel DeGroff + */ +public class DefaultHTTPUnexpectedExceptionHandler implements HTTPUnexpectedExceptionHandler { + @Override + public void handle(ExceptionHandlerContext context) { + context.getLogger() + .error(String.format("[%s] Closing socket with status [%d]. An HTTP worker threw an exception while processing a request.", + Thread.currentThread().threadId(), + context.getStatusCode()), + context.getThrowable()); + } +} diff --git a/src/main/java/io/fusionauth/http/server/ExceptionHandlerContext.java b/src/main/java/io/fusionauth/http/server/ExceptionHandlerContext.java new file mode 100644 index 0000000..894cf42 --- /dev/null +++ b/src/main/java/io/fusionauth/http/server/ExceptionHandlerContext.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2025, FusionAuth, All Rights Reserved + * + * 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.fusionauth.http.server; + +import io.fusionauth.http.log.Logger; + +/** + * Provide context to the exception handler. + * + * @author Daniel DeGroff + */ +public class ExceptionHandlerContext { + private final Logger logger; + + private final HTTPRequest request; + + private final Throwable throwable; + + private int statusCode; + + public ExceptionHandlerContext(Logger logger, HTTPRequest request, int statusCode, Throwable throwable) { + this.logger = logger; + this.request = request; + this.statusCode = statusCode; + this.throwable = throwable; + } + + /** + * This is provided for convenience, but you may wish to use your own logger. + * + * @return the optional logger to use in the exception handler. + */ + public Logger getLogger() { + return logger; + } + + /** + * This may be useful if you wish to know additional context of the exception such as the URI of the current HTTP request. + *
+ * Modifications to this object will have no effect on current or futures requests.
+ *
+ * @return the current HTTP request, or null if this exception was taking prior to constructing the HTTP request. This is unlikely but
+ * please account for this value being null.
+ */
+ public HTTPRequest getRequest() {
+ return request;
+ }
+
+ /**
+ * @return the desired status code for the HTTP response.
+ */
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ /**
+ * Suggest a status code for the HTTP response. This value will be used unless the response has already been committed meaning bytes have
+ * already been written to the client and the HTTP server is not able to modify the response code.
+ *
+ * @param statusCode the desired status code to set on the HTTP response.
+ */
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ /**
+ * @return the unexpected exception to handle
+ */
+ public Throwable getThrowable() {
+ return throwable;
+ }
+}
diff --git a/src/main/java/io/fusionauth/http/server/HTTPServerConfiguration.java b/src/main/java/io/fusionauth/http/server/HTTPServerConfiguration.java
index 113a8b8..2a1e6c2 100644
--- a/src/main/java/io/fusionauth/http/server/HTTPServerConfiguration.java
+++ b/src/main/java/io/fusionauth/http/server/HTTPServerConfiguration.java
@@ -79,6 +79,8 @@ public class HTTPServerConfiguration implements Configurable