*/
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 {
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);
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());
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;
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 {
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);
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);
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());
}
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();
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;
}
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();
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;
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;
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);
}
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());
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());
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);
--- /dev/null
+/*-
+ * ============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;
+ }
+}
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 {
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");
}};
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 {
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);
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;
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 {
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";
@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);
@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);
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));
@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);
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));