
com.venky.swf.integration.api.Call Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swf-db Show documentation
Show all versions of swf-db Show documentation
Succinct Web Framework - Db
The newest version!
package com.venky.swf.integration.api;
import com.venky.core.collections.IgnoreCaseMap;
import com.venky.core.io.ByteArrayInputStream;
import com.venky.core.string.StringUtil;
import com.venky.core.util.Bucket;
import com.venky.core.util.ObjectUtil;
import com.venky.swf.db.Database;
import com.venky.swf.db.annotations.column.ui.mimes.MimeType;
import com.venky.swf.routing.Config;
import com.venky.xml.XMLDocument;
import org.apache.commons.io.input.ReaderInputStream;
import org.json.simple.JSONAware;
import org.json.simple.JSONValue;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Redirect;
import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublisher;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpRequest.Builder;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Flow.Subscriber;
import java.util.zip.GZIPInputStream;
public class Call implements Serializable {
HttpMethod method = HttpMethod.GET;
InputFormat inputFormat = InputFormat.FORM_FIELDS;
String url ;
Map requestHeaders = new IgnoreCaseMap<>();
public Map> getResponseHeaders() {
return responseHeaders;
}
private transient Map> responseHeaders = new IgnoreCaseMap<>();
private transient ByteArrayInputStream responseStream = null;
private transient ByteArrayInputStream errorStream = null;
private transient int status = -1;
public int getStatus(){
return status;
}
T input;
private void checkExpired(){
if (responseStream != null){
throw new RuntimeException("Call already used once. Create another instance of Call Object");
}
}
public Call method(HttpMethod method){
checkExpired();
this.method = method;
return this;
}
public Call inputFormat(InputFormat format){
checkExpired();
this.inputFormat = format;
return this;
}
public Call url(String url){
checkExpired();
if (url != null) {
try {
this.url = new URI(url).normalize().toString();
}catch (Exception ex){
this.url = url;
}
}
return this;
}
public Call url(String baseUrl, String relativeUrl){
checkExpired();
StringBuilder sUrl = new StringBuilder();
if (baseUrl.endsWith("/")) {
sUrl.append(baseUrl.substring(0, baseUrl.length()-1));
}else {
sUrl.append(baseUrl);
}
if (relativeUrl.startsWith("/")){
sUrl.append(relativeUrl);
}else {
sUrl.append("/").append(relativeUrl);
}
return url(sUrl.toString());
}
public Call headers(Map requestHeaders){
checkExpired();
requestHeaders.forEach((k,v)->{
this.requestHeaders.put(k,v);
});
return this;
}
public Call header(String key, String value){
checkExpired();
this.requestHeaders.put(key,value);
return this;
}
public Call input(T input){
checkExpired();
this.input = input;
return this;
}
public Call(){
}
int timeOut = 60000;
public Call timeOut(int timeOut){
checkExpired();
this.timeOut = timeOut;
return this;
}
private Call invoke() {
checkExpired();
if (method == HttpMethod.GET && inputFormat != InputFormat.FORM_FIELDS) {
method = HttpMethod.POST;
//throw new RuntimeException("Cannot call API using Method " + method + " and parameter as " + inputFormat );
}
Builder curlBuilder ;
StringBuilder fakeCurlRequest = new StringBuilder();
try {
StringBuilder sUrl = new StringBuilder();
sUrl.append(url);
String parameterString = inputFormat == InputFormat.JSON ? getParametersAsJSONString(input) :
(inputFormat == InputFormat.XML ? getParametersAsXMLString(input):
(inputFormat == InputFormat.FORM_FIELDS ? getParametersAsFormFields(input) :
""));
if (method == HttpMethod.GET && parameterString.length() > 0) {
if (sUrl.lastIndexOf("?") < 0) {
sUrl.append("?");
}else {
sUrl.append("&");
}
sUrl.append(parameterString);
}
fakeCurlRequest.append("Request ").append(":\n curl ");
curlBuilder = HttpRequest.newBuilder().uri(new URI(sUrl.toString()));
curlBuilder.timeout(Duration.ofMillis(timeOut));
byte[] parameterByteArray = inputFormat == InputFormat.INPUT_STREAM ? getParameterRaw(input) : parameterString.getBytes();
if (method == HttpMethod.GET){
curlBuilder.GET();
}else {
curlBuilder.POST(BodyPublishers.ofByteArray(parameterByteArray));
}
curlBuilder.setHeader("Accept-Encoding", "gzip");
curlBuilder.version(Version.HTTP_2);
for (String k : requestHeaders.keySet()) {
String v = requestHeaders.get(k);
curlBuilder.setHeader(k, v);
fakeCurlRequest.append(" -H '").append(k).append(": ").append(v).append("' ");
}
fakeCurlRequest.append("'").append(sUrl).append("'");
fakeCurlRequest.append(" ");
if (method != HttpMethod.GET) {
if (inputFormat == InputFormat.INPUT_STREAM){
String contentType = requestHeaders.get("content-type");
MimeType mimeType = null;
if (!ObjectUtil.isVoid(contentType)){
mimeType = MimeType.getMimeType(contentType);
}
if (ObjectUtil.isVoid(contentType) || mimeType == null || !mimeType.isText() ){
fakeCurlRequest.append("-d '").append("**Raw binary Stream**").append("'");
}else {
fakeCurlRequest.append("-d '").append(new String(parameterByteArray)).append("'");
}
}else {
fakeCurlRequest.append("-d '").append(parameterString).append("'");
}
}
HttpRequest request = curlBuilder.build();
HttpResponse response = HttpClient.newBuilder().followRedirects(Redirect.ALWAYS).build().send(request, BodyHandlers.ofInputStream());
this.status = response.statusCode();
if (response.statusCode() >= 200 && response.statusCode() < 299 ) {
//2xx is success.!!
InputStream in = isResponseDecompressed() && response.headers().firstValue("Content-Encoding").isPresent() ? new GZIPInputStream(response.body()) : response.body();
responseHeaders.putAll(response.headers().map());
responseStream = new ByteArrayInputStream(StringUtil.readBytes(in));
errorStream= new ByteArrayInputStream(new byte[]{});
this.hasErrors = false;
}else {
InputStream in = isResponseDecompressed() && response.headers().firstValue("Content-Encoding").isPresent() ? new GZIPInputStream(response.body()) : response.body();
errorStream = new ByteArrayInputStream(StringUtil.readBytes(in));
responseStream = new ByteArrayInputStream(new byte[] {});
this.hasErrors = true;
}
if (responseStream.available()> 0){
fakeCurlRequest.append("\n Response:\n");
String contentType = responseHeaders.get("content-type").isEmpty() ? MimeType.TEXT_PLAIN.toString() : responseHeaders.get("content-type").get(0);
if (contentType.equals(MimeType.APPLICATION_JSON.toString()) ||
contentType.contains(MimeType.APPLICATION_XML.toString()) ||
contentType.startsWith("text")){
fakeCurlRequest.append(StringUtil.read(responseStream,true));
}else {
fakeCurlRequest.append("**Raw binary Stream**");
}
}else if (errorStream.available() >0){
fakeCurlRequest.append("\n Error:\n");
fakeCurlRequest.append(StringUtil.read(errorStream,true));
}
Config.instance().getLogger(getClass().getName()).info(fakeCurlRequest.toString());
return this;
} catch (Exception e) {
throw new RuntimeException(e); //Soften the exception.
}
}
boolean hasErrors = false;
public boolean hasErrors(){
if (responseStream == null){
invoke();
}
return this.hasErrors ;
}
@SuppressWarnings("unchecked")
public J getResponseAsJson(){
return (J)JSONValue.parse(new InputStreamReader(getResponseStream()));
}
public XMLDocument getResponseAsXML(){
return XMLDocument.getDocumentFor(getResponseStream());
}
public InputStream getResponseStream() {
if (responseStream == null){
invoke();
}
return responseStream;
}
public InputStream getErrorStream() {
if (responseStream == null){
invoke();
}
return errorStream;
}
public String getError(){
return Database.getJdbcTypeHelper("").getTypeRef(InputStream.class).getTypeConverter().toString(getErrorStream());
}
@SuppressWarnings("unchecked")
private String getParametersAsFormFields(Object p) {
if (p == null) {
return "" ;
}
Map parameters = (Map)p;
StringBuilder q = new StringBuilder();
Bucket pCount = new Bucket();
parameters.forEach((k,v)->{
if (pCount.intValue() > 0) {
q.append("&");
}
String key = (String)k;
String value;
try {
if (v instanceof List){
StringBuilder csv = new StringBuilder();
((List) v).forEach(entry->{
if (csv.length() > 0){
csv.append(",");
}
csv.append(entry);
});
value = URLEncoder.encode(csv.toString(), "utf-8");
}else {
value = URLEncoder.encode(String.valueOf(v), "utf-8");
}
} catch (UnsupportedEncodingException e) {
value = String.valueOf(v);
}
if (q.indexOf(key+"=") < 0) {
q.append(key).append("=").append(value);
}
pCount.increment();
});
return q.toString();
}
private String getParametersAsJSONString(Object p) {
return ((JSONAware)p).toString();
}
private String getParametersAsXMLString(Object p) {
return ((XMLDocument)p).toString();
}
private byte[] getParameterRaw(Object p){
if (p instanceof InputStream){
return StringUtil.readBytes((InputStream)p);
}else if (p instanceof Reader) {
return StringUtil.readBytes(new ReaderInputStream((Reader)p));
}else if (p instanceof byte[]){
return (byte[])p;
}else {
throw new RuntimeException("unknown raw parameter" + p.getClass());
}
}
boolean responseDecompressed = true;
public boolean isResponseDecompressed() {
return responseDecompressed;
}
public void setResponseDecompressed(boolean responseDecompressed) {
this.responseDecompressed = responseDecompressed;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy