diff options
author | Marek Szwałkiewicz <marek.szwalkiewicz@external.t-mobile.pl> | 2023-03-02 12:43:50 +0100 |
---|---|---|
committer | Marek Szwałkiewicz <marek.szwalkiewicz@external.t-mobile.pl> | 2023-03-03 12:42:35 +0100 |
commit | 508489a4ea7000b9e24cdb0ea48f5357010d783e (patch) | |
tree | d0ae300483b4fb943194ce8f0535a19eb9c1b8f5 | |
parent | 928348966d924f7cf41077f98ab6665ea6aec512 (diff) |
Enable case insensitive matching of http headers
This change creates simple case insensitive map implementation that
is used in HttpSdcResponse class to store the response headers.
Generally HTTP headers are supposed to be case insensitive and
sometimes get transformed (in our case - by istio sidecar) to lower case.
With this change lower case will still be matched and the original
behaviour will not break.
Issue-ID: SDC-4233
Signed-off-by: Marek Szwałkiewicz <marek.szwalkiewicz@external.t-mobile.pl>
Change-Id: I1cb9d9e75ff656ccb12c690c553bccc672332a12
9 files changed, 95 insertions, 36 deletions
diff --git a/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpRequestFactory.java b/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpRequestFactory.java index 9e2f3ee..ab4bd29 100644 --- a/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpRequestFactory.java +++ b/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpRequestFactory.java @@ -19,15 +19,16 @@ */ package org.onap.sdc.http; + import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.message.BasicHeader; +import org.onap.sdc.utils.CaseInsensitiveMap; import java.util.Base64; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; public class HttpRequestFactory { @@ -40,14 +41,14 @@ public class HttpRequestFactory { this.authHeaderValue = "Basic " + Base64.getEncoder().encodeToString(createAuthHeaderData(user, password)); } - public HttpGet createHttpGetRequest(String url, Map<String, String> headersMap) { + public HttpGet createHttpGetRequest(String url, CaseInsensitiveMap<String, String> headersMap) { HttpGet httpGet = new HttpGet(url); httpGet.setHeaders(createHttpRequestHeaders(headersMap, authHeaderValue)); return httpGet; } - public HttpPost createHttpPostRequest(String url, Map<String, String> headersMap, HttpEntity entity) { + public HttpPost createHttpPostRequest(String url, CaseInsensitiveMap<String, String> headersMap, HttpEntity entity) { HttpPost httpPost = new HttpPost(url); httpPost.setHeaders(createHttpRequestHeaders(headersMap, authHeaderValue)); httpPost.setEntity(entity); @@ -55,7 +56,7 @@ public class HttpRequestFactory { return httpPost; } - private Header[] createHttpRequestHeaders(Map<String, String> headersMap, String authorizationValue) { + private Header[] createHttpRequestHeaders(CaseInsensitiveMap<String, String> headersMap, String authorizationValue) { final List<Header> headers = headersMap.entrySet().stream() .map(it -> new BasicHeader(it.getKey(), it.getValue())) .collect(Collectors.toList()); diff --git a/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpSdcClient.java b/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpSdcClient.java index 8b6ee0a..73663e6 100644 --- a/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpSdcClient.java +++ b/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpSdcClient.java @@ -31,6 +31,7 @@ import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.onap.sdc.api.consumer.IConfiguration; import org.onap.sdc.utils.Pair; +import org.onap.sdc.utils.CaseInsensitiveMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,8 +39,6 @@ import java.io.IOException; import java.net.ConnectException; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; public class HttpSdcClient implements IHttpSdcClient { @@ -75,11 +74,11 @@ public class HttpSdcClient implements IHttpSdcClient { this.httpClient = httpClientPair.getSecond(); } - public HttpSdcResponse postRequest(String requestUrl, HttpEntity entity, Map<String, String> headersMap) { + public HttpSdcResponse postRequest(String requestUrl, HttpEntity entity, CaseInsensitiveMap<String, String> headersMap) { return postRequest(requestUrl, entity, headersMap, ALWAYS_CLOSE_THE_REQUEST_CONNECTION).getFirst(); } - public Pair<HttpSdcResponse, CloseableHttpResponse> postRequest(String requestUrl, HttpEntity entity, Map<String, String> headersMap, boolean closeTheRequest) { + public Pair<HttpSdcResponse, CloseableHttpResponse> postRequest(String requestUrl, HttpEntity entity, CaseInsensitiveMap<String, String> headersMap, boolean closeTheRequest) { Pair<HttpSdcResponse, CloseableHttpResponse> ret; final String url = resolveUrl(requestUrl); log.debug("url to send {}", url); @@ -100,11 +99,11 @@ public class HttpSdcClient implements IHttpSdcClient { return ret; } - public HttpSdcResponse getRequest(String requestUrl, Map<String, String> headersMap) { + public HttpSdcResponse getRequest(String requestUrl, CaseInsensitiveMap<String, String> headersMap) { return getRequest(requestUrl, headersMap, ALWAYS_CLOSE_THE_REQUEST_CONNECTION).getFirst(); } - public Pair<HttpSdcResponse, CloseableHttpResponse> getRequest(String requestUrl, Map<String, String> headersMap, boolean closeTheRequest) { + public Pair<HttpSdcResponse, CloseableHttpResponse> getRequest(String requestUrl, CaseInsensitiveMap<String, String> headersMap, boolean closeTheRequest) { Pair<HttpSdcResponse, CloseableHttpResponse> ret; final String url = resolveUrl(requestUrl); @@ -118,7 +117,7 @@ public class HttpSdcClient implements IHttpSdcClient { log.debug("GET Response Status {}", httpResponse.getStatusLine().getStatusCode()); Header[] headersRes = httpResponse.getAllHeaders(); - Map<String, String> headersResMap = new HashMap<>(); + CaseInsensitiveMap<String, String> headersResMap = new CaseInsensitiveMap<>(); for (Header header : headersRes) { headersResMap.put(header.getName(), header.getValue()); } diff --git a/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpSdcResponse.java b/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpSdcResponse.java index ad64f3f..46a2c48 100644 --- a/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpSdcResponse.java +++ b/sdc-distribution-client/src/main/java/org/onap/sdc/http/HttpSdcResponse.java @@ -20,15 +20,15 @@ package org.onap.sdc.http; -import java.util.Map; - import org.apache.http.HttpEntity; +import org.onap.sdc.utils.CaseInsensitiveMap; + public class HttpSdcResponse { private int status; private HttpEntity message; - private Map<String, String> headersMap; + private CaseInsensitiveMap<String, String> headersMap; public HttpSdcResponse(int status, HttpEntity message) { super(); @@ -36,18 +36,18 @@ public class HttpSdcResponse { this.message = message; } - public HttpSdcResponse(int status, HttpEntity message, Map<String, String> headersMap) { + public HttpSdcResponse(int status, HttpEntity message, CaseInsensitiveMap<String, String> headersMap) { super(); this.status = status; this.message = message; this.headersMap = headersMap; } - public Map<String, String> getHeadersMap() { + public CaseInsensitiveMap<String, String> getHeadersMap() { return headersMap; } - public void setHeadersMap(Map<String, String> headersMap) { + public void setHeadersMap(CaseInsensitiveMap<String, String> headersMap) { this.headersMap = headersMap; } diff --git a/sdc-distribution-client/src/main/java/org/onap/sdc/http/IHttpSdcClient.java b/sdc-distribution-client/src/main/java/org/onap/sdc/http/IHttpSdcClient.java index 9adce23..3ea4795 100644 --- a/sdc-distribution-client/src/main/java/org/onap/sdc/http/IHttpSdcClient.java +++ b/sdc-distribution-client/src/main/java/org/onap/sdc/http/IHttpSdcClient.java @@ -20,15 +20,14 @@ package org.onap.sdc.http; -import java.util.Map; - +import org.onap.sdc.utils.CaseInsensitiveMap; import org.apache.http.HttpEntity; public interface IHttpSdcClient { - HttpSdcResponse postRequest(String requestUrl, HttpEntity entity, Map<String, String> headersMap); + HttpSdcResponse postRequest(String requestUrl, HttpEntity entity, CaseInsensitiveMap<String, String> headersMap); - HttpSdcResponse getRequest(String requestUrl, Map<String, String> headersMap); + HttpSdcResponse getRequest(String requestUrl, CaseInsensitiveMap<String, String> headersMap); void closeHttpClient(); diff --git a/sdc-distribution-client/src/main/java/org/onap/sdc/http/SdcConnectorClient.java b/sdc-distribution-client/src/main/java/org/onap/sdc/http/SdcConnectorClient.java index 18aba95..f96a9a8 100644 --- a/sdc-distribution-client/src/main/java/org/onap/sdc/http/SdcConnectorClient.java +++ b/sdc-distribution-client/src/main/java/org/onap/sdc/http/SdcConnectorClient.java @@ -29,9 +29,7 @@ import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.UUID; import org.apache.commons.io.IOUtils; @@ -50,6 +48,7 @@ import org.onap.sdc.utils.DistributionActionResultEnum; import org.onap.sdc.utils.DistributionClientConstants; import org.onap.sdc.utils.Pair; import org.onap.sdc.utils.kafka.KafkaDataResponse; +import org.onap.sdc.utils.CaseInsensitiveMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -116,7 +115,7 @@ public class SdcConnectorClient { private Pair<HttpSdcResponse, CloseableHttpResponse> performSdcServerRequest(String sdcUrl) { String requestId = generateRequestId(); - Map<String, String> requestHeaders = addHeadersToHttpRequest(requestId); + CaseInsensitiveMap<String, String> requestHeaders = addHeadersToHttpRequest(requestId); log.debug("about to perform get on SDC. requestId= {} url= {}", requestId, sdcUrl); return httpClient.getRequest(sdcUrl, requestHeaders, false); } @@ -129,7 +128,7 @@ public class SdcConnectorClient { DistributionClientDownloadResultImpl response; String requestId = generateRequestId(); - Map<String, String> requestHeaders = new HashMap<>(); + CaseInsensitiveMap<String, String> requestHeaders = new CaseInsensitiveMap<>(); requestHeaders.put(DistributionClientConstants.HEADER_REQUEST_ID, requestId); requestHeaders.put(DistributionClientConstants.HEADER_INSTANCE_ID, configuration.getConsumerID()); requestHeaders.put(HttpHeaders.ACCEPT, ContentType.APPLICATION_OCTET_STREAM.toString()); @@ -196,8 +195,8 @@ public class SdcConnectorClient { return result; } - protected Map<String, String> addHeadersToHttpRequest(String requestId) { - Map<String, String> requestHeaders = new HashMap<>(); + protected CaseInsensitiveMap<String, String> addHeadersToHttpRequest(String requestId) { + CaseInsensitiveMap<String, String> requestHeaders = new CaseInsensitiveMap<>(); requestHeaders.put(DistributionClientConstants.HEADER_REQUEST_ID, requestId); requestHeaders.put(DistributionClientConstants.HEADER_INSTANCE_ID, configuration.getConsumerID()); requestHeaders.put(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()); @@ -269,8 +268,8 @@ public class SdcConnectorClient { try { is = entity.getContent(); String artifactName = ""; - if (getServersResponse.getHeadersMap().containsKey(CONTENT_DISPOSITION_HEADER)) { - artifactName = getServersResponse.getHeadersMap().get(CONTENT_DISPOSITION_HEADER); + if (getServersResponse.getHeadersMap().containsCaseInsensitiveKey(CONTENT_DISPOSITION_HEADER)) { + artifactName = getServersResponse.getHeadersMap().getCaseInsensitiveKey(CONTENT_DISPOSITION_HEADER); } byte[] payload = IOUtils.toByteArray(is); diff --git a/sdc-distribution-client/src/main/java/org/onap/sdc/utils/CaseInsensitiveMap.java b/sdc-distribution-client/src/main/java/org/onap/sdc/utils/CaseInsensitiveMap.java new file mode 100644 index 0000000..efb1120 --- /dev/null +++ b/sdc-distribution-client/src/main/java/org/onap/sdc/utils/CaseInsensitiveMap.java @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * sdc-distribution-client + * ================================================================================ + * Copyright (C) 2023 Deutsche Telekom Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.sdc.utils; + +import java.util.HashMap; + +/** + * A custom map implementation that allows case-insensitive key checks + * + * This is used for response/request headers that can be transformed to + * lowercase by the ingress/envoy sidecar. + * HTTP headers are case-insensitive according to RFC 2616 + * + * @author mszwalkiewicz + */ +public class CaseInsensitiveMap<K, V> extends HashMap<K, V> { + + public boolean containsCaseInsensitiveKey(String key) { + for (K existingKey : keySet()) { + if (existingKey.toString().equalsIgnoreCase(key)) { + return true; + } + } + return false; + } + + public V getCaseInsensitiveKey(String key) { + for (K existingKey : keySet()) { + if (existingKey.toString().equalsIgnoreCase(key)) { + return super.get(existingKey); + } + } + return null; + } +} diff --git a/sdc-distribution-client/src/test/java/org/onap/sdc/http/HttpAsdcClientTest.java b/sdc-distribution-client/src/test/java/org/onap/sdc/http/HttpAsdcClientTest.java index cbd12c3..6193e4c 100644 --- a/sdc-distribution-client/src/test/java/org/onap/sdc/http/HttpAsdcClientTest.java +++ b/sdc-distribution-client/src/test/java/org/onap/sdc/http/HttpAsdcClientTest.java @@ -41,6 +41,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.onap.sdc.utils.Pair; import org.onap.sdc.utils.TestConfiguration; +import org.onap.sdc.utils.CaseInsensitiveMap; @ExtendWith(MockitoExtension.class) class HttpSdcClientTest { @@ -51,7 +52,7 @@ class HttpSdcClientTest { private static final String K_2 = "k2"; private static final String V_2 = "v2"; private static final Header[] HEADERS = new Header[]{new BasicHeader(K_1, V_1), new BasicHeader(K_2, V_2)}; - private static final HashMap<String, String> HEADERS_MAP = new HashMap<String, String>() {{ + private static final CaseInsensitiveMap<String, String> HEADERS_MAP = new CaseInsensitiveMap<String, String>() {{ put("key1", "key2"); }}; diff --git a/sdc-distribution-client/src/test/java/org/onap/sdc/http/HttpRequestFactoryTest.java b/sdc-distribution-client/src/test/java/org/onap/sdc/http/HttpRequestFactoryTest.java index c9eb4b3..a5404ae 100644 --- a/sdc-distribution-client/src/test/java/org/onap/sdc/http/HttpRequestFactoryTest.java +++ b/sdc-distribution-client/src/test/java/org/onap/sdc/http/HttpRequestFactoryTest.java @@ -25,12 +25,11 @@ import static org.mockito.Mockito.mock; import java.net.URI; import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.Map; import org.apache.http.HttpEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.junit.jupiter.api.Test; +import org.onap.sdc.utils.CaseInsensitiveMap; class HttpRequestFactoryTest { @@ -40,7 +39,7 @@ class HttpRequestFactoryTest { private static final String HEADER_KEY_2 = "key2"; private static final String HEADER_VALUE_1 = "value1"; private static final String HEADER_VALUE_2 = "value2"; - private static final Map<String, String> HEADERS = new HashMap<String, String>() { + private static final CaseInsensitiveMap<String, String> HEADERS = new CaseInsensitiveMap<String, String>() { { put(HEADER_KEY_1, HEADER_VALUE_1); put(HEADER_KEY_2, HEADER_VALUE_2); diff --git a/sdc-distribution-client/src/test/java/org/onap/sdc/http/SdcConnectorClientTest.java b/sdc-distribution-client/src/test/java/org/onap/sdc/http/SdcConnectorClientTest.java index 61b8388..e449c4c 100644 --- a/sdc-distribution-client/src/test/java/org/onap/sdc/http/SdcConnectorClientTest.java +++ b/sdc-distribution-client/src/test/java/org/onap/sdc/http/SdcConnectorClientTest.java @@ -38,7 +38,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.http.HttpEntity; @@ -54,6 +53,7 @@ import org.onap.sdc.api.results.IDistributionClientResult; import org.onap.sdc.utils.DistributionActionResultEnum; import org.onap.sdc.utils.Pair; import org.onap.sdc.utils.kafka.KafkaDataResponse; +import org.onap.sdc.utils.CaseInsensitiveMap; public class SdcConnectorClientTest { @@ -61,7 +61,7 @@ public class SdcConnectorClientTest { private static final HttpSdcClient httpClient = mock(HttpSdcClient.class); private static final IConfiguration configuration = mock(IConfiguration.class); private static final HttpSdcResponse httpSdcResponse = mock(HttpSdcResponse.class); - private static final Map<String, String> mockHeaders = new HashMap<>(); + private static final Map<String, String> mockHeaders = new CaseInsensitiveMap<>(); private static SdcConnectorClient sdcClient; private static final String ARTIFACT_URL = "http://127.0.0.1/artifact/url"; @@ -219,7 +219,7 @@ public class SdcConnectorClientTest { @Test public void downloadArtifactHappyScenarioTest() throws IOException { - Map<String, String> headers = new HashMap<>(); + CaseInsensitiveMap<String, String> headers = new CaseInsensitiveMap<>(); headers.put(SdcConnectorClient.CONTENT_DISPOSITION_HEADER, "SomeHeader"); IArtifactInfo artifactInfo = mock(IArtifactInfo.class); @@ -242,6 +242,9 @@ public class SdcConnectorClientTest { @Test public void downloadArtifactDataIntegrityProblemTest() throws IOException { + CaseInsensitiveMap<String, String> headers = new CaseInsensitiveMap<>(); + headers.put(SdcConnectorClient.CONTENT_DISPOSITION_HEADER, "SomeHeader"); + IArtifactInfo artifactInfo = mock(IArtifactInfo.class); when(artifactInfo.getArtifactURL()).thenReturn(ARTIFACT_URL); @@ -251,6 +254,7 @@ public class SdcConnectorClientTest { when(responseMock.getStatus()).thenReturn(HttpStatus.SC_OK); when(responseMock.getMessage()).thenReturn(messageMock); + when(responseMock.getHeadersMap()).thenReturn(headers); when(messageMock.getContent()).thenReturn(new ByteArrayInputStream(BYTES)); doReturn(responsePair).when(httpClient).getRequest(eq(ARTIFACT_URL), any(), eq(false)); @@ -260,6 +264,9 @@ public class SdcConnectorClientTest { @Test public void downloadArtifactExceptionDuringDownloadHandlingTest() throws IOException { + CaseInsensitiveMap<String, String> headers = new CaseInsensitiveMap<>(); + headers.put(SdcConnectorClient.CONTENT_DISPOSITION_HEADER, "SomeHeader"); + IArtifactInfo artifactInfo = mock(IArtifactInfo.class); when(artifactInfo.getArtifactURL()).thenReturn(ARTIFACT_URL); @@ -269,6 +276,7 @@ public class SdcConnectorClientTest { when(responseMock.getStatus()).thenReturn(HttpStatus.SC_OK); when(responseMock.getMessage()).thenReturn(messageMock); + when(responseMock.getHeadersMap()).thenReturn(headers); when(messageMock.getContent()).thenReturn(new ThrowingInputStreamForTesting()); doReturn(responsePair).when(httpClient).getRequest(eq(ARTIFACT_URL), any(), eq(false)); |