
com.github.bingoohuang.springrestclient.utils.RestReq Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spring-rest-client Show documentation
Show all versions of spring-rest-client Show documentation
convenient spring rest client for rest services
package com.github.bingoohuang.springrestclient.utils;
import com.github.bingoohuang.springrestclient.annotations.SuccInResponseJSONProperty;
import com.github.bingoohuang.springrestclient.exception.RestException;
import com.github.bingoohuang.springrestclient.provider.BaseUrlProvider;
import com.github.bingoohuang.springrestclient.provider.SignProvider;
import com.github.bingoohuang.springrestclient.xml.Xmls;
import com.github.bingoohuang.utils.codec.Json;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.mashape.unirest.request.BaseRequest;
import com.mashape.unirest.request.HttpRequest;
import com.mashape.unirest.request.HttpRequestWithBody;
import com.mashape.unirest.request.ValueUtils;
import com.mashape.unirest.request.body.MultipartBody;
import lombok.val;
import org.springframework.context.ApplicationContext;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.InputStream;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class RestReq {
final SuccInResponseJSONProperty succInResponseJSONProperty;
final Map fixedRequestParams;
final Map> sendStatusExceptionMappings;
final Class> apiClass;
final BaseUrlProvider baseUrlProvider;
final String prefix;
final Map routeParams;
final Map requestParams;
final Map cookies;
final RestLog restLog;
final SignProvider signProvider;
final ApplicationContext appContext;
final RequestParamsHelper requestParamsHelper;
final String firstConsume;
RestReq(
String firstConsume,
SuccInResponseJSONProperty succInResponseJSONProperty,
Map fixedRequestParams,
Map> sendStatusExceptionMappings,
Class> apiClass,
BaseUrlProvider baseUrlProvider,
String prefix,
Map routeParams,
Map requestParams,
Map cookies,
boolean async,
SignProvider signProvider,
ApplicationContext appContext) {
this.firstConsume = firstConsume;
this.succInResponseJSONProperty = succInResponseJSONProperty;
this.fixedRequestParams = fixedRequestParams;
this.sendStatusExceptionMappings = sendStatusExceptionMappings;
this.apiClass = apiClass;
this.baseUrlProvider = baseUrlProvider;
this.prefix = prefix;
this.routeParams = routeParams;
this.requestParams = requestParams;
this.cookies = cookies;
this.restLog = new RestLog(apiClass, async);
this.signProvider = signProvider;
this.appContext = appContext;
this.requestParamsHelper = new RequestParamsHelper(
fixedRequestParams, requestParams, appContext);
}
static ThreadLocal> lastResponseTL;
static {
lastResponseTL = new ThreadLocal>();
}
public static HttpResponse> lastResponse() {
return lastResponseTL.get();
}
public String get() throws Throwable {
String url = createUrl();
HttpRequest get = Unirest.get(url);
setRouteParamsAndCookie(get);
get.queryString(requestParamsHelper.mergeRequestParams());
return request(null, get);
}
public InputStream getBinary() throws Throwable {
String url = createUrl();
HttpRequest get = Unirest.get(url);
setRouteParamsAndCookie(get);
get.queryString(requestParamsHelper.mergeRequestParams());
return requestBinary(null, get);
}
public Future> getAsync() throws Throwable {
String url = createUrl();
HttpRequest get = Unirest.get(url);
setRouteParamsAndCookie(get);
get.queryString(requestParamsHelper.mergeRequestParams());
return requestAsync(null, get);
}
public Future> getAsyncBinary() throws Throwable {
String url = createUrl();
HttpRequest get = Unirest.get(url);
setRouteParamsAndCookie(get);
get.queryString(requestParamsHelper.mergeRequestParams());
return requestAsyncBinary(null, get);
}
public String post() throws Throwable {
String url = createUrl();
HttpRequestWithBody post = Unirest.post(url);
setRouteParamsAndCookie(post);
post.queryString(requestParamsHelper.createQueryParams());
val requestParams = requestParamsHelper.mergeRequestParamsWithoutQueryParams();
BaseRequest fields = fields(post, requestParams);
return request(requestParams, fields);
}
public InputStream postBinary() throws Throwable {
String url = createUrl();
HttpRequestWithBody post = Unirest.post(url);
setRouteParamsAndCookie(post);
post.queryString(requestParamsHelper.createQueryParams());
val requestParams = requestParamsHelper.mergeRequestParamsWithoutQueryParams();
BaseRequest fields = fields(post, requestParams);
return requestBinary(requestParams, fields);
}
private BaseRequest fields(
HttpRequestWithBody post, Map requestParams) {
MultipartBody field = null;
for (Map.Entry entry : requestParams.entrySet()) {
Object value = entry.getValue();
boolean isFileCollection = false;
if (value instanceof Collection) {
isFileCollection = true;
for (Object o : (Collection) value) {
if (o instanceof File || o instanceof MultipartFile)
field = fieldFileOrElse(post, field, entry, o);
else {
isFileCollection = false;
break;
}
}
}
if (!isFileCollection) {
field = fieldFileOrElse(post, field, entry, value);
}
}
return field == null ? post : field;
}
private MultipartBody fieldFileOrElse(HttpRequestWithBody post,
MultipartBody field,
Map.Entry entry,
Object value) {
if (value instanceof File) {
if (field != null) field.field(entry.getKey(), (File) value);
else field = post.field(entry.getKey(), (File) value);
} else if (value instanceof MultipartFile) {
if (field != null)
field.field(entry.getKey(), (MultipartFile) value);
else field = post.field(entry.getKey(), (MultipartFile) value);
} else {
if (field != null) field.field(entry.getKey(), value);
else field = post.field(entry.getKey(), value);
}
return field;
}
public Future> postAsync() throws Throwable {
String url = createUrl();
val post = Unirest.post(url);
setRouteParamsAndCookie(post);
post.queryString(requestParamsHelper.createQueryParams());
val requestParams = requestParamsHelper.mergeRequestParamsWithoutQueryParams();
BaseRequest fields = fields(post, requestParams);
return requestAsync(requestParams, fields);
}
public Future> postAsyncBinary() throws Throwable {
String url = createUrl();
val post = Unirest.post(url);
setRouteParamsAndCookie(post);
post.queryString(requestParamsHelper.createQueryParams());
val requestParams = requestParamsHelper.mergeRequestParamsWithoutQueryParams();
BaseRequest fields = fields(post, requestParams);
return requestAsyncBinary(requestParams, fields);
}
static boolean callBlackcat = classExists(
"com.github.bingoohuang.blackcat.javaagent.callback.Blackcat");
public static boolean classExists(String className) {
try {
Class.forName(className);
return true;
} catch (Throwable e) { // including ClassNotFoundException
return false;
}
}
private void setRouteParamsAndCookie(HttpRequest httpRequest) {
if (callBlackcat) {
com.github.bingoohuang.blackcat.javaagent.callback
.Blackcat.prepareRPC(httpRequest);
}
for (Map.Entry entry : routeParams.entrySet()) {
String value = String.valueOf(entry.getValue());
httpRequest.routeParam(entry.getKey(), value);
}
val cookieStr = new StringBuilder();
for (Map.Entry entry : cookies.entrySet()) {
String value = String.valueOf(entry.getValue());
cookieStr.append(' ').append(entry.getKey()).append("=").append(value).append(";");
}
if (cookieStr.length() > 0)
httpRequest.header("Cookie", cookieStr.toString());
}
public String postBody(Object bean) throws Throwable {
val post = createPost();
val body = createBody(post, bean);
post.body(body);
val requestParams = createJsonBody(body);
return request(requestParams, post);
}
public InputStream postBodyBinary(Object bean) throws Throwable {
val post = createPost();
val body = createBody(post, bean);
post.body(body);
val requestParams = createJsonBody(body);
return requestBinary(requestParams, post);
}
public Future> postBodyAsync(Object bean) throws Throwable {
val post = createPost();
val body = createBody(post, bean);
post.body(body);
Map requestParams = createJsonBody(body);
return requestAsync(requestParams, post);
}
public Future> postBodyAsyncBinary(Object bean) throws Throwable {
val post = createPost();
val body = createBody(post, bean);
post.body(body);
val requestParams = createJsonBody(body);
return requestAsyncBinary(requestParams, post);
}
private Map createJsonBody(String body) {
Map requestParams = Maps.newHashMap();
requestParams.put("_json", body);
return requestParams;
}
private HttpRequestWithBody createPost() {
String url = createUrl();
val post = Unirest.post(url);
setRouteParamsAndCookie(post);
post.queryString(requestParamsHelper.mergeRequestParams());
return post;
}
private String createBody(HttpRequestWithBody post, Object bean) {
if (firstConsume != null && firstConsume.indexOf("/xml") >= 0) {
post.header("Content-Type", "application/xml;charset=UTF-8");
return Xmls.marshal(bean);
} else {
post.header("Content-Type", "application/json;charset=UTF-8");
return ValueUtils.processValue(bean);
}
}
private String request(Map reqParams, BaseRequest httpReq)
throws Throwable {
boolean loggedResponse = false;
try {
restLog.logAndSign(signProvider, reqParams, httpReq.getHttpRequest());
lastResponseTL.remove();
val response = httpReq.asString();
restLog.log(response);
loggedResponse = true;
lastResponseTL.set(response);
if (isSuccessful(response))
return RestClientUtils.nullOrBody(response);
throw processStatusExceptionMappings(response);
} catch (UnirestException e) {
if (!loggedResponse) restLog.log(e);
throw new RuntimeException(e);
} catch (Throwable e) {
if (!loggedResponse) restLog.log(e);
throw e;
}
}
private InputStream requestBinary(Map reqParams, BaseRequest httpReq)
throws Throwable {
boolean loggedResponse = false;
try {
restLog.logAndSign(signProvider, reqParams, httpReq.getHttpRequest());
lastResponseTL.remove();
val response = httpReq.asBinary();
restLog.log(response);
loggedResponse = true;
lastResponseTL.set(response);
if (isSuccessful(response))
return RestClientUtils.nullOrBody(response);
throw processStatusExceptionMappings(response);
} catch (UnirestException e) {
if (!loggedResponse) restLog.log(e);
throw new RuntimeException(e);
} catch (Throwable e) {
if (!loggedResponse) restLog.log(e);
throw e;
}
}
private Future> requestAsync(
Map reqParams, BaseRequest httpReq)
throws Throwable {
restLog.logAndSign(signProvider, reqParams, httpReq.getHttpRequest());
lastResponseTL.remove(); // clear response threadlocal before execution
val callback = new UniRestCallback(apiClass, restLog);
val future = httpReq.asStringAsync(callback);
return new Future>() {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return future.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return callback.isCancelled();
}
@Override
public boolean isDone() {
return callback.isDone();
}
@Override
public HttpResponse get()
throws InterruptedException, ExecutionException {
return callback.get();
}
@Override
public HttpResponse get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return callback.get(unit.toMillis(timeout));
}
};
}
private Future> requestAsyncBinary(
Map requestParams, BaseRequest httpRequest)
throws Throwable {
restLog.logAndSign(signProvider, requestParams, httpRequest.getHttpRequest());
lastResponseTL.remove(); // clear response threadlocal before execution
val callback = new UniRestCallback(apiClass, restLog);
val future = httpRequest.asBinaryAsync(callback);
return new Future>() {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return future.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return callback.isCancelled();
}
@Override
public boolean isDone() {
return callback.isDone();
}
@Override
public HttpResponse get()
throws InterruptedException, ExecutionException {
return callback.get();
}
@Override
public HttpResponse get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return callback.get(unit.toMillis(timeout));
}
};
}
public Throwable processStatusExceptionMappings(HttpResponse> response)
throws Throwable {
Class extends Throwable> exceptionClass;
exceptionClass = sendStatusExceptionMappings.get(response.getStatus());
String msg = response.header("error-msg");
if (Strings.isNullOrEmpty(msg)) {
Object body = response.getBody();
msg = body instanceof InputStream ? "" : ("" + body);
}
if (exceptionClass == null)
throw new RestException(response.getStatus(), msg);
throw Obj.createObject(exceptionClass, msg);
}
private String createUrl() {
String baseUrl = baseUrlProvider.getBaseUrl(apiClass);
if (Strings.isNullOrEmpty(baseUrl)) {
throw new RuntimeException(
"base url cannot be null generated by provider "
+ baseUrlProvider.getClass());
}
return baseUrl + prefix;
}
public boolean isSuccessful(HttpResponse> response) {
int status = response.getStatus();
boolean isHttpSucc = status >= 200 && status < 300;
if (!isHttpSucc) return false;
if (succInResponseJSONProperty == null) return true;
if (!RestClientUtils.isResponseJsonContentType(response)) return true;
Object body = response.getBody();
if (body instanceof InputStream) return true;
Map map = Json.unJson("" + body);
String key = succInResponseJSONProperty.key();
Object realValue = map.get(key);
String expectedValue = succInResponseJSONProperty.value();
return expectedValue.equals("" + realValue);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy