package com.erdaoya.springcloud.comx.utils.rest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.erdaoya.springcloud.comx.context.Context;
import com.erdaoya.springcloud.comx.source.SourceBizException;
import com.erdaoya.springcloud.comx.source.SourceException;
import com.erdaoya.springcloud.comx.utils.rest.clients.ApacheHttpClient;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.util.*;
/**
* Created by xue on 12/15/16.
*/
public class RequestMessage implements ArrayAccessBase{
public static final String METHOD_GET = "get";
public static final String METHOD_POST = "post";
public static final String METHOD_DELETE = "delete";
public static final String METHOD_PUT = "put";
private static final String HEADER_FIELD_TRACE_ID = "X-Gomeplus-Trace-Id";
private static final String HEADER_FIELD_TRACE_ID_LOWERCASE = "x-gomeplus-trace-id";
private static final String HEADER_FIELD_X_FORWARDED_FOR = "X-Forwarded-For";
private static final String QUERY_FIELD_TRACE_ID = "traceId";
private static final String DEFAULT_TRACE_ID_PREFIX = "COMX";
public static final Integer DEFAULT_TIMEOUT = 10;
@Deprecated
protected HashMap<String, String> commonParameterHolder;
protected Url url;
protected String method;
protected Map<String, Object> data;
protected HashMap<String, String> headerParameters;
protected Integer timeout;
//TODO 重构
protected RestTemplate restTemplate;
public RestTemplate getRestTemplate() {
return restTemplate;
}
public void setRestTemplate(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
// constructors;
public RequestMessage(Url url, String method, Map<String, Object> data, HashMap<String, String> headerParameters, Integer timeout) {
this.url = url;
this.method = method;
this.data = data;
this.headerParameters = headerParameters;
this.timeout = timeout;
}
// implements interface
public boolean containsKey(Object key) {
List<String> templist = Arrays.asList("url", "method", "data", "headerParameters", "timeout");
return templist.contains(key);
}
public Object get(Object key) {
if (key.equals("url")) return url;
if (key.equals("method")) return method;
if (key.equals("data")) return data;
if (key.equals("headerParameters")) return headerParameters;
return null;
}
/**
* 传入context 是为了日共日志功能
* 类原则上可替换
* 抛出异常还是由业务检查抛出异常?
* @param context 当前context
* @return ResponseMessage
*/
public ResponseMessage execute(Context context) throws SourceException {
String targetUrl = url.getUrl();
String requestData = (null != data)?new JSONObject(data).toJSONString():"";
// 执行 HttpClient request 函数
// TODO 需要将错误码和信息 throw 出去
// TODO 暂时用SourceExeption 之后将这一部分抽出去
try {
HttpResponse httpResponse = ApacheHttpClient.request(targetUrl, method.toUpperCase(), requestData, headerParameters, timeout);
int status = httpResponse.getStatusLine().getStatusCode();
HttpEntity entity = httpResponse.getEntity();
String responseBody = (entity != null) ? EntityUtils.toString(entity) : null;
if (status >= 200 && status < 300) {
JSONObject responseBodyJson = JSON.parseObject(responseBody);
return new ResponseMessage(responseBodyJson.get("data"), responseBodyJson.get("message").toString(), status);
} else {
context.getLogger().error("Loading URI:" + targetUrl + " status:" + status + " responseBody:" + responseBody);
JSONObject responseBodyJson;
try {
responseBodyJson = JSON.parseObject(responseBody);
} catch (Exception ex) {
// response body info
throw new SourceBizException("", status);
}
throw new SourceBizException(responseBodyJson.get("message").toString(), status);
}
} catch (IOException ex) {
context.getLogger().error(ex.getMessage());
throw new SourceException(ex);
}
}
/**
* 初始化 traceId
* TODO UUID 生成32位,可以改为更短而不失去精度, http://www.iteye.com/topic/1134781
* @return String
*/
public String initTraceId() {
String traceId = getTraceId();
if (traceId.isEmpty()) {
traceId = DEFAULT_TRACE_ID_PREFIX + UUID.randomUUID().toString();
setHeaderParameter(HEADER_FIELD_TRACE_ID, traceId);
}
return traceId;
}
/**
* traceId 追踪标识
* traceId 是用于追踪日志用的标识字符串, 通过header X-Gomeplus-Trace-Id或 url query traceId传递, header 和URL并存时,以URL为准.
* @return String|""
*/
public String getTraceId() {
String traceId = (String)url.getQuery().get(QUERY_FIELD_TRACE_ID);
if (null != traceId) return traceId;
traceId = getHeaderParameter(HEADER_FIELD_TRACE_ID);
if (null != traceId) return traceId;
traceId = getHeaderParameter(HEADER_FIELD_TRACE_ID_LOWERCASE);
if (null != traceId) return traceId;
return "";
}
//TODO url
public void setTraceId(String newtraceId) {
if (url.getQuery().containsKey(QUERY_FIELD_TRACE_ID)) {
url.getQuery().put(QUERY_FIELD_TRACE_ID, newtraceId);
} else {
setHeaderParameter(HEADER_FIELD_TRACE_ID, newtraceId);
}
}
public String getJsonp() {
return (String)url.getQuery().get("jsonp");
}
private void setHeaderParameter(String key, String value) {
headerParameters.put(key, value);
}
private String getHeaderParameter(String key) {
return headerParameters.get(key);
}
// getters and setters
public Url getUrl() {
return url;
}
public void setUrl(Url url) {
this.url = url;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public Map<String, Object> getData() {
return data;
}
public void setData(Map<String, Object> data) {
this.data = data;
}
public HashMap<String, String> getHeaderParameters() {
return headerParameters;
}
public void setHeaderParameters(HashMap<String, String> headerParameters) {
this.headerParameters = headerParameters;
}
public Integer getTimeout() {
return timeout;
}
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
}