package org.sef4j.core.helpers.senders.http;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collection;
import java.util.Map;
import org.sef4j.core.api.EventSender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* EventSender for sending byte[] as http POST requests
*
* <PRE> EventSender(byte[])
* +---------------------+
* sendEvent | - toURL | http POST /url
* -----> | - headers | ---------------------> Http Server
* byte[] | - pooledCon | Content-Type=contentType (Elasticsearch, InfluxDB, MongoDB, others ...)
* +---------------------+ .
* "byte[]..."
* </PRE>
*/
public class HttpPostBytesSender implements EventSender<byte[]> {
private static final Logger LOG = LoggerFactory.getLogger(HttpPostBytesSender.class);
public static final String CONTENT_TYPE_JSON = "application/json";
private String displayName;
private URL toURL;
private String contentType;
private Map<String,String> headers;
// ?? may keep open connection with java.net.HttpURLConnection
private boolean closeImmediateCon = true;
private HttpURLConnection pooledCon;
// ------------------------------------------------------------------------
public HttpPostBytesSender(String displayName, URL toURL, String contentType, Map<String,String> headers) {
this.displayName = displayName;
this.toURL = toURL;
this.contentType = contentType;
this.headers = headers;
}
// ------------------------------------------------------------------------
public void sendEvent(byte[] data) {
HttpURLConnection con = openHttpURLConnection();
try {
doSendContent(con, data);
} finally {
releaseHttpURLConnection(con);
}
}
public void sendEvents(Collection<byte[]> datas) {
HttpURLConnection con = openHttpURLConnection();
try {
for(byte[] data : datas) {
doSendContent(con, data);
}
} finally {
releaseHttpURLConnection(con);
}
}
protected void doSendContent(HttpURLConnection con, byte[] data) {
try {
con.setDoOutput(true);
con.setRequestMethod("POST");
if (contentType != null) {
con.setRequestProperty("Content-Type", contentType);
}
if (headers != null) {
for(Map.Entry<String,String> e : headers.entrySet()) {
con.setRequestProperty(e.getKey(), e.getValue());
}
}
OutputStream conOutput = con.getOutputStream();
conOutput.write(data);
conOutput.close();
// con.setReadTimeout(10000);
int responseCode = con.getResponseCode();
if (responseCode == 200) {
// OK!
} else {
String responseMsg = con.getResponseMessage();
throw new RuntimeException("Failed to POST json to '" + displayName + "', response code:" + responseCode + " msg:" + responseMsg);
}
} catch(IOException ex) {
throw new RuntimeException("Failed to POST json to '" + displayName + "', ex:" + ex.getMessage());
}
}
protected HttpURLConnection openHttpURLConnection() {
HttpURLConnection con;
if (pooledCon != null) {
con = pooledCon;
} else {
try {
con = (HttpURLConnection) toURL.openConnection();
pooledCon = con;
} catch(IOException ex) {
// do not display real seriesURL...it contains user/password!
LOG.warn("Failed to connect to '" + displayName + "', ex:" + ex.getMessage() + " ... rethrow");
throw new RuntimeException("Failed to connect to '" + displayName +"'", ex);
}
}
return con;
}
protected void releaseHttpURLConnection(HttpURLConnection con) {
if (con != null) {
if (closeImmediateCon) {
pooledCon = null;
try {
con.disconnect();
} catch(Exception ex) {
// ignore, no rethrow!
}
}
}
}
}