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

Adds reponseheaders to API excpetion #299

Merged
merged 7 commits into from
Apr 27, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

## [0.4.3] - 2023-04-17

### Added

- Adds responseHeader to APIException class

## [0.4.2] - 2023-03-31

### Added
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.microsoft.kiota;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;

/** Parent type for exceptions thrown by the client when receiving failed responses to its requests. */
Expand All @@ -23,4 +26,8 @@ public ApiException(@Nonnull final Throwable cause) {

/** The HTTP status code for the response*/
public int responseStatusCode;

/** The HTTP response headers for the error response*/
@Nonnull
public Map<String, List<String>> responseHeaders = new HashMap<String, List<String>>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -581,13 +581,15 @@ private Response throwIfFailedResponse(@Nonnull final Response response, @Nonnul

final String statusCodeAsString = Integer.toString(response.code());
final Integer statusCode = response.code();
final Map<String, List<String>> responseHeaders = response.headers().toMultimap();
if (errorMappings == null ||
!errorMappings.containsKey(statusCodeAsString) &&
!(statusCode >= 400 && statusCode < 500 && errorMappings.containsKey("4XX")) &&
!(statusCode >= 500 && statusCode < 600 && errorMappings.containsKey("5XX"))) {
spanForAttributes.setAttribute(errorMappingFoundAttributeName, false);
final ApiException result = new ApiException("the server returned an unexpected status code and no error class is registered for this code " + statusCode);
result.responseStatusCode = statusCode;
result.responseHeaders = responseHeaders;
spanForAttributes.recordException(result);
throw result;
}
Expand All @@ -606,6 +608,7 @@ private Response throwIfFailedResponse(@Nonnull final Response response, @Nonnul
closeResponse = false;
final ApiException result = new ApiException("service returned status code" + statusCode + " but no response body was found");
result.responseStatusCode = statusCode;
result.responseHeaders = responseHeaders;
spanForAttributes.recordException(result);
throw result;
}
Expand All @@ -620,6 +623,7 @@ private Response throwIfFailedResponse(@Nonnull final Response response, @Nonnul
result = new ApiException("unexpected error type " + error.getClass().getName());
}
result.responseStatusCode = statusCode;
result.responseHeaders = responseHeaders;
spanForAttributes.recordException(result);
throw result;
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.microsoft.kiota.HttpMethod;
import com.microsoft.kiota.RequestInformation;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.io.InputStream;
import java.io.IOException;
import java.net.URI;
Expand All @@ -23,6 +24,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import org.mockito.stubbing.Answer;
import org.junit.jupiter.api.Test;

import okhttp3.Call;
import okhttp3.Callback;
Expand All @@ -34,6 +36,8 @@
import okhttp3.Response;
import okhttp3.ResponseBody;

import com.microsoft.kiota.ApiException;

public class OkHttpRequestAdapterTest {
@ParameterizedTest
@EnumSource(value = HttpMethod.class, names = {"PUT", "POST", "PATCH"})
Expand Down Expand Up @@ -142,6 +146,36 @@ public void SendReturnsObjectOnContent(int statusCode) throws Exception {
final var response = requestAdapter.sendAsync(requestInformation, (node) -> mockEntity, null).get();
assertNotNull(response);
}
@Test
public void throwsAPIException() throws Exception {
final var authenticationProviderMock = mock(AuthenticationProvider.class);
when(authenticationProviderMock.authenticateRequest(any(RequestInformation.class), any(Map.class))).thenReturn(CompletableFuture.completedFuture(null));
final var client = getMockClient(new Response.Builder()
.code(404)
.message("Not Found")
.protocol(Protocol.HTTP_1_1)
.request(new Request.Builder().url("http://localhost").build())
.body(ResponseBody.create("test".getBytes("UTF-8"), MediaType.parse("application/json")))
.header("request-id", "request-id-value")
.build());
final var requestInformation = new RequestInformation() {{
setUri(new URI("https://localhost"));
httpMethod = HttpMethod.GET;
}};
final var mockEntity = mock(Parsable.class);
when(mockEntity.getFieldDeserializers()).thenReturn(new HashMap<>());
final var mockParseNode = mock(ParseNode.class);
when(mockParseNode.getObjectValue(any(ParsableFactory.class))).thenReturn(mockEntity);
final var mockFactory = mock(ParseNodeFactory.class);
when(mockFactory.getParseNode(any(String.class), any(InputStream.class))).thenReturn(mockParseNode);
when(mockFactory.getValidContentType()).thenReturn("application/json");
final var requestAdapter = new OkHttpRequestAdapter(authenticationProviderMock, mockFactory, null, client);
final var exception = assertThrows(ExecutionException.class, ()->requestAdapter.sendAsync(requestInformation, (node) -> mockEntity, null).get()) ;
final var cause = exception.getCause();
assertTrue(cause instanceof ApiException);
assertEquals(404, ((ApiException)cause).responseStatusCode);
assertTrue(((ApiException)cause).responseHeaders.containsKey("request-id"));
}
public static OkHttpClient getMockClient(final Response response) throws IOException {
final OkHttpClient mockClient = mock(OkHttpClient.class);
final Call remoteCall = mock(Call.class);
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ org.gradle.caching=true
mavenGroupId = com.microsoft.kiota
mavenMajorVersion = 0
mavenMinorVersion = 4
mavenPatchVersion = 2
mavenPatchVersion = 3
mavenArtifactSuffix =

#These values are used to run functional tests
Expand Down