com.dynatrace.openkit.protocol.StatusResponse Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openkit-java Show documentation
Show all versions of openkit-java Show documentation
Dynatrace OpenKit - Java Reference Implementation
The newest version!
/**
* Copyright 2018-2021 Dynatrace LLC
*
* 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.
*/
package com.dynatrace.openkit.protocol;
import com.dynatrace.openkit.api.Logger;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Implements a status response which is sent for the request types status check and beacon send.
*/
public class StatusResponse {
/**
* Response code sent by HTTP server to indicate success.
*/
public static final int HTTP_OK = 200;
/**
* Bad request is error code 400 in the HTTP protocol.
*/
public static final int HTTP_BAD_REQUEST = 400;
/**
* Too many requests sent by client (rate limiting) error code.
*/
public static final int HTTP_TOO_MANY_REQUESTS = 429;
/**
* Key in the HTTP response headers for Retry-After
*/
static final String RESPONSE_KEY_RETRY_AFTER = "retry-after";
/**
* Default "Retry-After" is 10 minutes.
*/
static final long DEFAULT_RETRY_AFTER_IN_MILLISECONDS = 10L * 60L * 1000L;
/**
* Value that is sent if response status indicates an error.
*
*
* The status is part of the payload {@link ResponseAttributes}.
*
*/
static final String RESPONSE_STATUS_ERROR = "ERROR";
private final Logger logger;
private final int responseCode;
private final Map> headers;
private final ResponseAttributes responseAttributes;
// *** constructors ***
private StatusResponse(Logger logger, ResponseAttributes responseAttributes, int responseCode, Map> headers) {
this.logger = logger;
this.responseAttributes = responseAttributes;
this.responseCode = responseCode;
this.headers = responseHeadersWithLowerCaseKeys(headers);
}
private static Map> responseHeadersWithLowerCaseKeys(Map> headers) {
Map> result = new HashMap<>(headers.size());
for (Map.Entry> entry : headers.entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
result.put(entry.getKey().toLowerCase(), entry.getValue());
}
}
return Collections.unmodifiableMap(result);
}
public static StatusResponse createSuccessResponse(
Logger logger,
ResponseAttributes responseAttributes,
int responseCode,
Map> headers) {
return new StatusResponse(logger, responseAttributes, responseCode, headers);
}
public static StatusResponse createErrorResponse(Logger logger, int responseCode) {
return createErrorResponse(logger, responseCode, new HashMap>());
}
public static StatusResponse createErrorResponse(Logger logger, int responseCode, Map> headers) {
ResponseAttributes responseAttributes = ResponseAttributesImpl.withUndefinedDefaults().build();
return new StatusResponse(logger, responseAttributes, responseCode, headers);
}
public boolean isErroneousResponse() {
return getResponseCode() >= HTTP_BAD_REQUEST || isStatusSetToError();
}
private boolean isStatusSetToError() {
if (!responseAttributes.isAttributeSet(ResponseAttribute.STATUS)) {
// no status sent - therefore no error
return false;
}
return RESPONSE_STATUS_ERROR.equals(responseAttributes.getStatus());
}
public int getResponseCode() {
return responseCode;
}
/**
* Returns the attributes received as response from the server.
*/
public ResponseAttributes getResponseAttributes() {
return responseAttributes;
}
public long getRetryAfterInMilliseconds() {
List values = getHeaders().get(RESPONSE_KEY_RETRY_AFTER);
if (values == null) {
// the Retry-After response header is missing
logger.warning(RESPONSE_KEY_RETRY_AFTER + " is not available - using default value " + DEFAULT_RETRY_AFTER_IN_MILLISECONDS);
return DEFAULT_RETRY_AFTER_IN_MILLISECONDS;
}
if (values.size() != 1) {
// the Retry-After response header has multiple values, but only one is expected
logger.warning(RESPONSE_KEY_RETRY_AFTER + " has unexpected number of values - using default value " + DEFAULT_RETRY_AFTER_IN_MILLISECONDS);
return DEFAULT_RETRY_AFTER_IN_MILLISECONDS;
}
// according to RFC 7231 Section 7.1.3 (https://tools.ietf.org/html/rfc7231#section-7.1.3)
// Retry-After value can either be a delay seconds value, which is a non-negative decimal integer
// or it is an HTTP date.
// Our implementation assumes only delay seconds value here
int delaySeconds;
try {
delaySeconds = Integer.parseInt(values.get(0));
} catch (NumberFormatException e) {
logger.error("Failed to parse " + RESPONSE_KEY_RETRY_AFTER + " value \"" + values.get(0)
+ "\" - using default value " + DEFAULT_RETRY_AFTER_IN_MILLISECONDS);
return DEFAULT_RETRY_AFTER_IN_MILLISECONDS;
}
// convert delay seconds to milliseconds
return delaySeconds * 1000L;
}
Map> getHeaders() {
return headers;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy