-
Notifications
You must be signed in to change notification settings - Fork 29
feat: [OpenAPI] ResponseMetadataListener with case insensitive header map
#1070
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
Changes from 84 commits
888bc4d
3473fff
7991ce9
6638e7a
c08ceb6
a697b6e
28e8135
c3e438f
c934b1f
ea0eeb6
b81f4c2
50a57bb
6a33cf6
cde369f
7aed42d
d4747ad
03933a0
27cc015
112360d
a9e609b
2f684c6
aa60080
73ffecc
f4358bc
3ce5400
ad8a738
d8add74
0c0176c
db04109
ffada46
cd26cf8
8357f5f
4d5b97b
e1390af
97c5e03
59fedb1
c5cba53
e6ec8b9
f16b2c9
1b4ffcb
c56376c
0773674
943de3c
cc08bfb
bdc8c72
3387432
64c7bdd
8257a9a
45e4dbc
41ef22f
50a0e0f
eb21453
acff1d1
9f00a54
1c0bef8
84b4e9e
f02fd1d
cefb244
1632d2c
1e00604
31d8620
0a71d8e
119dd09
a84b2ca
476fef7
5884d6e
5f61ebf
4835a34
de76c72
067ddc8
de01665
b7d623e
16f26ab
1226e6f
4cf87b9
d8bc954
f1216a9
d8a945e
859a8f1
f05242f
c6483a2
27c7843
587e038
49a1081
3c7ee80
b75ed48
b94ace5
aa1f126
ffbdd19
139dd1d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.sap.cloud.sdk.services.openapi.apache; | ||
|
|
||
| @FunctionalInterface | ||
| public interface ResponseMetadataListener | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Minor/Nitpick)
|
||
| { | ||
| void onResponse( OpenApiResponse response ); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could create a new class |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| package com.sap.cloud.sdk.services.openapi.apiclient; | ||
|
|
||
| import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; | ||
| import static com.github.tomakehurst.wiremock.client.WireMock.get; | ||
| import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; | ||
| import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; | ||
| import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; | ||
| import static com.github.tomakehurst.wiremock.client.WireMock.verify; | ||
| import static org.assertj.core.api.Assertions.assertThat; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.concurrent.atomic.AtomicReference; | ||
|
|
||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||
| import com.fasterxml.jackson.core.type.TypeReference; | ||
| import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; | ||
| import com.github.tomakehurst.wiremock.junit5.WireMockTest; | ||
| import com.sap.cloud.sdk.services.openapi.apache.ApiClient; | ||
| import com.sap.cloud.sdk.services.openapi.apache.BaseApi; | ||
| import com.sap.cloud.sdk.services.openapi.apache.OpenApiResponse; | ||
| import com.sap.cloud.sdk.services.openapi.apache.Pair; | ||
| import com.sap.cloud.sdk.services.openapi.core.OpenApiRequestException; | ||
|
|
||
| import lombok.Data; | ||
|
|
||
| @WireMockTest | ||
| class ApacheApiClientResponseHandlingTest | ||
| { | ||
| private static final String TEST_PATH = "/test"; | ||
| private static final String TEST_RESPONSE_BODY = "{\"message\": \"success\"}"; | ||
|
|
||
| @Test | ||
| void testResponseMetadataListener( final WireMockRuntimeInfo wmInfo ) | ||
| { | ||
| stubFor( | ||
| get(urlEqualTo(TEST_PATH)) | ||
| .willReturn( | ||
| aResponse() | ||
| .withStatus(200) | ||
| .withHeader("x-custom-header", "some-value") | ||
| .withBody(TEST_RESPONSE_BODY))); | ||
|
|
||
| final AtomicReference<OpenApiResponse> metadata = new AtomicReference<>(); | ||
| final ApiClient apiClient = | ||
| ApiClient.create().withBasePath(wmInfo.getHttpBaseUrl()).withResponseMetadataListener(metadata::set); | ||
|
|
||
| final TestApi api = new TestApi(apiClient); | ||
| final TestResponse result = api.executeRequest(); | ||
|
|
||
| assertThat(result).isNotNull(); | ||
| assertThat(result.getMessage()).isEqualTo("success"); | ||
| assertThat(metadata.get()).isNotNull(); | ||
| assertThat(metadata.get().getStatusCode()).isEqualTo(200); | ||
| assertThat(metadata.get().getHeaders()).isNotEmpty(); | ||
| assertThat(metadata.get().getHeaders()).containsKey("x-custom-header"); | ||
|
|
||
| verify(1, getRequestedFor(urlEqualTo(TEST_PATH))); | ||
| } | ||
|
|
||
| @Test | ||
| void testCaseInsensitiveHeaderLookup( final WireMockRuntimeInfo wmInfo ) | ||
| { | ||
| stubFor( | ||
| get(urlEqualTo(TEST_PATH)) | ||
| .willReturn( | ||
| aResponse() | ||
| .withStatus(200) | ||
| .withBody(TEST_RESPONSE_BODY) | ||
| .withHeader("x-custom-header", "some-value"))); | ||
|
|
||
| final AtomicReference<OpenApiResponse> capturedResponse = new AtomicReference<>(); | ||
| final ApiClient apiClient = | ||
| ApiClient | ||
| .create() | ||
| .withBasePath(wmInfo.getHttpBaseUrl()) | ||
| .withResponseMetadataListener(capturedResponse::set); | ||
|
|
||
| final TestApi api = new TestApi(apiClient); | ||
| api.executeRequest(); | ||
|
|
||
| // Verify case-insensitive access works | ||
| final Map<String, List<String>> headers = capturedResponse.get().getHeaders(); | ||
| assertThat(headers.get("x-custom-header")).contains("some-value"); | ||
| assertThat(headers.get("X-Custom-Header")).contains("some-value"); | ||
| assertThat(headers.get("X-CUSTOM-HEADER")).contains("some-value"); | ||
| } | ||
|
|
||
| private static class TestApi extends BaseApi | ||
| { | ||
| private final String path; | ||
|
|
||
| TestApi( final ApiClient apiClient ) | ||
| { | ||
| this(apiClient, TEST_PATH); | ||
| } | ||
|
|
||
| TestApi( final ApiClient apiClient, final String path ) | ||
| { | ||
| super(apiClient); | ||
| this.path = path; | ||
| } | ||
|
|
||
| TestResponse executeRequest() | ||
| throws OpenApiRequestException | ||
| { | ||
| final List<Pair> localVarQueryParams = new ArrayList<>(); | ||
| final List<Pair> localVarCollectionQueryParams = new ArrayList<>(); | ||
| final Map<String, String> localVarHeaderParams = new HashMap<>(); | ||
| final Map<String, Object> localVarFormParams = new HashMap<>(); | ||
|
|
||
| final String[] localVarAccepts = { "application/json" }; | ||
| final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts); | ||
|
|
||
| final String[] localVarContentTypes = {}; | ||
| final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes); | ||
|
|
||
| final TypeReference<TestResponse> localVarReturnType = new TypeReference<TestResponse>() | ||
| { | ||
| }; | ||
|
|
||
| return apiClient | ||
| .invokeAPI( | ||
| path, | ||
| "GET", | ||
| localVarQueryParams, | ||
| localVarCollectionQueryParams, | ||
| null, | ||
| null, | ||
| localVarHeaderParams, | ||
| localVarFormParams, | ||
| localVarAccept, | ||
| localVarContentType, | ||
| localVarReturnType); | ||
| } | ||
| } | ||
|
|
||
| @Data | ||
| private static class TestResponse | ||
| { | ||
| @JsonProperty( "message" ) | ||
| private String message; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Map.copy()doesn't return aTreeMapand therefore removes the nice case insensitive matching of headers. Instead I opted to make the treeMap unmodifiable at creation site withCollections.unmodifiableMap()