com.chargebee.internal.HttpUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of chargebee-java Show documentation
Show all versions of chargebee-java Show documentation
Java client library for ChargeBee API
package com.chargebee.internal;
import com.chargebee.*;
import com.chargebee.exceptions.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.zip.GZIPInputStream;
import org.apache.commons.codec.binary.Base64;
import org.json.*;
public class HttpUtil {
public enum Method {
GET, POST;
}
public static final String CONTENT_TYPE_HEADER_NAME = "Content-Type";
/**
* To temporarily capture the http response
*/
private static class Resp {
int httpCode;
JSONObject jsonContent;
public Map> responseHeaders;
private Resp(int httpCode, JSONObject jsonContent, Map> responseHeaders) {
this.httpCode = httpCode;
this.jsonContent = jsonContent;
this.responseHeaders = responseHeaders;
}
private Result toResult() {
return new Result(httpCode, jsonContent, responseHeaders);
}
private ListResult toListResult() {
return new ListResult(httpCode, jsonContent, responseHeaders);
}
}
public static Result get(String url, Params params, Map headers,Environment env) throws IOException {
if(params != null && !params.isEmpty()) {
url = url + '?' + toQueryStr(params); // fixme: what about url size restrictions ??
}
HttpURLConnection conn = createConnection(url, Method.GET, headers,env);
Resp resp = sendRequest(conn);
return resp.toResult();
}
public static ListResult getList(String url, Params params, Map headers,Environment env) throws IOException {
if(params != null && !params.isEmpty()) {
url = url + '?' + toQueryStr(params, true); // fixme: what about url size restrictions ??
}
HttpURLConnection conn = createConnection(url, Method.GET, headers,env);
Resp resp = sendRequest(conn);
return resp.toListResult();
}
public static Result post(String url, Params params, Map headers, Environment env) throws IOException {
return doFormSubmit(url,Method.POST, toQueryStr(params), headers,env);
}
public static Result post(String url, String content, Map headers, Environment env) throws IOException {
return doFormSubmit(url, Method.POST, content, headers, env);
}
public static String toQueryStr(Params map) {
return toQueryStr(map, false);
}
public static String toQueryStr(Params map, boolean isListReq) {
StringJoiner buf = new StringJoiner("&");
for (Map.Entry entry : map.entries()) {
Object value = entry.getValue();
if(value instanceof List){
List l = (List)value;
if(isListReq){
String keyValPair = enc(entry.getKey()) + "=" + enc(l.isEmpty()?"": l.toString());
buf.add(keyValPair);
continue;
}
for (int i = 0; i < l.size(); i++) {
String val = l.get(i);
String keyValPair = enc(entry.getKey() + "[" + i + "]") + "=" + enc(val != null?val:"");
buf.add(keyValPair);
}
}else{
String keyValPair = enc(entry.getKey()) + "=" + enc((String)value);
buf.add(keyValPair);
}
}
return buf.toString();
}
private static String enc(String val) {
try {
return URLEncoder.encode(val, Environment.CHARSET);
} catch(Exception exp) {
throw new RuntimeException(exp);
}
}
private static Result doFormSubmit(String url,Method m, String queryStr, Map headers,
Environment env) throws IOException {
HttpURLConnection conn = createConnection(url, m, headers,env);
writeContent(conn, queryStr);
Resp resp = sendRequest(conn);
return resp.toResult();
}
private static void writeContent(HttpURLConnection conn, String queryStr) throws IOException {
if (queryStr == null) {
return;
}
OutputStream os = conn.getOutputStream();
try {
os.write(queryStr.getBytes(Environment.CHARSET));
} finally {
os.close();
}
}
private static HttpURLConnection createConnection(String url, Method m,
Map headers,
Environment config)
throws IOException {
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod(m.name());
setTimeouts(conn, config);
addHeaders(conn, config);
addCustomHeaders(conn,headers);
setContentType(conn, m, headers);
if (m == Method.POST) {
conn.setDoOutput(true);
}
conn.setUseCaches(false);
return conn;
}
private static Resp sendRequest(HttpURLConnection conn) throws IOException {
int httpRespCode = conn.getResponseCode();
Map> responseHeaders = conn.getHeaderFields();
if (httpRespCode == HttpURLConnection.HTTP_NO_CONTENT) {
throw new RuntimeException("Got http_no_content response");
}
boolean error = httpRespCode < 200 || httpRespCode > 299;
String content = getContentAsString(conn, error);
JSONObject jsonResp = getContentAsJSON(content);
if(error) {
try {
jsonResp.getString("api_error_code");
String type = jsonResp.optString("type");
String exceptionMessage = jsonResp.getString("message");
if(isBatchApi(conn)) {
throw new BatchAPIException(httpRespCode, exceptionMessage, jsonResp);
}
else if ("payment".equals(type)) {
throw new PaymentException(httpRespCode, exceptionMessage, jsonResp);
} else if ("operation_failed".equals(type)) {
throw new OperationFailedException(httpRespCode, exceptionMessage, jsonResp);
} else if ("invalid_request".equals(type)) {
throw new InvalidRequestException(httpRespCode, exceptionMessage, jsonResp);
} else{
throw new APIException(httpRespCode, exceptionMessage, jsonResp);
}
}catch(APIException ex){
throw ex;
} catch (Exception ex) {
throw new RuntimeException("Error when parsing the error response. Probably not ChargeBee' error response. The content is \n " + content, ex);
}
}
return new Resp(httpRespCode, jsonResp, responseHeaders);
}
private static void setTimeouts(URLConnection conn, Environment config) {
conn.setConnectTimeout(config.connectTimeout);
conn.setReadTimeout(config.readTimeout);
}
private static boolean isBatchApi(HttpURLConnection connection) {
return connection.getURL().toString().contains("/batch/");
}
private static void setContentType(HttpURLConnection conn, Method m, Map headers) {
if(!(headers.containsKey(CONTENT_TYPE_HEADER_NAME))) {
if (m == Method.POST) {
addHeader(conn, "Content-Type", "application/x-www-form-urlencoded;charset=" + Environment.CHARSET);
}
}
}
private static void setContentType(HttpURLConnection conn, Method m) {
if (m == Method.POST) {
addHeader(conn, "Content-Type", "application/x-www-form-urlencoded;charset=" + Environment.CHARSET);
}
}
private static void addHeaders(HttpURLConnection conn, Environment config) {
addHeader(conn, "Accept-Charset", Environment.CHARSET);
addHeader(conn, "User-Agent", String.format("Chargebee-Java-Client v%s", Environment.LIBRARY_VERSION));
addHeader(conn, "Authorization", getAuthValue(config));
addHeader(conn, "Accept", "application/json");
addHeader(conn, "OS-Version",String.format("%s %s %s",System.getProperty("os.name"),System.getProperty("os.arch"),System.getProperty("os.version")));
addHeader(conn,"Lang-Version",System.getProperty("java.version"));
}
private static void addCustomHeaders(HttpURLConnection conn, Map headers) {
for (Map.Entry entry : headers.entrySet()) {
addHeader(conn, entry.getKey(), entry.getValue());
}
}
private static void addHeader(HttpURLConnection conn, String headerName, String value) {
conn.setRequestProperty(headerName, value);
}
private static String getAuthValue(Environment config) {
return "Basic " + Base64.encodeBase64String((config.apiKey + ":").getBytes())
.replaceAll("\r?", "").replaceAll("\n?", "");
}
private static JSONObject getContentAsJSON(String content) throws IOException {
JSONObject obj;
try {
obj = new JSONObject(content);
} catch (JSONException exp) {
if (content.contains("503")){
throw new RuntimeException("Sorry, the server is currently unable to handle the request due to a temporary overload or scheduled maintenance. Please retry after sometime. \n type: internal_temporary_error, \n http_status_code: 503, \n error_code: internal_temporary_error,\n content: " + content,exp);
}
else if (content.contains("504")){
throw new RuntimeException("The server did not receive a timely response from an upstream server, request aborted. If this problem persists, contact us at [email protected]. \n type: gateway_timeout, \n http_status_code: 504, \n error_code: gateway_timeout,\n content: " + content,exp);
}
else{
throw new RuntimeException("Sorry, something went wrong when trying to process the request. If this problem persists, contact us at [email protected]. \n type: internal_error, \n http_status_code: 500, \n error_code: internal_error,\n " + content,exp);
}
}
return obj;
}
private static String getContentAsString(HttpURLConnection conn, boolean error) throws IOException {
InputStream resp = (error) ? conn.getErrorStream() : conn.getInputStream();
if (resp == null) {
throw new RuntimeException("Got Empty Response ");
}
try {
if ("gzip".equalsIgnoreCase(conn.getContentEncoding())) {
resp = new GZIPInputStream(resp);
}
InputStreamReader inp = new InputStreamReader(resp, Environment.CHARSET);
StringBuilder buf = new StringBuilder();
char[] buffer = new char[1024];//Should use content length.
int bytesRead;
while ((bytesRead = inp.read(buffer, 0, buffer.length)) >= 0) {
buf.append(buffer, 0, bytesRead);
}
String content = buf.toString();
return content;
} finally {
resp.close();
}
}
}