org.pipservices3.rpc.connect.HttpConnectionResolver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pip-services3-rpc Show documentation
Show all versions of pip-services3-rpc Show documentation
Networking and communication platform for Pip.Services in Java
The newest version!
package org.pipservices3.rpc.connect;
import org.pipservices3.commons.config.ConfigParams;
import org.pipservices3.commons.config.IConfigurable;
import org.pipservices3.commons.errors.ApplicationException;
import org.pipservices3.commons.errors.ConfigException;
import org.pipservices3.commons.refer.IReferenceable;
import org.pipservices3.commons.refer.IReferences;
import org.pipservices3.components.auth.CredentialParams;
import org.pipservices3.components.auth.CredentialResolver;
import org.pipservices3.components.connect.ConnectionParams;
import org.pipservices3.components.connect.ConnectionResolver;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Helper class to retrieve connections for HTTP-based services abd clients.
*
* In addition to regular functions of ConnectionResolver is able to parse http:// URIs
* and validate connection parameters before returning them.
*
* ### Configuration parameters ###
*
* - connection:
*
* - discovery_key: (optional) a key to retrieve the connection from IDiscovery
*
- ... other connection parameters
*
* - connections: alternative to connection
*
* - [connection params 1]: first connection parameters
*
- ...
*
- [connection params N]: Nth connection parameters
*
- ...
*
*
*
* ### References ###
*
* - *:discovery:*:*:1.0 (optional) IDiscovery services
*
*
* ### Example ###
*
* {@code
* ConfigParams config = ConfigParams.fromTuples(
* "connection.host", "10.1.1.100",
* "connection.port", 8080
* );
*
* HttpConnectionResolver connectionResolver = new HttpConnectionResolver();
* connectionResolver.configure(config);
* connectionResolver.setReferences(references);
*
* ConnectionParams params = connectionResolver.resolve("123");
* }
*
* @see ConnectionParams
* @see ConnectionResolver
*/
public class HttpConnectionResolver implements IReferenceable, IConfigurable {
/**
* The base connection resolver.
*/
protected ConnectionResolver _connectionResolver = new ConnectionResolver();
/**
* The base credential resolver.
*/
protected CredentialResolver _credentialResolver = new CredentialResolver();
/**
* Configures component by passing configuration parameters.
*
* @param config configuration parameters to be set.
*/
public void configure(ConfigParams config) {
_connectionResolver.configure(config);
_credentialResolver.configure(config);
}
/**
* Sets references to dependent components.
*
* @param references references to locate the component dependencies.
*/
public void setReferences(IReferences references) {
_connectionResolver.setReferences(references);
_credentialResolver.setReferences(references);
}
private void validateConnection(String correlationId, ConnectionParams connection, CredentialParams credential) throws ApplicationException {
if (connection == null)
throw new ConfigException(correlationId, "NO_CONNECTION", "HTTP connection is not set");
String uri = connection.getUri();
if (uri != null && uri.length() > 0)
return;
String protocol = connection.getProtocolWithDefault("http");
if (!"http".equals(protocol) && !"https".equals(protocol)) {
throw new ConfigException(correlationId, "WRONG_PROTOCOL", "Protocol is not supported by REST connection")
.withDetails("protocol", protocol);
}
String host = connection.getHost();
if (host == null)
throw new ConfigException(correlationId, "NO_HOST", "Connection host is not set");
int port = connection.getPort();
if (port == 0)
throw new ConfigException(correlationId, "NO_PORT", "Connection port is not set");
// Check HTTPS credentials
if (protocol.equals("https")) {
// Check for credential
if (credential == null) {
throw new ConfigException(
correlationId, "NO_CREDENTIAL", "SSL certificates are not configured for HTTPS protocol");
} else {
// Sometimes when we use https we are on an internal network and do not want to have to deal with security.
// When we need a https connection and we don't want to pass credentials, flag is 'credential.internal_network',
// this flag just has to be present and non null for this functionality to work.
if (credential.getAsNullableString("internal_network") == null) {
if (credential.getAsNullableString("ssl_key_file") == null) {
throw new ConfigException(
correlationId, "NO_SSL_KEY_FILE", "SSL key file is not configured in credentials");
} else if (credential.getAsNullableString("ssl_crt_file") == null) {
throw new ConfigException(
correlationId, "NO_SSL_CRT_FILE", "SSL crt file is not configured in credentials");
}
}
}
}
}
private ConnectionParams composeConnection(List connections, CredentialParams credential) {
var unpackConn = new ConfigParams[connections.size()];
AtomicInteger i = new AtomicInteger();
connections.forEach(
(c) -> {
unpackConn[i.get()] = ConfigParams.fromValue(c);
i.getAndIncrement();
}
);
var connection = ConnectionParams.mergeConfigs(unpackConn);
var uri = connection.getAsString("uri");
if (uri == null || uri.equals("")) {
var protocol = connection.getAsStringWithDefault("protocol", "http");
var host = connection.getAsString("host");
var port = connection.getAsInteger("port");
uri = protocol + "://" + host;
if (port > 0) {
uri += ":" + port;
}
connection.setAsObject("uri", uri);
} else {
var address = URI.create(uri);
var protocol = address.getScheme();
connection.setAsObject("protocol", protocol);
connection.setAsObject("host", address.getHost());
connection.setAsObject("port", address.getPort());
}
if (Objects.equals(connection.getAsString("protocol"), "https") && credential != null) {
if (credential.getAsNullableString("internal_network") == null) {
connection = connection.override(credential);
}
}
return ConnectionParams.fromConfig(connection);
}
/**
* Resolves a single component connection. If connections are configured to be
* retrieved from Discovery service it finds a IDiscovery and resolves the
* connection there.
*
* @param correlationId (optional) transaction id to trace execution through
* call chain.
* @return resolved connection.
* @throws ApplicationException when error occured.
*/
public ConnectionParams resolve(String correlationId) throws ApplicationException {
ConnectionParams connection = _connectionResolver.resolve(correlationId);
CredentialParams credential = _credentialResolver.lookup(correlationId);
this.validateConnection(correlationId, connection, credential);
return this.composeConnection(List.of(connection), credential);
}
/**
* Resolves all component connection. If connections are configured to be
* retrieved from Discovery service it finds a IDiscovery and resolves the
* connection there.
*
* @param correlationId (optional) transaction id to trace execution through
* call chain.
* @return resolved connections.
* @throws ApplicationException when error occured.
*/
public ConnectionParams resolveAll(String correlationId) throws ApplicationException {
var connections = this._connectionResolver.resolveAll(correlationId);
var credential = this._credentialResolver.lookup(correlationId);
connections = connections != null ? connections : new ArrayList<>();
for (var connection : connections)
this.validateConnection(correlationId, connection, credential);
return this.composeConnection(connections, credential);
}
/**
* Registers the given connection in all referenced discovery services. This
* method can be used for dynamic service discovery.
*
* @param correlationId (optional) transaction id to trace execution through
* call chain.
* @throws ApplicationException when error occured.
*/
public void register(String correlationId) throws ApplicationException {
var connection = this._connectionResolver.resolve(correlationId);
var credential = this._credentialResolver.lookup(correlationId);
// Validate connection
this.validateConnection(correlationId, connection, credential);
this._connectionResolver.register(correlationId, connection);
}
}