com.ksc.http.JsonErrorResponseHandler Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2015-2016 ksyun.com, Inc. or its affiliates. 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.
* A copy of the License is located at
*
* http://ksyun.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.ksc.http;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.fasterxml.jackson.core.JsonFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ksc.KscServiceException;
import com.ksc.KscServiceException.ErrorType;
import com.ksc.annotation.SdkInternalApi;
import com.ksc.internal.http.JsonErrorCodeParser;
import com.ksc.internal.http.JsonErrorMessageParser;
import com.ksc.transform.JsonErrorUnmarshaller;
import com.ksc.util.IOUtils;
@SdkInternalApi
public class JsonErrorResponseHandler implements HttpResponseHandler {
private static final Log LOG = LogFactory.getLog(JsonErrorResponseHandler.class);
private final List unmarshallers;
private final JsonErrorCodeParser errorCodeParser;
private final JsonErrorMessageParser errorMessageParser;
private final JsonFactory jsonFactory;
public JsonErrorResponseHandler(List errorUnmarshallers, JsonErrorCodeParser errorCodeParser,
JsonErrorMessageParser errorMessageParser, JsonFactory jsonFactory) {
this.unmarshallers = errorUnmarshallers;
this.errorCodeParser = errorCodeParser;
this.errorMessageParser = errorMessageParser;
this.jsonFactory = jsonFactory;
}
@Override
public boolean needsConnectionLeftOpen() {
return false;
}
@Override
public KscServiceException handle(HttpResponse response) throws Exception {
JsonContent jsonContent = JsonContent.createJsonContent(response, jsonFactory);
JsonNode errorNode = jsonContent.jsonNode.get("Error");
// String errorCode =
// errorCodeParser.parseErrorCode(response.getHeaders(),
// jsonContent.jsonNode);
KscServiceException ase = new KscServiceException("Unable to parse HTTP response content,not Error");
if (errorNode == null) {
return ase;
}
JsonNode errorCodeNode = errorNode.get("Code");
if (errorCodeNode != null) {
ase.setErrorCode(errorCodeNode.asText());
}
// Jackson has special-casing for 'message' values when deserializing
// Throwables, but sometimes the service passes the error message in
// other JSON fields - handle it here.
ase.setErrorMessage(errorMessageParser.parseErrorMessage(errorNode));
ase.setServiceName(response.getRequest().getServiceName());
ase.setStatusCode(response.getStatusCode());
ase.setErrorType(getErrorTypeFromStatusCode(response.getStatusCode()));
ase.setRawResponse(jsonContent.rawContent);
// String requestId = getRequestIdFromHeaders(response.getHeaders());
JsonNode requestIdNode = jsonContent.jsonNode.get("RequestId");
if (requestIdNode != null) {
ase.setRequestId(requestIdNode.asText());
}
JsonNode errorType = errorNode.get("Type");
if (errorType == null) {
ase.setErrorType(ErrorType.Unknown);
} else if (errorType.asText().equalsIgnoreCase("Receiver")) {
ase.setErrorType(ErrorType.Service);
} else if (errorType.asText().equalsIgnoreCase("Sender")) {
ase.setErrorType(ErrorType.Client);
}
return ase;
}
/**
* Create an AmazonServiceException using the chain of unmarshallers. This
* method will never return null, it will always return a valid
* AmazonServiceException
*
* @param errorCode
* Error code to find an appropriate unmarshaller
* @param jsonContent
* JsonContent of HTTP response
* @return AmazonServiceException
*/
private KscServiceException createException(String errorCode, JsonContent jsonContent) {
if (!jsonContent.isJsonValid()) {
return new KscServiceException("Unable to parse HTTP response content");
}
KscServiceException ase = unmarshallException(errorCode, jsonContent);
if (ase == null) {
ase = new KscServiceException("Unable to unmarshall exception response with the unmarshallers provided");
}
return ase;
}
private KscServiceException unmarshallException(String errorCode, JsonContent jsonContent) {
for (JsonErrorUnmarshaller unmarshaller : unmarshallers) {
if (unmarshaller.matchErrorCode(errorCode)) {
try {
return unmarshaller.unmarshall(jsonContent.jsonNode);
} catch (Exception e) {
LOG.info("Unable to unmarshall exception content", e);
return null;
}
}
}
return null;
}
private ErrorType getErrorTypeFromStatusCode(int statusCode) {
return statusCode < 500 ? ErrorType.Client : ErrorType.Service;
}
private String getRequestIdFromHeaders(Map headers) {
for (Entry headerEntry : headers.entrySet()) {
if (headerEntry.getKey().equalsIgnoreCase(X_KSC_REQUEST_ID_HEADER)) {
return headerEntry.getValue();
}
}
return null;
}
/**
* Simple struct like class to hold both the raw json string content and
* it's parsed JsonNode
*/
private static class JsonContent {
public final byte[] rawContent;
public final JsonNode jsonNode;
@SuppressWarnings("unused")
private final ObjectMapper mapper;
/**
* Static factory method to create a JsonContent object from the
* contents of the HttpResponse provided
*/
public static JsonContent createJsonContent(HttpResponse httpResponse, JsonFactory jsonFactory) {
byte[] rawJsonContent = null;
try {
if (httpResponse.getContent() != null) {
rawJsonContent = IOUtils.toByteArray(httpResponse.getContent());
}
} catch (Exception e) {
LOG.info("Unable to read HTTP response content", e);
}
return new JsonContent(rawJsonContent,
new ObjectMapper(jsonFactory).configure(JsonParser.Feature.ALLOW_COMMENTS, true));
}
private JsonContent(byte[] rawJsonContent, ObjectMapper mapper) {
this.rawContent = rawJsonContent;
this.jsonNode = parseJsonContent(rawJsonContent, mapper);
this.mapper = mapper;
}
private static JsonNode parseJsonContent(byte[] rawJsonContent, ObjectMapper mapper) {
if (rawJsonContent == null) {
return null;
}
try {
return mapper.readTree(rawJsonContent);
} catch (Exception e) {
LOG.info("Unable to parse HTTP response content", e);
return null;
}
}
public boolean isJsonValid() {
return jsonNode != null;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy