Skip to content
This repository was archived by the owner on Sep 26, 2023. It is now read-only.

Commit 8a170d1

Browse files
fix: update exception mapping on HTTP error responses (#1570)
* fix: update exception mapping on HTTP error responses. Interprets HTTP error reponse codes as defined by the canonical error code mapping. Not marking as breaking changes as it affects only httpjson that is not GA-ed. * chore: rename parameter * chore: enhance test Co-authored-by: Mike Eltsufin <meltsufin@google.com>
1 parent b629488 commit 8a170d1

File tree

6 files changed

+113
-200
lines changed

6 files changed

+113
-200
lines changed

‎gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionCallable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public void onSuccess(ResponseT r) {
9595
public void onFailure(Throwable throwable) {
9696
if (throwable instanceof HttpResponseException) {
9797
HttpResponseException e = (HttpResponseException) throwable;
98-
StatusCode statusCode = HttpJsonStatusCode.of(e.getStatusCode(), e.getMessage());
98+
StatusCode statusCode = HttpJsonStatusCode.of(e.getStatusCode());
9999
boolean canRetry = retryableCodes.contains(statusCode.getCode());
100100
String message = e.getStatusMessage();
101101
ApiException newException =

‎gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonOperationSnapshot.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,9 @@ public Builder setResponse(Object response) {
138138
return this;
139139
}
140140

141-
public Builder setError(int errorCode, String errorMessage) {
141+
public Builder setError(int httpStatus, String errorMessage) {
142142
this.errorCode =
143-
HttpJsonStatusCode.of(
144-
errorCode == 0 ? Code.OK.getHttpStatusCode() : errorCode, errorMessage);
143+
httpStatus == 0 ? HttpJsonStatusCode.of(Code.OK) : HttpJsonStatusCode.of(httpStatus);
145144
this.errorMessage = errorMessage;
146145
return this;
147146
}

‎gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonStatusCode.java

Lines changed: 35 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,18 @@
3232
import com.google.api.core.BetaApi;
3333
import com.google.api.core.InternalExtensionOnly;
3434
import com.google.api.gax.rpc.StatusCode;
35-
import com.google.api.gax.rpc.StatusCode.Code;
36-
import com.google.common.base.Strings;
3735
import java.util.Objects;
3836

3937
/** A failure code specific to an HTTP call. */
4038
@BetaApi
4139
@InternalExtensionOnly
4240
public class HttpJsonStatusCode implements StatusCode {
43-
static final String FAILED_PRECONDITION = "FAILED_PRECONDITION";
44-
static final String OUT_OF_RANGE = "OUT_OF_RANGE";
45-
static final String ALREADY_EXISTS = "ALREADY_EXISTS";
46-
static final String DATA_LOSS = "DATA_LOSS";
47-
static final String UNKNOWN = "UNKNOWN";
48-
4941
private final int httpStatus;
5042
private final Code statusCode;
5143

5244
/** Creates a new instance with the given status code. */
53-
public static HttpJsonStatusCode of(int httpStatus, String errorMessage) {
54-
return new HttpJsonStatusCode(httpStatus, httpStatusToStatusCode(httpStatus, errorMessage));
45+
public static HttpJsonStatusCode of(int httpStatus) {
46+
return new HttpJsonStatusCode(httpStatus, httpStatusToStatusCode(httpStatus));
5547
}
5648

5749
public static HttpJsonStatusCode of(Code statusCode) {
@@ -103,56 +95,43 @@ static Code rpcCodeToStatusCode(com.google.rpc.Code rpcCode) {
10395
}
10496
}
10597

106-
static Code httpStatusToStatusCode(int httpStatus, String errorMessage) {
107-
String causeMessage = Strings.nullToEmpty(errorMessage).toUpperCase();
108-
switch (httpStatus) {
109-
case 200:
110-
return Code.OK;
111-
case 400:
112-
if (causeMessage.contains(OUT_OF_RANGE)) {
113-
return Code.OUT_OF_RANGE;
114-
} else if (causeMessage.contains(FAILED_PRECONDITION)) {
115-
return Code.FAILED_PRECONDITION;
116-
} else {
98+
static Code httpStatusToStatusCode(int httpStatus) {
99+
if (200 <= httpStatus && httpStatus < 300) {
100+
return Code.OK;
101+
} else if (400 <= httpStatus && httpStatus < 500) {
102+
switch (httpStatus) {
103+
case 400:
117104
return Code.INVALID_ARGUMENT;
118-
}
119-
case 401:
120-
return Code.UNAUTHENTICATED;
121-
case 403:
122-
return Code.PERMISSION_DENIED;
123-
case 404:
124-
return Code.NOT_FOUND;
125-
case 409:
126-
if (causeMessage.contains(ALREADY_EXISTS)) {
127-
return Code.ALREADY_EXISTS;
128-
} else {
105+
case 401:
106+
return Code.UNAUTHENTICATED;
107+
case 403:
108+
return Code.PERMISSION_DENIED;
109+
case 404:
110+
return Code.NOT_FOUND;
111+
case 409:
129112
return Code.ABORTED;
130-
}
131-
case 411:
132-
throw new IllegalStateException(
133-
"411 status code received (Content-Length header not given.) Please file a bug against https://github.com/googleapis/gax-java/\n"
134-
+ httpStatus);
135-
case 429:
136-
return Code.RESOURCE_EXHAUSTED;
137-
case 499:
138-
return Code.CANCELLED;
139-
case 500:
140-
if (causeMessage.contains(DATA_LOSS)) {
141-
return Code.DATA_LOSS;
142-
} else if (causeMessage.contains(UNKNOWN)) {
143-
return Code.UNKNOWN;
144-
} else {
113+
case 416:
114+
return Code.OUT_OF_RANGE;
115+
case 429:
116+
return Code.RESOURCE_EXHAUSTED;
117+
case 499:
118+
return Code.CANCELLED;
119+
default:
120+
return Code.FAILED_PRECONDITION;
121+
}
122+
} else if (500 <= httpStatus && httpStatus < 600) {
123+
switch (httpStatus) {
124+
case 501:
125+
return Code.UNIMPLEMENTED;
126+
case 503:
127+
return Code.UNAVAILABLE;
128+
case 504:
129+
return Code.DEADLINE_EXCEEDED;
130+
default:
145131
return Code.INTERNAL;
146-
}
147-
case 501:
148-
return Code.UNIMPLEMENTED;
149-
case 503:
150-
return Code.UNAVAILABLE;
151-
case 504:
152-
return Code.DEADLINE_EXCEEDED;
153-
default:
154-
throw new IllegalArgumentException("Unrecognized http status code: " + httpStatus);
132+
}
155133
}
134+
return Code.UNKNOWN;
156135
}
157136

158137
@Override

‎gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonOperationSnapshotTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public void newBuilderTestWithError() {
6767
.build();
6868

6969
assertEquals(testOperationSnapshot.getErrorMessage(), "Forbidden");
70-
assertEquals(testOperationSnapshot.getErrorCode(), HttpJsonStatusCode.of(403, "Forbidden"));
70+
assertEquals(testOperationSnapshot.getErrorCode(), HttpJsonStatusCode.of(403));
7171
assertTrue(testOperationSnapshot.isDone());
7272
}
7373

‎gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonStatusCodeTest.java

Lines changed: 29 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,10 @@
2929
*/
3030
package com.google.api.gax.httpjson;
3131

32-
import static org.junit.Assert.assertEquals;
33-
import static org.junit.Assert.assertNotNull;
32+
import static com.google.common.truth.Truth.assertThat;
3433
import static org.junit.Assert.fail;
3534

36-
import com.google.api.gax.rpc.StatusCode;
37-
import java.util.Arrays;
35+
import com.google.api.gax.rpc.StatusCode.Code;
3836
import java.util.HashSet;
3937
import java.util.Set;
4038
import org.junit.Test;
@@ -43,9 +41,9 @@ public class HttpJsonStatusCodeTest {
4341

4442
@Test
4543
public void rpcCodeToStatusCodeTest() {
46-
Set<StatusCode.Code> allCodes = new HashSet<>();
44+
Set<Code> allCodes = new HashSet<>();
4745
for (com.google.rpc.Code rpcCode : com.google.rpc.Code.values()) {
48-
StatusCode.Code statusCode;
46+
Code statusCode;
4947
try {
5048
statusCode = HttpJsonStatusCode.rpcCodeToStatusCode(rpcCode);
5149
} catch (IllegalArgumentException e) {
@@ -55,77 +53,39 @@ public void rpcCodeToStatusCodeTest() {
5553
continue;
5654
}
5755

58-
assertNotNull(statusCode);
56+
assertThat(statusCode).isNotNull();
5957
allCodes.add(statusCode);
6058
}
6159

62-
assertEquals(allCodes, new HashSet<>(Arrays.asList(StatusCode.Code.values())));
60+
assertThat(Code.values()).asList().containsExactlyElementsIn(allCodes);
6361
}
6462

6563
@Test
6664
public void httpStatusToStatusCodeTest() {
67-
// The HTTP status code conversion logic is currently in the process of being standardized,
68-
// the tested logic may change in nearest future.
69-
final String defaultMessage = "anything";
70-
assertEquals(
71-
StatusCode.Code.OK, HttpJsonStatusCode.httpStatusToStatusCode(200, defaultMessage));
72-
assertEquals(
73-
StatusCode.Code.OUT_OF_RANGE,
74-
HttpJsonStatusCode.httpStatusToStatusCode(400, HttpJsonStatusCode.OUT_OF_RANGE));
75-
assertEquals(
76-
StatusCode.Code.FAILED_PRECONDITION,
77-
HttpJsonStatusCode.httpStatusToStatusCode(400, HttpJsonStatusCode.FAILED_PRECONDITION));
78-
assertEquals(
79-
StatusCode.Code.INVALID_ARGUMENT,
80-
HttpJsonStatusCode.httpStatusToStatusCode(400, defaultMessage));
81-
assertEquals(
82-
StatusCode.Code.UNAUTHENTICATED,
83-
HttpJsonStatusCode.httpStatusToStatusCode(401, defaultMessage));
84-
assertEquals(
85-
StatusCode.Code.PERMISSION_DENIED,
86-
HttpJsonStatusCode.httpStatusToStatusCode(403, defaultMessage));
87-
assertEquals(
88-
StatusCode.Code.NOT_FOUND, HttpJsonStatusCode.httpStatusToStatusCode(404, defaultMessage));
89-
assertEquals(
90-
StatusCode.Code.ALREADY_EXISTS,
91-
HttpJsonStatusCode.httpStatusToStatusCode(409, HttpJsonStatusCode.ALREADY_EXISTS));
92-
assertEquals(
93-
StatusCode.Code.ABORTED, HttpJsonStatusCode.httpStatusToStatusCode(409, defaultMessage));
94-
assertEquals(
95-
StatusCode.Code.RESOURCE_EXHAUSTED,
96-
HttpJsonStatusCode.httpStatusToStatusCode(429, defaultMessage));
97-
assertEquals(
98-
StatusCode.Code.CANCELLED, HttpJsonStatusCode.httpStatusToStatusCode(499, defaultMessage));
99-
assertEquals(
100-
StatusCode.Code.DATA_LOSS,
101-
HttpJsonStatusCode.httpStatusToStatusCode(500, HttpJsonStatusCode.DATA_LOSS));
102-
assertEquals(
103-
StatusCode.Code.UNKNOWN,
104-
HttpJsonStatusCode.httpStatusToStatusCode(500, HttpJsonStatusCode.UNKNOWN));
105-
assertEquals(
106-
StatusCode.Code.INTERNAL, HttpJsonStatusCode.httpStatusToStatusCode(500, defaultMessage));
107-
assertEquals(
108-
StatusCode.Code.UNIMPLEMENTED,
109-
HttpJsonStatusCode.httpStatusToStatusCode(501, defaultMessage));
110-
assertEquals(
111-
StatusCode.Code.UNAVAILABLE,
112-
HttpJsonStatusCode.httpStatusToStatusCode(503, defaultMessage));
113-
assertEquals(
114-
StatusCode.Code.DEADLINE_EXCEEDED,
115-
HttpJsonStatusCode.httpStatusToStatusCode(504, defaultMessage));
65+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(200)).isEqualTo(Code.OK);
66+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(201)).isEqualTo(Code.OK);
11667

117-
try {
118-
HttpJsonStatusCode.httpStatusToStatusCode(411, defaultMessage);
119-
fail();
120-
} catch (IllegalStateException e) {
121-
// expected
122-
}
68+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(400)).isEqualTo(Code.INVALID_ARGUMENT);
69+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(401)).isEqualTo(Code.UNAUTHENTICATED);
70+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(403)).isEqualTo(Code.PERMISSION_DENIED);
71+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(404)).isEqualTo(Code.NOT_FOUND);
72+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(409)).isEqualTo(Code.ABORTED);
73+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(416)).isEqualTo(Code.OUT_OF_RANGE);
74+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(429)).isEqualTo(Code.RESOURCE_EXHAUSTED);
75+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(499)).isEqualTo(Code.CANCELLED);
12376

124-
try {
125-
HttpJsonStatusCode.httpStatusToStatusCode(666, defaultMessage);
126-
fail();
127-
} catch (IllegalArgumentException e) {
128-
// expected
129-
}
77+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(405)).isEqualTo(Code.FAILED_PRECONDITION);
78+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(408)).isEqualTo(Code.FAILED_PRECONDITION);
79+
80+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(500)).isEqualTo(Code.INTERNAL);
81+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(501)).isEqualTo(Code.UNIMPLEMENTED);
82+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(502)).isEqualTo(Code.INTERNAL);
83+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(503)).isEqualTo(Code.UNAVAILABLE);
84+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(504)).isEqualTo(Code.DEADLINE_EXCEEDED);
85+
86+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(100)).isEqualTo(Code.UNKNOWN);
87+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(300)).isEqualTo(Code.UNKNOWN);
88+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(302)).isEqualTo(Code.UNKNOWN);
89+
assertThat(HttpJsonStatusCode.httpStatusToStatusCode(600)).isEqualTo(Code.UNKNOWN);
13090
}
13191
}

0 commit comments

Comments
 (0)