Skip to content

Commit a2b6924

Browse files
committed
- add basic ErrorHandler logic
- ref #3863
1 parent 569bc04 commit a2b6924

5 files changed

Lines changed: 116 additions & 2 deletions

File tree

jooby/src/main/java/io/jooby/StatusCode.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,14 @@ public final class StatusCode {
738738
public static final StatusCode REQUEST_HEADER_FIELDS_TOO_LARGE =
739739
new StatusCode(REQUEST_HEADER_FIELDS_TOO_LARGE_CODE, "Request Header Fields Too Large");
740740

741+
/** {@code 499 The client aborted the request before completion}. */
742+
public static final int CLIENT_CLOSED_REQUEST_CODE = 499;
743+
744+
/** {@code 499 The client aborted the request before completion}. */
745+
public static final StatusCode CLIENT_CLOSED_REQUEST =
746+
new StatusCode(
747+
CLIENT_CLOSED_REQUEST_CODE, "The client aborted the request before completion");
748+
741749
// --- 5xx Server Error ---
742750

743751
/**
@@ -1025,6 +1033,7 @@ public static StatusCode valueOf(final int statusCode) {
10251033
case PRECONDITION_REQUIRED_CODE -> PRECONDITION_REQUIRED;
10261034
case TOO_MANY_REQUESTS_CODE -> TOO_MANY_REQUESTS;
10271035
case REQUEST_HEADER_FIELDS_TOO_LARGE_CODE -> REQUEST_HEADER_FIELDS_TOO_LARGE;
1036+
case CLIENT_CLOSED_REQUEST_CODE -> CLIENT_CLOSED_REQUEST;
10281037
case SERVER_ERROR_CODE -> SERVER_ERROR;
10291038
case NOT_IMPLEMENTED_CODE -> NOT_IMPLEMENTED;
10301039
case BAD_GATEWAY_CODE -> BAD_GATEWAY;

jooby/src/main/java/io/jooby/trpc/TrpcError.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import java.util.Map;
99

10-
public record TrpcError(ErrorDetail error) {
11-
public record ErrorDetail(String message, int code, Map<String, Object> data) {}
10+
public class TrpcError extends RuntimeException {
11+
public TrpcError(String message, int code, Map<String, Object> data) {
12+
super(message);
13+
}
1214
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package io.jooby.trpc;
7+
8+
import io.jooby.StatusCode;
9+
10+
public enum TrpcErrorCode {
11+
PARSE_ERROR(-32700, StatusCode.BAD_REQUEST),
12+
BAD_REQUEST(-32600, StatusCode.BAD_REQUEST),
13+
INTERNAL_SERVER_ERROR(-32603, StatusCode.SERVER_ERROR),
14+
UNAUTHORIZED(-32001, StatusCode.UNAUTHORIZED),
15+
FORBIDDEN(-32003, StatusCode.FORBIDDEN),
16+
NOT_FOUND(-32004, StatusCode.NOT_FOUND),
17+
METHOD_NOT_SUPPORTED(-32005, StatusCode.METHOD_NOT_ALLOWED),
18+
TIMEOUT(-32008, StatusCode.REQUEST_TIMEOUT),
19+
CONFLICT(-32009, StatusCode.CONFLICT),
20+
PRECONDITION_FAILED(-32012, StatusCode.PRECONDITION_FAILED),
21+
PAYLOAD_TOO_LARGE(-32013, StatusCode.REQUEST_ENTITY_TOO_LARGE),
22+
UNPROCESSABLE_CONTENT(-32022, StatusCode.UNPROCESSABLE_ENTITY),
23+
TOO_MANY_REQUESTS(-32029, StatusCode.TOO_MANY_REQUESTS),
24+
CLIENT_CLOSED_REQUEST(-32099, StatusCode.CLIENT_CLOSED_REQUEST);
25+
26+
private final int rpcCode;
27+
private final StatusCode statusCode;
28+
29+
TrpcErrorCode(int rpcCode, StatusCode statusCode) {
30+
this.rpcCode = rpcCode;
31+
this.statusCode = statusCode;
32+
}
33+
34+
public int getRpcCode() {
35+
return rpcCode;
36+
}
37+
38+
public StatusCode getStatusCode() {
39+
return statusCode;
40+
}
41+
42+
/** Helper to map a standard Jooby HTTP status code to the closest tRPC equivalent. */
43+
public static TrpcErrorCode of(StatusCode status) {
44+
for (var code : values()) {
45+
if (code.statusCode.value() == status.value()) {
46+
return code;
47+
}
48+
}
49+
return INTERNAL_SERVER_ERROR; // Fallback
50+
}
51+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package io.jooby.trpc;
7+
8+
import java.util.Map;
9+
10+
import edu.umd.cs.findbugs.annotations.NonNull;
11+
import io.jooby.Context;
12+
import io.jooby.ErrorHandler;
13+
import io.jooby.StatusCode;
14+
15+
public class TrpcErrorHandler implements ErrorHandler {
16+
@Override
17+
public void apply(@NonNull Context ctx, @NonNull Throwable cause, @NonNull StatusCode code) {
18+
if (ctx.getRequestPath().startsWith("/trpc/")) {
19+
20+
var trpcCode = TrpcErrorCode.of(code);
21+
22+
Map<String, Object> errorData =
23+
Map.of(
24+
"code", trpcCode.name(),
25+
"httpStatus", code.value(),
26+
"path", ctx.getRequestPath().replace("/trpc/", ""));
27+
28+
var errorDetail =
29+
new TrpcError.ErrorDetail(cause.getMessage(), trpcCode.getRpcCode(), errorData);
30+
var trpcResponse = new TrpcError(errorDetail);
31+
32+
ctx.setResponseCode(code).render(trpcResponse);
33+
}
34+
}
35+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package io.jooby.trpc;
7+
8+
import edu.umd.cs.findbugs.annotations.NonNull;
9+
import io.jooby.Extension;
10+
import io.jooby.Jooby;
11+
12+
public class TrpcModule implements Extension {
13+
@Override
14+
public void install(@NonNull Jooby application) throws Exception {
15+
application.error(new TrpcErrorHandler());
16+
}
17+
}

0 commit comments

Comments
 (0)