2 * ============LICENSE_START======================================================================
3 * Copyright (C) 2018-2023 Nordix Foundation. All rights reserved.
4 * Modifications Copyright (C) 2020-2021 Nokia. All rights reserved
5 * ===============================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 * ============LICENSE_END========================================================================
20 package org.oran.datafile.http;
22 import java.util.Base64;
23 import java.util.List;
25 import org.apache.hc.core5.http.NameValuePair;
26 import org.apache.http.HttpStatus;
27 import org.oran.datafile.model.FileServerData;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
31 public final class HttpUtils implements HttpStatus {
33 private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);
34 public static final int HTTP_DEFAULT_PORT = 80;
35 public static final int HTTPS_DEFAULT_PORT = 443;
36 public static final String JWT_TOKEN_NAME = "access_token";
37 public static final String AUTH_JWT_WARN = "Both JWT token and Basic auth data present. Omitting basic auth info.";
38 public static final String AUTH_JWT_ERROR =
39 "More than one JWT token present in the queryParameters. Omitting JWT token.";
44 public static String nonRetryableResponse(int responseCode) {
45 return "Unexpected response code - " + responseCode;
48 public static String retryableResponse(int responseCode) {
49 return "Unexpected response code - " + responseCode + ". No retry attempts will be done.";
52 public static boolean isSuccessfulResponseCodeWithDataRouter(Integer statusCode) {
53 return statusCode >= 200 && statusCode < 300;
56 public static boolean isBasicAuthDataFilled(final FileServerData fileServerData) {
57 return !fileServerData.userId.isEmpty() && !fileServerData.password.isEmpty();
60 public static String basicAuthContent(String username, String password) {
61 return "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes());
64 public static String jwtAuthContent(String token) {
65 return "Bearer " + token;
69 * Prepare uri to retrieve file from xNF using HTTP connection. If JWT token was
71 * in the queryParameters, it is removed. Other entries are rewritten.
73 * @param fileServerData fileServerData including - server address, port,
74 * queryParameters and uriRawFragment
75 * @param remoteFile file which has to be downloaded
76 * @return uri String representing the xNF HTTP location
78 public static String prepareHttpUri(FileServerData fileServerData, String remoteFile) {
79 return prepareUri("http", fileServerData, remoteFile, HTTP_DEFAULT_PORT);
83 * Prepare uri to retrieve file from xNF using HTTPS connection. If JWT token
85 * in the queryParameters, it is removed. Other entries are rewritten.
87 * @param fileServerData fileServerData including - server address, port,
88 * queryParameters and uriRawFragment
89 * @param remoteFile file which has to be downloaded
90 * @return uri String representing the xNF HTTPS location
92 public static String prepareHttpsUri(FileServerData fileServerData, String remoteFile) {
93 return prepareUri("https", fileServerData, remoteFile, HTTPS_DEFAULT_PORT);
97 * Prepare uri to retrieve file from xNF. If JWT token was included
98 * in the queryParameters, it is removed. Other entries are rewritten.
100 * @param scheme scheme which is used during the connection
101 * @param fileServerData fileServerData including - server address, port, query
103 * @param remoteFile file which has to be downloaded
104 * @param defaultPort default port which exchange empty entry for given
106 * @return uri String representing the xNF location
108 public static String prepareUri(String scheme, FileServerData fileServerData, String remoteFile, int defaultPort) {
109 int port = fileServerData.port != null ? fileServerData.port : defaultPort;
110 String query = rewriteQueryWithoutToken(fileServerData.queryParameters);
111 String fragment = fileServerData.uriRawFragment;
112 if (!query.isEmpty()) {
115 if (!fragment.isEmpty()) {
116 fragment = "#" + fragment;
118 return scheme + "://" + fileServerData.serverAddress + ":" + port + remoteFile + query + fragment;
122 * Returns JWT token string (if single exist) from the queryParameters.
124 * @param fileServerData file server data which contain queryParameters where
125 * JWT token may exist
126 * @return JWT token value if single token entry exist or empty string
128 * If JWT token key has no value, empty string will be returned.
130 public static String getJWTToken(FileServerData fileServerData) {
132 if (fileServerData.queryParameters.isEmpty()) {
135 boolean jwtTokenKeyPresent = HttpUtils.isQueryWithSingleJWT(fileServerData.queryParameters);
136 if (!jwtTokenKeyPresent) {
139 String token = HttpUtils.getJWTToken(fileServerData.queryParameters);
140 if (HttpUtils.isBasicAuthDataFilled(fileServerData)) {
141 logger.warn(HttpUtils.AUTH_JWT_WARN);
147 * Checks if the queryParameters contains single JWT token entry. Valid
149 * contains only one token entry.
151 * @param query queryParameters
152 * @return true if queryParameters contains single token
154 public static boolean isQueryWithSingleJWT(List<NameValuePair> query) {
158 int i = getJWTTokenCount(query);
163 logger.error(AUTH_JWT_ERROR);
170 * Returns the number of JWT token entries. Valid queryParameters contains only
173 * @param queryElements elements of the queryParameters
174 * @return true if queryParameters contains single JWT token entry
176 public static int getJWTTokenCount(List<NameValuePair> queryElements) {
178 for (NameValuePair element : queryElements) {
179 if (element.getName().equals(JWT_TOKEN_NAME)) {
186 private static String getJWTToken(List<NameValuePair> query) {
187 for (NameValuePair element : query) {
188 if (!element.getName().equals(JWT_TOKEN_NAME)) {
191 if (element.getValue() != null) {
192 return element.getValue();
200 * Rewrites HTTP queryParameters without JWT token
202 * @param query list of NameValuePair of elements sent in the queryParameters
203 * @return String representation of queryParameters elements which were provided
205 * Empty string is possible when queryParameters is empty or contains
206 * only access_token key.
208 public static String rewriteQueryWithoutToken(List<NameValuePair> query) {
209 if (query.isEmpty()) {
212 StringBuilder sb = new StringBuilder();
213 for (NameValuePair nvp : query) {
214 if (nvp.getName().equals(JWT_TOKEN_NAME)) {
217 sb.append(nvp.getName());
218 if (nvp.getValue() != null) {
220 sb.append(nvp.getValue());
224 if ((sb.length() > 0) && (sb.charAt(sb.length() - 1) == '&')) {
225 sb.deleteCharAt(sb.length() - 1);
227 return sb.toString();