io.resourcepool.jarpic.client.HttpJsonRpcClient Maven / Gradle / Ivy
package io.resourcepool.jarpic.client;
import io.resourcepool.jarpic.model.Error;
import io.resourcepool.jarpic.model.JsonRpcCallback;
import io.resourcepool.jarpic.model.JsonRpcMultiCallback;
import io.resourcepool.jarpic.model.JsonRpcRequest;
import io.resourcepool.jarpic.model.JsonRpcResponse;
import io.resourcepool.jarpic.parser.RequestMapper;
import io.resourcepool.jarpic.parser.ResponseParser;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
/**
* @author Loïc Ortola on 11/03/2016.
* This implementation proposes a simple Http Json RPC 2.0 Client.
*/
public class HttpJsonRpcClient implements JsonRpcClient {
private OkHttpClient client;
private String endpoint;
private static final MediaType JSON = MediaType.parse("application/json; charset=UTF-8");
/**
* Construct a new HttpJsonRpcClient.
* One Client is made for one endpoint.
*
* @param endpoint the target url endpoint
*/
public HttpJsonRpcClient(String endpoint) {
this.endpoint = endpoint;
this.client = new OkHttpClient();
}
/**
* Construct a new HttpJsonRpcClient.
* One Client is made for one endpoint.
*
* @param endpoint the target url endpoint
* @param client the http client instance
*/
public HttpJsonRpcClient(String endpoint, OkHttpClient client) {
this.endpoint = endpoint;
this.client = client;
}
@SuppressWarnings("unchecked")
@Override
public JsonRpcResponse send(JsonRpcRequest req, Class resultClass) throws IOException {
Request request = buildOkHttpRequest(req);
Response response = client.newCall(request).execute();
if (response.code() >= 300) {
return buildError(req, response);
}
String contentType = response.header("content-type");
if (contentType != null && contentType.contains("application/json")) {
try {
return ResponseParser.parseOne(response.body().byteStream(), resultClass);
} catch (ParseException e) {
return buildError(req, null);
}
} else {
// No JSON response. If 200, we assume it was a notification.
return null;
}
}
@Override
public void send(final JsonRpcRequest req, final Class resultClass, final JsonRpcCallback callback) {
Request request = buildOkHttpRequest(req);
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callback.onFailure(e);
}
@SuppressWarnings("unchecked")
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.code() >= 300) {
callback.onResponse(buildError(req, response));
return;
}
String contentType = response.header("content-type");
if (contentType != null && contentType.contains("application/json")) {
try {
callback.onResponse(ResponseParser.parseOne(response.body().byteStream(), resultClass));
} catch (ParseException e) {
callback.onResponse(buildError(req, null));
}
} else {
// No JSON response. If 200, we assume it was a notification.
callback.onResponse(null);
}
}
});
}
@SuppressWarnings("unchecked")
@Override
public List> send(List reqs, Class resultClass) throws IOException {
Request request = new Request.Builder()
.url(endpoint)
.post(RequestBody.create(JSON, RequestMapper.map(reqs).toString()))
.build();
Response response = client.newCall(request).execute();
if (response.code() >= 300) {
List> responses = new ArrayList>(reqs.size());
for (JsonRpcRequest req : reqs) {
responses.add(buildError(req, response));
}
return responses;
}
String contentType = response.header("content-type");
if (contentType != null && contentType.contains("application/json")) {
return ResponseParser.parseList(response.body().byteStream(), resultClass);
}
// No JSON response. If 200, we assume it was a notification.
return null;
}
@Override
public void send(final List reqs, final Class resultClass, final JsonRpcMultiCallback callback) {
Request request = buildOkHttpRequest(reqs);
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
callback.onFailure(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.code() >= 300) {
List responses = new ArrayList(reqs.size());
for (JsonRpcRequest req : reqs) {
responses.add(buildError(req, response));
}
callback.onResponse(responses);
return;
}
String contentType = response.header("content-type");
if (contentType != null && contentType.contains("application/json")) {
callback.onResponse(ResponseParser.parseList(response.body().byteStream(), resultClass));
return;
}
// No JSON response. If 200, we assume it was a notification.
callback.onResponse(null);
}
});
}
/**
* Build regular json-rpc http request.
*
* @param req the JsonRpcRequest object
* @return the OkHttp request
*/
private Request buildOkHttpRequest(JsonRpcRequest req) {
return new Request.Builder()
.url(endpoint)
.post(RequestBody.create(JSON, RequestMapper.map(req).toString()))
.build();
}
/**
* Build regular json-rpc http request.
*
* @param reqs the list of JsonRpcRequest objects
* @return the OkHttp request
*/
private Request buildOkHttpRequest(List reqs) {
return new Request.Builder()
.url(endpoint)
.post(RequestBody.create(JSON, RequestMapper.map(reqs).toString()))
.build();
}
/**
* Build Error Response depending on statuscode and content.
*
* @param req the JsonRpcRequest object
* @param response the OkHttp response
* @return the OkHttp request
*/
private JsonRpcResponse buildError(JsonRpcRequest req, Response response) {
JsonRpcResponse.Builder b = JsonRpcResponse
.builder()
.id(req.getId());
if (response == null) {
b.error(new Error(-32700, "Parse error", null));
} else if (response.code() == 400) {
b.error(new Error(-32602, "Invalid params", null));
} else if (response.code() == 404) {
b.error(new Error(-32601, "Method not found", null));
} else {
b.error(new Error(-32000, Integer.toString(response.code()) + " - " + response.message(), null));
}
return b.build();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy