Minor refactorinng of datafaile collector
[nonrtric/plt/ranpm.git] / datafilecollector / src / main / java / org / oran / datafile / http / HttpUtils.java
diff --git a/datafilecollector/src/main/java/org/oran/datafile/http/HttpUtils.java b/datafilecollector/src/main/java/org/oran/datafile/http/HttpUtils.java
new file mode 100644 (file)
index 0000000..02155d3
--- /dev/null
@@ -0,0 +1,229 @@
+/*-
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2018-2023 Nordix Foundation. All rights reserved.
+ * Modifications Copyright (C) 2020-2021 Nokia. 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.oran.datafile.http;
+
+import java.util.Base64;
+import java.util.List;
+
+import org.apache.hc.core5.http.NameValuePair;
+import org.apache.http.HttpStatus;
+import org.oran.datafile.model.FileServerData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class HttpUtils implements HttpStatus {
+
+    private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);
+    public static final int HTTP_DEFAULT_PORT = 80;
+    public static final int HTTPS_DEFAULT_PORT = 443;
+    public static final String JWT_TOKEN_NAME = "access_token";
+    public static final String AUTH_JWT_WARN = "Both JWT token and Basic auth data present. Omitting basic auth info.";
+    public static final String AUTH_JWT_ERROR =
+        "More than one JWT token present in the queryParameters. Omitting JWT token.";
+
+    private HttpUtils() {
+    }
+
+    public static String nonRetryableResponse(int responseCode) {
+        return "Unexpected response code - " + responseCode;
+    }
+
+    public static String retryableResponse(int responseCode) {
+        return "Unexpected response code - " + responseCode + ". No retry attempts will be done.";
+    }
+
+    public static boolean isSuccessfulResponseCodeWithDataRouter(Integer statusCode) {
+        return statusCode >= 200 && statusCode < 300;
+    }
+
+    public static boolean isBasicAuthDataFilled(final FileServerData fileServerData) {
+        return !fileServerData.userId.isEmpty() && !fileServerData.password.isEmpty();
+    }
+
+    public static String basicAuthContent(String username, String password) {
+        return "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes());
+    }
+
+    public static String jwtAuthContent(String token) {
+        return "Bearer " + token;
+    }
+
+    /**
+     * Prepare uri to retrieve file from xNF using HTTP connection. If JWT token was
+     * included
+     * in the queryParameters, it is removed. Other entries are rewritten.
+     *
+     * @param fileServerData fileServerData including - server address, port,
+     *        queryParameters and uriRawFragment
+     * @param remoteFile file which has to be downloaded
+     * @return uri String representing the xNF HTTP location
+     */
+    public static String prepareHttpUri(FileServerData fileServerData, String remoteFile) {
+        return prepareUri("http", fileServerData, remoteFile, HTTP_DEFAULT_PORT);
+    }
+
+    /**
+     * Prepare uri to retrieve file from xNF using HTTPS connection. If JWT token
+     * was included
+     * in the queryParameters, it is removed. Other entries are rewritten.
+     *
+     * @param fileServerData fileServerData including - server address, port,
+     *        queryParameters and uriRawFragment
+     * @param remoteFile file which has to be downloaded
+     * @return uri String representing the xNF HTTPS location
+     */
+    public static String prepareHttpsUri(FileServerData fileServerData, String remoteFile) {
+        return prepareUri("https", fileServerData, remoteFile, HTTPS_DEFAULT_PORT);
+    }
+
+    /**
+     * Prepare uri to retrieve file from xNF. If JWT token was included
+     * in the queryParameters, it is removed. Other entries are rewritten.
+     *
+     * @param scheme scheme which is used during the connection
+     * @param fileServerData fileServerData including - server address, port, query
+     *        and fragment
+     * @param remoteFile file which has to be downloaded
+     * @param defaultPort default port which exchange empty entry for given
+     *        connection type
+     * @return uri String representing the xNF location
+     */
+    public static String prepareUri(String scheme, FileServerData fileServerData, String remoteFile, int defaultPort) {
+        int port = fileServerData.port != null ? fileServerData.port : defaultPort;
+        String query = rewriteQueryWithoutToken(fileServerData.queryParameters);
+        String fragment = fileServerData.uriRawFragment;
+        if (!query.isEmpty()) {
+            query = "?" + query;
+        }
+        if (!fragment.isEmpty()) {
+            fragment = "#" + fragment;
+        }
+        return scheme + "://" + fileServerData.serverAddress + ":" + port + remoteFile + query + fragment;
+    }
+
+    /**
+     * Returns JWT token string (if single exist) from the queryParameters.
+     *
+     * @param fileServerData file server data which contain queryParameters where
+     *        JWT token may exist
+     * @return JWT token value if single token entry exist or empty string
+     *         elsewhere.
+     *         If JWT token key has no value, empty string will be returned.
+     */
+    public static String getJWTToken(FileServerData fileServerData) {
+
+        if (fileServerData.queryParameters.isEmpty()) {
+            return "";
+        }
+        boolean jwtTokenKeyPresent = HttpUtils.isQueryWithSingleJWT(fileServerData.queryParameters);
+        if (!jwtTokenKeyPresent) {
+            return "";
+        }
+        String token = HttpUtils.getJWTToken(fileServerData.queryParameters);
+        if (HttpUtils.isBasicAuthDataFilled(fileServerData)) {
+            logger.warn(HttpUtils.AUTH_JWT_WARN);
+        }
+        return token;
+    }
+
+    /**
+     * Checks if the queryParameters contains single JWT token entry. Valid
+     * queryParameters
+     * contains only one token entry.
+     *
+     * @param query queryParameters
+     * @return true if queryParameters contains single token
+     */
+    public static boolean isQueryWithSingleJWT(List<NameValuePair> query) {
+        if (query == null) {
+            return false;
+        }
+        int i = getJWTTokenCount(query);
+        if (i == 0) {
+            return false;
+        }
+        if (i > 1) {
+            logger.error(AUTH_JWT_ERROR);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns the number of JWT token entries. Valid queryParameters contains only
+     * one token entry.
+     *
+     * @param queryElements elements of the queryParameters
+     * @return true if queryParameters contains single JWT token entry
+     */
+    public static int getJWTTokenCount(List<NameValuePair> queryElements) {
+        int i = 0;
+        for (NameValuePair element : queryElements) {
+            if (element.getName().equals(JWT_TOKEN_NAME)) {
+                i++;
+            }
+        }
+        return i;
+    }
+
+    private static String getJWTToken(List<NameValuePair> query) {
+        for (NameValuePair element : query) {
+            if (!element.getName().equals(JWT_TOKEN_NAME)) {
+                continue;
+            }
+            if (element.getValue() != null) {
+                return element.getValue();
+            }
+            return "";
+        }
+        return "";
+    }
+
+    /**
+     * Rewrites HTTP queryParameters without JWT token
+     *
+     * @param query list of NameValuePair of elements sent in the queryParameters
+     * @return String representation of queryParameters elements which were provided
+     *         in the input
+     *         Empty string is possible when queryParameters is empty or contains
+     *         only access_token key.
+     */
+    public static String rewriteQueryWithoutToken(List<NameValuePair> query) {
+        if (query.isEmpty()) {
+            return "";
+        }
+        StringBuilder sb = new StringBuilder();
+        for (NameValuePair nvp : query) {
+            if (nvp.getName().equals(JWT_TOKEN_NAME)) {
+                continue;
+            }
+            sb.append(nvp.getName());
+            if (nvp.getValue() != null) {
+                sb.append("=");
+                sb.append(nvp.getValue());
+            }
+            sb.append("&");
+        }
+        if ((sb.length() > 0) && (sb.charAt(sb.length() - 1) == '&')) {
+            sb.deleteCharAt(sb.length() - 1);
+        }
+        return sb.toString();
+    }
+}