Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Json body field to HttpResponseException #129

Merged
merged 4 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ private void unhandledException(JdkContext ctx, Exception e) {

private void defaultHandling(JdkContext ctx, HttpResponseException exception) {
ctx.status(exception.getStatus());
var jsonResponse = exception.jsonResponse();
if (exception.getStatus() == ErrorCode.REDIRECT.status()) {
ctx.performRedirect();
} else if (jsonResponse != null) {
ctx.json(jsonResponse);
} else if (useJson(ctx)) {
ctx.contentType(APPLICATION_JSON).write(asJsonContent(exception));
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package io.avaje.jex.http;

/** Thrown when unable to find a route/resource */
/** Thrown when request is invalid */
public class BadRequestException extends HttpResponseException {

public BadRequestException(String message) {
SentryMan marked this conversation as resolved.
Show resolved Hide resolved
super(400, message);
}

public BadRequestException(Object jsonResponse) {
super(400, jsonResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,38 @@

/**
* Throwing an uncaught {@code HttpResponseException} will interrupt http processing and set the
* status code and response body with the given message
* status code and response body with the given message or json body
*/
public class HttpResponseException extends RuntimeException {

private final int status;
private final Object jsonResponse;

/**
* @param status the http status to send
* @param message the exception message that will be sent back in the response
*/
public HttpResponseException(int status, String message) {
super(message);
this.status = status;
this.jsonResponse = null;
}

/**
* @param status the http status to send
* @param jsonResponse the response body that will be sent back as json
*/
public HttpResponseException(int status, Object jsonResponse) {

this.status = status;
this.jsonResponse = jsonResponse;
}

public int getStatus() {
return status;
}

public Object jsonResponse() {
return jsonResponse;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package io.avaje.jex.http;

/** Thrown when unable to find a route/resource */
/** Thrown when server has an internal error */
public class InternalServerErrorException extends HttpResponseException {

public InternalServerErrorException(String message) {
super(500, message);
}

public InternalServerErrorException(Object jsonResponse) {
super(500, jsonResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ public class NotFoundException extends HttpResponseException {
public NotFoundException(String message) {
super(404, message);
}

public NotFoundException(Object jsonResponse) {
super(404, jsonResponse);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.avaje.jex.core;

import io.avaje.jex.Jex;
import io.avaje.jex.http.BadRequestException;
import io.avaje.jex.http.ErrorCode;
import io.avaje.jex.http.HttpResponseException;
import io.avaje.jsonb.JsonException;
Expand All @@ -9,6 +10,7 @@
import org.junit.jupiter.api.Test;

import java.net.http.HttpResponse;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

Expand All @@ -34,6 +36,9 @@ static TestPair init() {
.put("/nested", ctx -> {
throw new JsonException("hmm");
})
.patch("/patch", ctx -> {
throw new BadRequestException(Map.of("error","bad request"));
})
.error(NullPointerException.class, (ctx, exception) -> ctx.text("npe"))
.error(IllegalStateException.class, (ctx, exception) -> ctx.status(222).text("Handled IllegalStateException|" + exception.getMessage()))
.error(JsonException.class, (ctx, exception) -> {throw new IllegalStateException();}));
Expand All @@ -60,6 +65,14 @@ void post() {
assertThat(res.body()).isEqualTo("Handled IllegalStateException|foo");
}

@Test
void patch() {
HttpResponse<String> res = pair.request().path("patch").PATCH().asString();
assertThat(res.statusCode()).isEqualTo(400);
assertThat(res.body()).isEqualTo("{\"error\":\"bad request\"}");
assertThat(res.headers().firstValue("Content-Type").get()).contains("application/json");
}

@Test
void expect_fallback_to_fallback() {
HttpResponse<String> res = pair.request().path("nested").PUT().asString();
Expand Down
Loading