Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #2431 - add support for headers in RemoteTermServiceProvider #2435

Merged
merged 5 commits into from
May 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/src/pages/guides/FHIRServerUsersGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -1972,6 +1972,9 @@ This section contains reference information about each of the configuration prop
|`fhirServer/term/remoteTermServiceProviders/hostnameVerificationEnabled`|boolean|Indicates whether hostname verification should be performed when using SSL transport|
|`fhirServer/term/remoteTermServiceProviders/basicAuth/username`|string|The basic authentication username for this remote term service provider|
|`fhirServer/term/remoteTermServiceProviders/basicAuth/password`|string|The basic authentication password for this remote term service provider|
|`fhirServer/term/remoteTermServiceProviders/headers`|array of objects|The `headers` element is an array of objects|
|`fhirServer/term/remoteTermServiceProviders/headers/name`|string|The HTTP header name that will be added to requests by this remote term service provider|
|`fhirServer/term/remoteTermServiceProviders/headers/value`|string|The HTTP header value that will be added to requests by this remote term service provider|
|`fhirServer/term/remoteTermServiceProviders/httpTimeout`|integer|The HTTP read timeout for this remote term service provider (in milliseconds)|
|`fhirServer/term/remoteTermServiceProviders/supports`|array of objects|The `supports` element is an array of objects|
|`fhirServer/term/remoteTermServiceProviders/supports/system`|string|The system URI supported by this remote term service provider|
Expand Down Expand Up @@ -2246,6 +2249,7 @@ must restart the server for that change to take effect.
|`fhirServer/term/remoteTermServiceProviders/trustStore`|N|N|
|`fhirServer/term/remoteTermServiceProviders/hostnameVerificationEnabled`|N|N|
|`fhirServer/term/remoteTermServiceProviders/basicAuth`|N|N|
|`fhirServer/term/remoteTermServiceProviders/headers`|N|N|
|`fhirServer/term/remoteTermServiceProviders/httpTimeout`|N|N|
|`fhirServer/term/remoteTermServiceProviders/supports`|N|N|
|`fhirServer/resources/open`|Y|Y|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider;
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider.Configuration;
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider.Configuration.BasicAuth;
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider.Configuration.Header;
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider.Configuration.Supports;
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider.Configuration.TrustStore;
import com.ibm.fhir.term.util.CodeSystemSupport;
Expand All @@ -47,11 +48,19 @@ public void testCreateCodeSystem() throws Exception {
CodeSystem codeSystem = TestUtil.readLocalResource("CodeSystem-test.json");
Entity<CodeSystem> entity = Entity.entity(codeSystem, FHIRMediaType.APPLICATION_FHIR_JSON);

Response response = target.path("CodeSystem").path("test").request().put(entity);
Response response = target.path("CodeSystem").path("test")
.request()
.header("X-FHIR-TENANT-ID", "tenant1")
.header("X-FHIR-DSID", "profile")
.put(entity);
int status = response.getStatus();
assertTrue(status == Response.Status.CREATED.getStatusCode() || status == Response.Status.OK.getStatusCode());

response = target.path("CodeSystem").path("test").request(FHIRMediaType.APPLICATION_FHIR_JSON).get();
response = target.path("CodeSystem").path("test")
.request(FHIRMediaType.APPLICATION_FHIR_JSON)
.header("X-FHIR-TENANT-ID", "tenant1")
.header("X-FHIR-DSID", "profile")
.get();
assertResponse(response, Response.Status.OK.getStatusCode());

CodeSystem responseCodeSystem = response.readEntity(CodeSystem.class);
Expand All @@ -60,7 +69,7 @@ public void testCreateCodeSystem() throws Exception {
this.codeSystem = responseCodeSystem;
}

@Test
@Test(dependsOnMethods = { "testCreateCodeSystem" })
public void testCreateRemoteTermServiceProvider() {
Configuration configuration = Configuration.builder()
.base(getRestBaseURL())
Expand All @@ -72,6 +81,14 @@ public void testCreateRemoteTermServiceProvider() {
.username(getFhirUser())
.password(getFhirPassword())
.build())
.headers(Header.builder()
.name("X-FHIR-TENANT-ID")
.value("tenant1")
.build(),
Header.builder()
.name("X-FHIR-DSID")
.value("profile")
.build())
.supports(Supports.builder()
.system(codeSystem.getUrl().getValue())
.version(codeSystem.getVersion().getValue())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider;
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider.Configuration;
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider.Configuration.BasicAuth;
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider.Configuration.Header;
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider.Configuration.Supports;
import com.ibm.fhir.term.remote.provider.RemoteTermServiceProvider.Configuration.TrustStore;
import com.ibm.fhir.term.service.FHIRTermService;
Expand Down Expand Up @@ -330,6 +331,17 @@ private void configureTermServiceCapabilities(PropertyGroup fhirConfig) throws E
.build());
}

Object[] headersArray = remoteTermServiceProviderPropertyGroup.getArrayProperty("headers");
JohnTimm marked this conversation as resolved.
Show resolved Hide resolved
if (headersArray != null) {
for (Object headerObject : headersArray) {
PropertyGroup headerPropertyGroup = (PropertyGroup) headerObject;
builder.headers(Header.builder()
.name(headerPropertyGroup.getStringProperty("name"))
.value(headerPropertyGroup.getStringProperty("value"))
.build());
}
}

builder.httpTimeout(remoteTermServiceProviderPropertyGroup.getIntProperty("httpTimeout", Configuration.DEFAULT_HTTP_TIMEOUT));

Object[] supportsArray = remoteTermServiceProviderPropertyGroup.getArrayProperty("supports");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

Expand Down Expand Up @@ -96,11 +98,13 @@ public class RemoteTermServiceProvider extends AbstractTermServiceProvider {

private final Configuration configuration;
private final String base;
private final MultivaluedMap<String, Object> headersMap;
private Client client;

public RemoteTermServiceProvider(Configuration configuration) {
this.configuration = Objects.requireNonNull(configuration, "configuration");
this.base = configuration.getBase();
headersMap = buildHeadersMap(configuration.getHeaders());
try {
log.info("Creating client...");

Expand Down Expand Up @@ -185,11 +189,13 @@ public Concept getConcept(CodeSystem codeSystem, Code code) {
.queryParam("version", codeSystem.getVersion().getValue())
.queryParam("code", code.getValue())
.request(FHIRMediaType.APPLICATION_FHIR_JSON)
.headers(headersMap)
.get() :
target.path(CODE_SYSTEM_LOOKUP)
.queryParam("system", codeSystem.getUrl().getValue())
.queryParam("code", code.getValue())
.request(FHIRMediaType.APPLICATION_FHIR_JSON)
.headers(headersMap)
.get();

log(GET, uri(CODE_SYSTEM_LOOKUP), response.getStatus(), elapsed(start));
Expand Down Expand Up @@ -240,6 +246,7 @@ public <R> Set<R> getConcepts(CodeSystem codeSystem, List<Filter> filters, Funct

response = target.path(VALUE_SET_EXPAND)
.request(FHIRMediaType.APPLICATION_FHIR_JSON)
.headers(headersMap)
.post(Entity.entity(parameters, FHIRMediaType.APPLICATION_FHIR_JSON));

log(POST, uri(VALUE_SET_EXPAND), response.getStatus(), elapsed(start));
Expand Down Expand Up @@ -294,11 +301,13 @@ public boolean hasConcept(CodeSystem codeSystem, Code code) {
.queryParam("version", codeSystem.getVersion().getValue())
.queryParam("code", code.getValue())
.request(FHIRMediaType.APPLICATION_FHIR_JSON)
.headers(headersMap)
.get() :
target.path(CODE_SYSTEM_VALIDATE_CODE)
.queryParam("url", codeSystem.getUrl().getValue())
.queryParam("code", code.getValue())
.request(FHIRMediaType.APPLICATION_FHIR_JSON)
.headers(headersMap)
.get();

log(GET, uri(CODE_SYSTEM_VALIDATE_CODE), response.getStatus(), elapsed(start));
Expand Down Expand Up @@ -359,12 +368,14 @@ public boolean subsumes(CodeSystem codeSystem, Code codeA, Code codeB) {
.queryParam("codeA", codeA.getValue())
.queryParam("codeB", codeB.getValue())
.request(FHIRMediaType.APPLICATION_FHIR_JSON)
.headers(headersMap)
.get() :
target.path(CODE_SYSTEM_SUBSUMES)
.queryParam("system", codeSystem.getUrl().getValue())
.queryParam("codeA", codeA.getValue())
.queryParam("codeB", codeB.getValue())
.request(FHIRMediaType.APPLICATION_FHIR_JSON)
.headers(headersMap)
.get();

log(GET, uri(CODE_SYSTEM_SUBSUMES), response.getStatus(), elapsed(start));
Expand All @@ -386,6 +397,14 @@ public boolean subsumes(CodeSystem codeSystem, Code codeA, Code codeB) {
}
}

private MultivaluedMap<String, Object> buildHeadersMap(List<Configuration.Header> headers) {
MultivaluedMap<String, Object> headersMap = new MultivaluedHashMap<>();
for (Configuration.Header header : headers) {
headersMap.putSingle(header.getName(), header.getValue());
}
return headersMap;
}

private double elapsed(long start) {
return (System.currentTimeMillis() - start) / 1000.0;
}
Expand Down Expand Up @@ -594,6 +613,7 @@ public static class Configuration {
private final TrustStore trustStore;
private final boolean hostnameVerificationEnabled;
private final BasicAuth basicAuth;
private final List<Header> headers;
private final int httpTimeout;
private final List<Supports> supports;

Expand All @@ -602,6 +622,7 @@ private Configuration(Builder builder) {
trustStore = builder.trustStore;
hostnameVerificationEnabled = builder.hostnameVerificationEnabled;
basicAuth = builder.basicAuth;
headers = Collections.unmodifiableList(builder.headers);
httpTimeout = builder.httpTimeout;
supports = Collections.unmodifiableList(builder.supports);
}
Expand All @@ -622,6 +643,10 @@ public BasicAuth getBasicAuth() {
return basicAuth;
}

public List<Header> getHeaders() {
return headers;
}

public int getHttpTimeout() {
return httpTimeout;
}
Expand All @@ -646,13 +671,14 @@ public boolean equals(Object obj) {
Objects.equals(trustStore, other.trustStore) &&
Objects.equals(hostnameVerificationEnabled, other.hostnameVerificationEnabled) &&
Objects.equals(basicAuth, other.basicAuth) &&
Objects.equals(headers, other.headers) &&
Objects.equals(httpTimeout, other.httpTimeout) &&
Objects.equals(supports, other.supports);
}

@Override
public int hashCode() {
return Objects.hash(base, trustStore, hostnameVerificationEnabled, basicAuth, httpTimeout, supports);
return Objects.hash(base, trustStore, hostnameVerificationEnabled, basicAuth, headers, httpTimeout, supports);
}

public Builder toBuilder() {
Expand All @@ -668,6 +694,7 @@ public static class Builder {
private TrustStore trustStore;
private boolean hostnameVerificationEnabled = DEFAULT_HOSTNAME_VERIFICATION_ENABLED;
private BasicAuth basicAuth;
private List<Header> headers = new ArrayList<>();
private int httpTimeout = DEFAULT_HTTP_TIMEOUT;
private List<Supports> supports = new ArrayList<>();

Expand All @@ -693,6 +720,18 @@ public Builder basicAuth(BasicAuth basicAuth) {
return this;
}

public Builder headers(Header... headers) {
for (Header value : headers) {
this.headers.add(value);
}
return this;
}

public Builder headers(Collection<Header> headers) {
this.headers = new ArrayList<>(headers);
return this;
}

public Builder httpTimeout(int httpTimeout) {
this.httpTimeout = httpTimeout;
return this;
Expand All @@ -719,6 +758,7 @@ protected Builder from(Configuration configuration) {
trustStore = configuration.trustStore;
hostnameVerificationEnabled = configuration.hostnameVerificationEnabled;
basicAuth = configuration.basicAuth;
headers = configuration.headers;
httpTimeout = configuration.httpTimeout;
supports.addAll(configuration.supports);
return this;
Expand Down Expand Up @@ -895,6 +935,83 @@ protected Builder from(BasicAuth basicAuth) {
}
}

/**
* A class that represents the HTTP header(s) supported by a remote term service provider
*/
public static class Header {
private final String name;
private final Object value;

public Header(Builder builder) {
name = Objects.requireNonNull(builder.name, "name");
value = Objects.requireNonNull(builder.value, "value");
}

public String getName() {
return name;
}

public Object getValue() {
return value;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Header other = (Header) obj;
return Objects.equals(name, other.name) &&
Objects.equals(value, other.value);
}

@Override
public int hashCode() {
return Objects.hash(name, value);
}

public Builder toBuilder() {
return new Builder().from(this);
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private String name;
private Object value;

private Builder() { }

public Builder name(String name) {
this.name = name;
return this;
}

public Builder value(Object value) {
this.value = value;
return this;
}

public Header build() {
return new Header(this);
}

protected Builder from(Header header) {
name = header.name;
value = header.value;
return this;
}
}
}

/**
* A class that represents the code system(s) supported by a remote term service provider
*/
Expand Down