use of com.predic8.membrane.core.exchange.Exchange in project service-proxy by membrane.
the class ClusterNotificationInterceptor method handleRequest.
@Override
public Outcome handleRequest(Exchange exc) throws Exception {
log.debug(exc.getOriginalRequestUri());
Matcher m = urlPattern.matcher(exc.getOriginalRequestUri());
if (!m.matches())
return Outcome.CONTINUE;
log.debug("request received: " + m.group(1));
if (validateSignature && !getParams(exc).containsKey("data")) {
exc.setResponse(Response.forbidden().build());
return Outcome.ABORT;
}
Map<String, String> params = validateSignature ? getDecryptedParams(getParams(exc).get("data")) : getParams(exc);
if (isTimedout(params)) {
exc.setResponse(Response.forbidden().build());
return Outcome.ABORT;
}
updateClusterManager(m, params);
exc.setResponse(Response.noContent().build());
return Outcome.RETURN;
}
use of com.predic8.membrane.core.exchange.Exchange in project service-proxy by membrane.
the class HttpClient method call.
public Exchange call(Exchange exc, boolean adjustHostHeader, boolean failOverOn5XX) throws Exception {
if (exc.getDestinations().isEmpty())
throw new IllegalStateException("List of destinations is empty. Please specify at least one destination.");
int counter = 0;
Exception exception = null;
Object trackNodeStatusObj = exc.getProperty(Exchange.TRACK_NODE_STATUS);
boolean trackNodeStatus = trackNodeStatusObj != null && trackNodeStatusObj instanceof Boolean && (Boolean) trackNodeStatusObj;
disableStreamingForRetries(exc);
while (counter < maxRetries) {
Connection con = null;
String dest = getDestination(exc, counter);
HostColonPort target = null;
try {
log.debug("try # " + counter + " to " + dest);
target = init(exc, dest, adjustHostHeader);
if (counter == 0) {
con = exc.getTargetConnection();
if (con != null) {
if (!con.isSame(target.host, target.port)) {
con.close();
con = null;
} else {
con.setKeepAttachedToExchange(true);
}
}
}
SSLProvider sslProvider = getOutboundSSLProvider(exc, target);
if (con == null) {
con = conMgr.getConnection(target.host, target.port, localAddr, sslProvider, connectTimeout, getSNIServerName(exc), proxy, proxySSLContext);
con.setKeepAttachedToExchange(exc.getRequest().isBindTargetConnectionToIncoming());
exc.setTargetConnection(con);
}
if (proxy != null && sslProvider == null)
// if we use a proxy for a plain HTTP (=non-HTTPS) request, attach the proxy credentials.
exc.getRequest().getHeader().setProxyAutorization(proxy.getCredentials());
Response response;
String newProtocol = null;
if (exc.getRequest().isCONNECTRequest()) {
handleConnectRequest(exc, con);
response = Response.ok().build();
newProtocol = "CONNECT";
} else {
response = doCall(exc, con);
if (trackNodeStatus)
exc.setNodeStatusCode(counter, response.getStatusCode());
if (exc.getProperty(Exchange.ALLOW_WEBSOCKET) == Boolean.TRUE && isUpgradeToResponse(response, "websocket")) {
log.debug("Upgrading to WebSocket protocol.");
newProtocol = "WebSocket";
}
if (exc.getProperty(Exchange.ALLOW_TCP) == Boolean.TRUE && isUpgradeToResponse(response, "tcp")) {
log.debug("Upgrading to TCP protocol.");
newProtocol = "TCP";
}
if (exc.getProperty(Exchange.ALLOW_SPDY) == Boolean.TRUE && isUpgradeToResponse(response, "SPDY/3.1")) {
log.debug("Upgrading to SPDY/3.1 protocol.");
newProtocol = "SPDY/3.1";
}
}
if (newProtocol != null) {
setupConnectionForwarding(exc, con, newProtocol, streamPumpStats);
exc.getDestinations().clear();
exc.getDestinations().add(dest);
con.setExchange(exc);
exc.setResponse(response);
return exc;
}
boolean is5XX = 500 <= response.getStatusCode() && response.getStatusCode() < 600;
if (!failOverOn5XX || !is5XX || counter == maxRetries - 1) {
applyKeepAliveHeader(response, con);
exc.getDestinations().clear();
exc.getDestinations().add(dest);
con.setExchange(exc);
response.addObserver(con);
exc.setResponse(response);
return exc;
}
// java.net.SocketException: Software caused connection abort: socket write error
} catch (ConnectException e) {
exception = e;
log.info("Connection to " + (target == null ? dest : target) + " refused.");
} catch (SocketException e) {
if (e.getMessage().contains("Software caused connection abort")) {
log.info("Connection to " + dest + " was aborted externally. Maybe by the server or the OS Membrane is running on.");
} else if (e.getMessage().contains("Connection reset")) {
log.info("Connection to " + dest + " was reset externally. Maybe by the server or the OS Membrane is running on.");
} else {
logException(exc, counter, e);
}
exception = e;
} catch (UnknownHostException e) {
log.warn("Unknown host: " + (target == null ? dest : target));
exception = e;
if (exc.getDestinations().size() < 2) {
// don't retry this host, it's useless. (it's very unlikely that it will work after timeBetweenTriesMs)
break;
}
} catch (EOFWhileReadingFirstLineException e) {
log.debug("Server connection to " + dest + " terminated before line was read. Line so far: " + e.getLineSoFar());
exception = e;
} catch (NoResponseException e) {
throw e;
} catch (Exception e) {
logException(exc, counter, e);
exception = e;
} finally {
if (trackNodeStatus) {
if (exception != null) {
exc.setNodeException(counter, exception);
}
}
}
counter++;
if (exc.getDestinations().size() == 1) {
// as documented above, the sleep timeout is only applied between successive calls to the same destination.
Thread.sleep(timeBetweenTriesMs);
}
}
throw exception;
}
use of com.predic8.membrane.core.exchange.Exchange in project service-proxy by membrane.
the class HttpClient method setupConnectionForwarding.
public static void setupConnectionForwarding(Exchange exc, final Connection con, final String protocol, StreamPump.StreamPumpStats streamPumpStats) throws SocketException {
final HttpServerHandler hsr = (HttpServerHandler) exc.getHandler();
String source = hsr.getSourceSocket().getRemoteSocketAddress().toString();
String dest = con.toString();
final StreamPump a;
final StreamPump b;
if ("WebSocket".equals(protocol)) {
WebSocketStreamPump aTemp = new WebSocketStreamPump(hsr.getSrcIn(), con.out, streamPumpStats, protocol + " " + source + " -> " + dest, exc.getRule(), true, exc);
WebSocketStreamPump bTemp = new WebSocketStreamPump(con.in, hsr.getSrcOut(), streamPumpStats, protocol + " " + source + " <- " + dest, exc.getRule(), false, null);
aTemp.init(bTemp);
bTemp.init(aTemp);
a = aTemp;
b = bTemp;
} else {
a = new StreamPump(hsr.getSrcIn(), con.out, streamPumpStats, protocol + " " + source + " -> " + dest, exc.getRule());
b = new StreamPump(con.in, hsr.getSrcOut(), streamPumpStats, protocol + " " + source + " <- " + dest, exc.getRule());
}
hsr.getSourceSocket().setSoTimeout(0);
exc.addExchangeViewerListener(new AbstractExchangeViewerListener() {
@Override
public void setExchangeFinished() {
String threadName = Thread.currentThread().getName();
new Thread(b, threadName + " " + protocol + " Backward Thread").start();
try {
Thread.currentThread().setName(threadName + " " + protocol + " Onward Thread");
a.run();
} finally {
try {
con.close();
} catch (IOException e) {
log.debug("", e);
}
}
}
});
}
use of com.predic8.membrane.core.exchange.Exchange in project service-proxy by membrane.
the class StatisticCollector method collectFrom.
public void collectFrom(AbstractExchange exc) {
totalCount++;
if (exc.getStatus() == ExchangeState.FAILED) {
errorCount++;
if (!countErrorExchanges)
return;
}
long timeReqSent = exc.getTimeReqSent();
if (timeReqSent == 0)
// this Exchange did not reach the HTTPClientInterceptor
return;
long timeResSent = exc.getTimeResSent();
if (timeResSent == 0)
// this Exchange is not yet completed
return;
goodCount++;
int time = (int) (timeResSent - timeReqSent);
if (time < minTime)
minTime = time;
if (time > maxTime)
maxTime = time;
totalTime += time;
try {
AbstractBody requestBody = exc.getRequest().getBody();
totalBytesSent += requestBody.isRead() ? requestBody.getLength() : 0;
AbstractBody responseBody = exc.getResponse().getBody();
totalBytesReceived += responseBody.isRead() ? responseBody.getLength() : 0;
} catch (IOException e) {
log.warn("", e);
}
}
use of com.predic8.membrane.core.exchange.Exchange in project service-proxy by membrane.
the class HTTPSchemaResolver method resolve.
public InputStream resolve(String url) throws ResourceRetrievalException {
try {
Exchange exc = new Request.Builder().method(Request.METHOD_GET).url(uriFactory, url).header(Header.USER_AGENT, Constants.PRODUCT_NAME + " " + Constants.VERSION).buildExchange();
Response response = getHttpClient().call(exc).getResponse();
response.readBody();
if (response.getStatusCode() != 200) {
ResourceRetrievalException rde = new ResourceRetrievalException(url, response.getStatusCode());
throw rde;
}
return new ByteArrayInputStream(ByteUtil.getByteArrayData(response.getBodyAsStreamDecoded()));
} catch (ResourceRetrievalException e) {
throw e;
} catch (Exception e) {
ResourceRetrievalException rre = new ResourceRetrievalException(url, e);
throw rre;
}
}
Aggregations