add explicit control over the User-Agent header, and make sure headers flow through properly to all calls

This commit is contained in:
Grahame Grieve 2021-10-23 05:56:36 +11:00
parent c69413e9e0
commit 5b9736dbff
36 changed files with 227 additions and 89 deletions

View File

@ -29,7 +29,7 @@ public class VSACImporter extends OIDBasedValueSetImporter {
CSVReader csv = new CSVReader(new FileInputStream(source));
csv.readHeaders();
FHIRToolingClient fhirToolingClient = new FHIRToolingClient("https://cts.nlm.nih.gov/fhir");
FHIRToolingClient fhirToolingClient = new FHIRToolingClient("https://cts.nlm.nih.gov/fhir", "fhir/vsac");
fhirToolingClient.setUsername(username);
fhirToolingClient.setPassword(password);

View File

@ -39,42 +39,42 @@ import java.net.URISyntaxException;
public class TerminologyClientFactory {
public static TerminologyClient makeClient(String url, FhirPublication v) throws URISyntaxException {
public static TerminologyClient makeClient(String url, String userAgent, FhirPublication v) throws URISyntaxException {
if (v == null)
return new TerminologyClientR5(checkEndsWith("/r4", url));
return new TerminologyClientR5(checkEndsWith("/r4", url), userAgent);
switch (v) {
case DSTU2016May:
return new TerminologyClientR3(checkEndsWith("/r3", url)); // r3 is the least worst match
return new TerminologyClientR3(checkEndsWith("/r3", url), userAgent); // r3 is the least worst match
case DSTU1:
throw new Error("The version " + v + " is not currently supported");
case DSTU2:
return new TerminologyClientR2(checkEndsWith("/r2", url));
return new TerminologyClientR2(checkEndsWith("/r2", url), userAgent);
case R4:
return new TerminologyClientR5(checkEndsWith("/r4", url));
return new TerminologyClientR5(checkEndsWith("/r4", url), userAgent);
case R5:
return new TerminologyClientR5(checkEndsWith("/r4", url)); // r4 for now, since the terminology is currently the same
return new TerminologyClientR5(checkEndsWith("/r4", url), userAgent); // r4 for now, since the terminology is currently the same
case STU3:
return new TerminologyClientR3(checkEndsWith("/r3", url));
return new TerminologyClientR3(checkEndsWith("/r3", url), userAgent);
default:
throw new Error("The version " + v + " is not currently supported");
}
}
public static TerminologyClient makeClient(String url, String v) throws URISyntaxException {
public static TerminologyClient makeClient(String url, String userAgent, String v) throws URISyntaxException {
if (v == null)
return new TerminologyClientR5(checkEndsWith("/r4", url));
return new TerminologyClientR5(checkEndsWith("/r4", url), userAgent);
v = VersionUtilities.getMajMin(v);
switch (v) {
case "1.0":
return new TerminologyClientR2(checkEndsWith("/r2", url));
return new TerminologyClientR2(checkEndsWith("/r2", url), userAgent);
case "1.4":
return new TerminologyClientR3(checkEndsWith("/r3", url)); // r3 is the least worst match
return new TerminologyClientR3(checkEndsWith("/r3", url), userAgent); // r3 is the least worst match
case "3.0":
return new TerminologyClientR3(checkEndsWith("/r3", url));
return new TerminologyClientR3(checkEndsWith("/r3", url), userAgent);
case "4.0":
return new TerminologyClientR4(checkEndsWith("/r4", url));
return new TerminologyClientR4(checkEndsWith("/r4", url), userAgent);
case "4.5":
return new TerminologyClientR5(checkEndsWith("/r4", url)); // r4 for now, since the terminology is currently the same
return new TerminologyClientR5(checkEndsWith("/r4", url), userAgent); // r4 for now, since the terminology is currently the same
default:
throw new Error("The version " + v + " is not currently supported");
}

View File

@ -48,8 +48,8 @@ public class TerminologyClientR2 implements TerminologyClient {
private final FHIRToolingClient client; // todo: use the R2 client
public TerminologyClientR2(String address) throws URISyntaxException {
client = new FHIRToolingClient(address);
public TerminologyClientR2(String address, String userAgent) throws URISyntaxException {
client = new FHIRToolingClient(address, userAgent);
}
@Override
@ -153,4 +153,10 @@ public class TerminologyClientR2 implements TerminologyClient {
public TerminologyClient setClientHeaders(ClientHeaders clientHeaders) {
return null;
}
@Override
public TerminologyClient setUserAgent(String userAgent) {
client.setUserAgent(userAgent);
return this;
}
}

View File

@ -49,13 +49,13 @@ public class TerminologyClientR3 implements TerminologyClient {
private final FHIRToolingClient client; // todo: use the R2 client
private ClientHeaders clientHeaders;
public TerminologyClientR3(String address) throws URISyntaxException {
client = new FHIRToolingClient(address);
public TerminologyClientR3(String address, String userAgent) throws URISyntaxException {
client = new FHIRToolingClient(address, userAgent);
setClientHeaders(new ClientHeaders());
}
public TerminologyClientR3(String address, ClientHeaders clientHeaders) throws URISyntaxException {
client = new FHIRToolingClient(address);
public TerminologyClientR3(String address, String userAgent, ClientHeaders clientHeaders) throws URISyntaxException {
client = new FHIRToolingClient(address, userAgent);
setClientHeaders(clientHeaders);
}
@ -162,4 +162,10 @@ public class TerminologyClientR3 implements TerminologyClient {
this.client.setClientHeaders(this.clientHeaders.headers());
return this;
}
@Override
public TerminologyClient setUserAgent(String userAgent) {
client.setUserAgent(userAgent);
return this;
}
}

View File

@ -49,13 +49,13 @@ public class TerminologyClientR4 implements TerminologyClient {
private final FHIRToolingClient client; // todo: use the R2 client
private ClientHeaders clientHeaders;
public TerminologyClientR4(String address) throws URISyntaxException {
this.client = new FHIRToolingClient(address);
public TerminologyClientR4(String address, String userAgent) throws URISyntaxException {
this.client = new FHIRToolingClient(address, userAgent);
setClientHeaders(new ClientHeaders());
}
public TerminologyClientR4(String address, ClientHeaders clientHeaders) throws URISyntaxException {
this.client = new FHIRToolingClient(address);
public TerminologyClientR4(String address, String userAgent, ClientHeaders clientHeaders) throws URISyntaxException {
this.client = new FHIRToolingClient(address, userAgent);
setClientHeaders(clientHeaders);
}
@ -162,4 +162,10 @@ public class TerminologyClientR4 implements TerminologyClient {
this.client.setClientHeaders(this.clientHeaders.headers());
return this;
}
@Override
public TerminologyClient setUserAgent(String userAgent) {
client.setUserAgent(userAgent);
return this;
}
}

View File

@ -46,13 +46,13 @@ public class TerminologyClientR5 implements TerminologyClient {
private final FHIRToolingClient client;
private ClientHeaders clientHeaders;
public TerminologyClientR5(String address) throws URISyntaxException {
this.client = new FHIRToolingClient(address);
public TerminologyClientR5(String address, String userAgent) throws URISyntaxException {
this.client = new FHIRToolingClient(address, userAgent);
setClientHeaders(new ClientHeaders());
}
public TerminologyClientR5(String address, ClientHeaders clientHeaders) throws URISyntaxException {
this.client = new FHIRToolingClient(address);
public TerminologyClientR5(String address, String userAgent, ClientHeaders clientHeaders) throws URISyntaxException {
this.client = new FHIRToolingClient(address, userAgent);
setClientHeaders(clientHeaders);
}
@ -148,4 +148,10 @@ public class TerminologyClientR5 implements TerminologyClient {
this.client.setClientHeaders(this.clientHeaders.headers());
return this;
}
@Override
public TerminologyClient setUserAgent(String userAgent) {
client.setUserAgent(userAgent);
return this;
}
}

View File

@ -117,7 +117,7 @@ public class BatchLoader {
private static int loadBundle(String server, Bundle b, int size, int start, int end) throws URISyntaxException {
System.out.println("Post to "+server+". size = "+Integer.toString(size)+", start = "+Integer.toString(start)+", total = "+Integer.toString(b.getEntry().size()));
FHIRToolingClient client = new FHIRToolingClient(server);
FHIRToolingClient client = new FHIRToolingClient(server, "fhir/batch-loader");
int c = start;
if (end == -1)
end = b.getEntry().size();

View File

@ -111,8 +111,8 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
return res;
}
public void connectToTSServer(String url) throws URISyntaxException {
txServer = new FHIRToolingClient(url);
public void connectToTSServer(String url, String userAgent) throws URISyntaxException {
txServer = new FHIRToolingClient(url, userAgent);
}
private void loadFromFile(InputStream stream, String name) throws IOException, FHIRException {

View File

@ -105,6 +105,7 @@ public class ClientUtils {
private String password;
private ToolingClientLogger logger;
private int retryCount;
private String userAgent;
public HttpHost getProxy() {
return proxy;
@ -258,7 +259,9 @@ public class ClientUtils {
* @param request
*/
protected void configureFhirRequest(HttpRequest request, String format, List<Header> headers) {
request.addHeader("User-Agent", "Java FHIR Client for FHIR");
if (!Utilities.noString(userAgent)) {
request.addHeader("User-Agent", userAgent);
}
if (format != null) {
request.addHeader("Accept",format);
@ -663,5 +666,13 @@ public class ClientUtils {
this.retryCount = retryCount;
}
public String getUserAgent() {
return userAgent;
}
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
}

View File

@ -100,14 +100,16 @@ public class FHIRToolingClient {
private ClientUtils utils = new ClientUtils();
//Pass enpoint for client - URI
public FHIRToolingClient(String baseServiceUrl) throws URISyntaxException {
public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException {
preferredResourceFormat = ResourceFormat.RESOURCE_XML;
utils.setUserAgent(userAgent);
detectProxy();
initialize(baseServiceUrl);
}
public FHIRToolingClient(String baseServiceUrl, String username, String password) throws URISyntaxException {
public FHIRToolingClient(String baseServiceUrl, String userAgent, String username, String password) throws URISyntaxException {
preferredResourceFormat = ResourceFormat.RESOURCE_XML;
utils.setUserAgent(userAgent);
utils.setUsername(username);
utils.setPassword(password);
detectProxy();
@ -857,5 +859,11 @@ public class FHIRToolingClient {
utils.setRetryCount(retryCount);
}
public String getUserAgent() {
return utils.getUserAgent();
}
public void setUserAgent(String userAgent) {
utils.setUserAgent(userAgent);
}
}

View File

@ -218,8 +218,8 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
loadBytes(name, stream);
}
public String connectToTSServer(String url) throws URISyntaxException {
txServer = new FHIRToolingClient(url);
public String connectToTSServer(String url, String userAgent) throws URISyntaxException {
txServer = new FHIRToolingClient(url, userAgent);
txServer.setTimeout(30000);
return txServer.getCapabilitiesStatementQuick().getSoftware().getVersion();
}

View File

@ -80,7 +80,7 @@ public class BatchLoader {
private static void LoadDirectory(String server, String folder, int size) throws IOException, Exception {
System.out.print("Connecting to "+server+".. ");
FHIRToolingClient client = new FHIRToolingClient(server);
FHIRToolingClient client = new FHIRToolingClient(server, "fhir/batch-loader");
System.out.println("Done");
IniFile ini = new IniFile(Utilities.path(folder, "batch-load-progress.ini"));

View File

@ -66,10 +66,12 @@ public class FHIRToolingClient {
private ArrayList<Header> headers = new ArrayList<>();
private String username;
private String password;
private String userAgent;
//Pass endpoint for client - URI
public FHIRToolingClient(String baseServiceUrl) throws URISyntaxException {
public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException {
preferredResourceFormat = ResourceFormat.RESOURCE_XML;
this.userAgent = userAgent;
initialize(baseServiceUrl);
}
@ -280,7 +282,7 @@ public class FHIRToolingClient {
if (client.getLogger() != null) {
client.getLogger().logRequest("POST", url.toString(), null, body);
}
result = client.issuePostRequest(url, body, getPreferredResourceFormat(),
result = client.issuePostRequest(url, body, getPreferredResourceFormat(), generateHeaders(),
"POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
} else {
if (client.getLogger() != null) {
@ -555,6 +557,9 @@ public class FHIRToolingClient {
if(this.headers != null) {
this.headers.forEach(header -> builder.add(header.toString()));
}
if (!Utilities.noString(userAgent)) {
builder.add("User-Agent: "+userAgent);
}
return builder.build();
}
@ -567,5 +572,13 @@ public class FHIRToolingClient {
String base64usernamePassword = Base64.getEncoder().encodeToString(usernamePassword.getBytes());
return new Header("Authorization", "Basic " + base64usernamePassword);
}
public String getUserAgent() {
return userAgent;
}
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
}

View File

@ -63,7 +63,7 @@ public class FhirRequestBuilder {
* @param headers Any additional {@link Headers} to add to the request.
*/
protected static void formatHeaders(Request.Builder request, String format, Headers headers) {
addDefaultHeaders(request);
addDefaultHeaders(request, headers);
if (format != null) addResourceFormatHeaders(request, format);
if (headers != null) addHeaders(request, headers);
}
@ -75,8 +75,10 @@ public class FhirRequestBuilder {
*
* @param request {@link Request.Builder} to add default headers to.
*/
protected static void addDefaultHeaders(Request.Builder request) {
request.addHeader("User-Agent", "hapi-fhir-tooling-client");
protected static void addDefaultHeaders(Request.Builder request, Headers headers) {
if (headers == null || !headers.names().contains("User-Agent")) {
request.addHeader("User-Agent", "hapi-fhir-tooling-client");
}
request.addHeader("Accept-Charset", DEFAULT_CHARSET);
}
@ -203,7 +205,7 @@ public class FhirRequestBuilder {
}
public <T extends Resource> ResourceRequest<T> execute() throws IOException {
formatHeaders(httpRequest, resourceFormat, null);
formatHeaders(httpRequest, resourceFormat, headers);
Response response = getHttpClient().newCall(httpRequest.build()).execute();
T resource = unmarshalReference(response, resourceFormat);
return new ResourceRequest<T>(resource, response.code(), getLocationHeader(response.headers()));

View File

@ -46,8 +46,8 @@ public class TerminologyClientR4 implements TerminologyClient {
private FHIRToolingClient client;
public TerminologyClientR4(String address) throws URISyntaxException {
client = new FHIRToolingClient(address);
public TerminologyClientR4(String address, String userAgent) throws URISyntaxException {
client = new FHIRToolingClient(address, userAgent);
}
@Override

View File

@ -80,7 +80,7 @@ public class BatchLoader {
private static void LoadDirectory(String server, String folder, int size) throws IOException, Exception {
System.out.print("Connecting to "+server+".. ");
FHIRToolingClient client = new FHIRToolingClient(server);
FHIRToolingClient client = new FHIRToolingClient(server, "fhir/batch-loader");
System.out.println("Done");
IniFile ini = new IniFile(Utilities.path(folder, "batch-load-progress.ini"));

View File

@ -63,10 +63,12 @@ public class FHIRToolingClient {
private ArrayList<Header> headers = new ArrayList<>();
private String username;
private String password;
private String userAgent;
//Pass endpoint for client - URI
public FHIRToolingClient(String baseServiceUrl) throws URISyntaxException {
public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException {
preferredResourceFormat = ResourceFormat.RESOURCE_XML;
this.userAgent = userAgent;
initialize(baseServiceUrl);
}
@ -277,7 +279,7 @@ public class FHIRToolingClient {
if (client.getLogger() != null) {
client.getLogger().logRequest("POST", url.toString(), null, body);
}
result = client.issuePostRequest(url, body, getPreferredResourceFormat(),
result = client.issuePostRequest(url, body, getPreferredResourceFormat(), generateHeaders(),
"POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
} else {
if (client.getLogger() != null) {
@ -528,6 +530,9 @@ public class FHIRToolingClient {
if(this.headers != null) {
this.headers.forEach(header -> builder.add(header.toString()));
}
if (!Utilities.noString(userAgent)) {
builder.add("User-Agent: "+userAgent);
}
return builder.build();
}
@ -540,5 +545,13 @@ public class FHIRToolingClient {
String base64usernamePassword = Base64.getEncoder().encodeToString(usernamePassword.getBytes());
return new Header("Authorization", "Basic " + base64usernamePassword);
}
public String getUserAgent() {
return userAgent;
}
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
}

View File

@ -63,7 +63,7 @@ public class FhirRequestBuilder {
* @param headers Any additional {@link Headers} to add to the request.
*/
protected static void formatHeaders(Request.Builder request, String format, Headers headers) {
addDefaultHeaders(request);
addDefaultHeaders(request, headers);
if (format != null) addResourceFormatHeaders(request, format);
if (headers != null) addHeaders(request, headers);
}
@ -75,8 +75,10 @@ public class FhirRequestBuilder {
*
* @param request {@link Request.Builder} to add default headers to.
*/
protected static void addDefaultHeaders(Request.Builder request) {
request.addHeader("User-Agent", "hapi-fhir-tooling-client");
protected static void addDefaultHeaders(Request.Builder request, Headers headers) {
if (headers == null || !headers.names().contains("User-Agent")) {
request.addHeader("User-Agent", "hapi-fhir-tooling-client");
}
request.addHeader("Accept-Charset", DEFAULT_CHARSET);
}
@ -203,7 +205,7 @@ public class FhirRequestBuilder {
}
public <T extends Resource> ResourceRequest<T> execute() throws IOException {
formatHeaders(httpRequest, resourceFormat, null);
formatHeaders(httpRequest, resourceFormat, headers);
Response response = getHttpClient().newCall(httpRequest.build()).execute();
T resource = unmarshalReference(response, resourceFormat);
return new ResourceRequest<T>(resource, response.code(), getLocationHeader(response.headers()));

View File

@ -394,7 +394,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
private void compareExpansions(ValueSet left, ValueSet right, ValueSetComparison res) {
ValueSet expL = left.hasExpansion() ? left : expand(left, res, "left", session.getContextLeft());
ValueSet expR = left.hasExpansion() ? left : expand(right, res, "right", session.getContextRight());
ValueSet expR = right.hasExpansion() ? right : expand(right, res, "right", session.getContextRight());
if (expL != null && expR != null) {
// ignore the parameters for now
compareConcepts(expL.getExpansion().getContains(), expR.getExpansion().getContains(), res.forceExpansion(), res.getUnion().getExpansion().getContains(), res.getIntersection().getExpansion().getContains(), "ValueSet.expansion.contains", res);

View File

@ -207,6 +207,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
protected TimeTracker clock;
private boolean tlogging = true;
private ICanonicalResourceLocator locator;
protected String userAgent;
public BaseWorkerContext() throws FileNotFoundException, IOException, FHIRException {
txCache = new TerminologyCache(lock, null);
@ -2100,4 +2101,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
this.locator = locator;
}
public String getUserAgent() {
return userAgent;
}
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
if (txClient != null)
txClient.setUserAgent(userAgent);
}
}

View File

@ -296,6 +296,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
txLog = new HTMLClientLogger(log);
}
txClient.setLogger(txLog);
txClient.setUserAgent(userAgent);
CapabilityStatement cps = txClient.getCapabilitiesStatementQuick();
setTxCaps(txClient.getTerminologyCapabilities());
return cps.getSoftware().getVersion();

View File

@ -54,4 +54,5 @@ public interface TerminologyClient {
CanonicalResource read(String type, String id);
ClientHeaders getClientHeaders();
TerminologyClient setClientHeaders(ClientHeaders clientHeaders);
TerminologyClient setUserAgent(String userAgent);
}

View File

@ -117,7 +117,7 @@ public class BatchLoader {
private static int loadBundle(String server, Bundle b, int size, int start, int end) throws URISyntaxException {
System.out.println("Post to "+server+". size = "+Integer.toString(size)+", start = "+Integer.toString(start)+", total = "+Integer.toString(b.getEntry().size()));
FHIRToolingClient client = new FHIRToolingClient(server);
FHIRToolingClient client = new FHIRToolingClient(server, "fhir/batch-loader");
int c = start;
if (end == -1)
end = b.getEntry().size();

View File

@ -95,10 +95,12 @@ public class FHIRToolingClient {
private ArrayList<Header> headers = new ArrayList<>();
private String username;
private String password;
private String userAgent;
//Pass endpoint for client - URI
public FHIRToolingClient(String baseServiceUrl) throws URISyntaxException {
public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException {
preferredResourceFormat = ResourceFormat.RESOURCE_XML;
this.userAgent = userAgent;
initialize(baseServiceUrl);
}
@ -309,7 +311,7 @@ public class FHIRToolingClient {
if (client.getLogger() != null) {
client.getLogger().logRequest("POST", url.toString(), null, body);
}
result = client.issuePostRequest(url, body, getPreferredResourceFormat(),
result = client.issuePostRequest(url, body, getPreferredResourceFormat(), generateHeaders(),
"POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
} else {
if (client.getLogger() != null) {
@ -336,7 +338,9 @@ public class FHIRToolingClient {
public Bundle transaction(Bundle batch) {
Bundle transactionResult = null;
try {
transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(), ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), "transaction", TIMEOUT_OPERATION + (TIMEOUT_ENTRY * batch.getEntry().size()));
transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(), ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(),
generateHeaders(),
"transaction", TIMEOUT_OPERATION + (TIMEOUT_ENTRY * batch.getEntry().size()));
} catch (Exception e) {
handleException("An error occurred trying to process this transaction request", e);
}
@ -560,6 +564,9 @@ public class FHIRToolingClient {
if(this.headers != null) {
this.headers.forEach(header -> builder.add(header.toString()));
}
if (!Utilities.noString(userAgent)) {
builder.add("User-Agent: "+userAgent);
}
return builder.build();
}
@ -572,5 +579,15 @@ public class FHIRToolingClient {
String base64usernamePassword = Base64.getEncoder().encodeToString(usernamePassword.getBytes());
return new Header("Authorization", "Basic " + base64usernamePassword);
}
public String getUserAgent() {
return userAgent;
}
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
}

View File

@ -149,6 +149,7 @@ public class Client {
public Bundle postBatchRequest(URI resourceUri,
byte[] payload,
String resourceFormat,
Headers headers,
String message,
int timeout) throws IOException {
if (payload == null) throw new EFhirClientException("POST requests require a non-null payload");
@ -157,7 +158,7 @@ public class Client {
.url(resourceUri.toURL())
.post(body);
return executeBundleRequest(request, resourceFormat, new Headers.Builder().build(), message, retryCount, timeout);
return executeBundleRequest(request, resourceFormat, headers, message, retryCount, timeout);
}
public <T extends Resource> Bundle executeBundleRequest(Request.Builder request,

View File

@ -63,7 +63,7 @@ public class FhirRequestBuilder {
* @param headers Any additional {@link Headers} to add to the request.
*/
protected static void formatHeaders(Request.Builder request, String format, Headers headers) {
addDefaultHeaders(request);
addDefaultHeaders(request, headers);
if (format != null) addResourceFormatHeaders(request, format);
if (headers != null) addHeaders(request, headers);
}
@ -75,8 +75,10 @@ public class FhirRequestBuilder {
*
* @param request {@link Request.Builder} to add default headers to.
*/
protected static void addDefaultHeaders(Request.Builder request) {
request.addHeader("User-Agent", "hapi-fhir-tooling-client");
protected static void addDefaultHeaders(Request.Builder request, Headers headers) {
if (headers == null || !headers.names().contains("User-Agent")) {
request.addHeader("User-Agent", "hapi-fhir-tooling-client");
}
request.addHeader("Accept-Charset", DEFAULT_CHARSET);
}
@ -203,7 +205,7 @@ public class FhirRequestBuilder {
}
public <T extends Resource> ResourceRequest<T> execute() throws IOException {
formatHeaders(httpRequest, resourceFormat, null);
formatHeaders(httpRequest, resourceFormat, headers);
Response response = getHttpClient().newCall(httpRequest.build()).execute();
T resource = unmarshalReference(response, resourceFormat);
return new ResourceRequest<T>(resource, response.code(), getLocationHeader(response.headers()));

View File

@ -65,7 +65,7 @@ class FHIRToolingClientTest {
Mockito.when(mockClient.executeBundleRequest(Mockito.any(Request.Builder.class), Mockito.anyString(),
Mockito.any(Headers.class), Mockito.anyString(), Mockito.anyInt(), Mockito.anyLong()))
.thenReturn(generateBundle());
toolingClient = new FHIRToolingClient(TX_ADDR);
toolingClient = new FHIRToolingClient(TX_ADDR, "fhir/test-cases");
toolingClient.setClient(mockClient);
}

View File

@ -19,7 +19,7 @@ class FhirRequestBuilderTest {
@DisplayName("Test default headers are added correctly.")
void addDefaultHeaders() {
Request.Builder request = new Request.Builder().url("http://www.google.com");
FhirRequestBuilder.addDefaultHeaders(request);
FhirRequestBuilder.addDefaultHeaders(request, null);
Map<String, List<String>> headersMap = request.build().headers().toMultimap();
Assertions.assertNotNull(headersMap.get("User-Agent"), "User-Agent header null.");

View File

@ -38,6 +38,7 @@ import java.io.InputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Stack;
@ -674,6 +675,16 @@ public class JsonTrackingParser {
return gson.toJson(json);
}
public static byte[] writeBytes(JsonObject json, boolean pretty) {
if (pretty) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
return gson.toJson(json).getBytes(StandardCharsets.UTF_8);
} else {
Gson gson = new GsonBuilder().create();
return gson.toJson(json).getBytes(StandardCharsets.UTF_8);
}
}
public static JsonObject fetchJson(String source) throws IOException {
URL url = new URL(source+"?nocache=" + System.currentTimeMillis());
HttpURLConnection c = (HttpURLConnection) url.openConnection();

View File

@ -64,6 +64,7 @@ import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.json.JSONUtil;
import org.hl7.fhir.utilities.json.JsonTrackingParser;
import org.hl7.fhir.utilities.npm.NpmPackage.ITransformingLoader;
import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformationSorter;
import org.hl7.fhir.utilities.npm.PackageGenerator.PackageType;
@ -84,6 +85,12 @@ import com.google.gson.JsonObject;
*/
public class NpmPackage {
public interface ITransformingLoader {
byte[] load(File f);
}
public class PackageResourceInformationSorter implements Comparator<PackageResourceInformation> {
@Override
public int compare(PackageResourceInformation o1, PackageResourceInformation o2) {
@ -1054,6 +1061,18 @@ public class NpmPackage {
}
}
public void loadAllFiles(ITransformingLoader loader) throws IOException {
for (String folder : folders.keySet()) {
NpmPackageFolder pf = folders.get(folder);
String p = folder.contains("$") ? path : Utilities.path(path, folder);
for (File f : new File(p).listFiles()) {
if (!f.isDirectory() && !isInternalExemptFile(f)) {
pf.getContent().put(f.getName(), loader.load(f));
}
}
}
}
public boolean isChangedByLoader() {
return changedByLoader;
}

View File

@ -189,23 +189,26 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
igLoader = new IgLoader(getPcm(), getContext(), getVersion(), isDebug());
}
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString) throws FHIRException, IOException, URISyntaxException {
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString, String userAgent) throws FHIRException, IOException, URISyntaxException {
loadCoreDefinitions(src, false, null);
getContext().setUserAgent(userAgent);
getContext().setCanRunWithoutTerminology(canRunWithoutTerminologyServer);
setTerminologyServer(txsrvr, txLog, version);
setVersion(vString);
igLoader = new IgLoader(getPcm(), getContext(), getVersion(), isDebug());
}
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, String vString) throws FHIRException, IOException, URISyntaxException {
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, String vString, String userAgent) throws FHIRException, IOException, URISyntaxException {
loadCoreDefinitions(src, false, null);
getContext().setUserAgent(userAgent);
setTerminologyServer(txsrvr, txLog, version);
setVersion(vString);
igLoader = new IgLoader(getPcm(), getContext(), getVersion(), isDebug());
}
public ValidationEngine(String src, String vString, TimeTracker tt) throws FHIRException, IOException, URISyntaxException {
public ValidationEngine(String src, String vString, TimeTracker tt, String userAgent) throws FHIRException, IOException, URISyntaxException {
loadCoreDefinitions(src, false, tt);
getContext().setUserAgent(userAgent);
setVersion(vString);
igLoader = new IgLoader(getPcm(), getContext(), getVersion(), isDebug());
}
@ -271,7 +274,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
return "n/a: No Terminology Server";
} else {
try {
return context.connectToTSServer(TerminologyClientFactory.makeClient(url, version), log);
return context.connectToTSServer(TerminologyClientFactory.makeClient(url, context.getUserAgent(), version), log);
} catch (Exception e) {
if (context.isCanRunWithoutTerminology()) {
return "n/a: Running without Terminology Server (error: " + e.getMessage() + ")";

View File

@ -231,7 +231,7 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IC
String root = getRoot(p, url);
if (root != null) {
TerminologyClient c;
c = TerminologyClientFactory.makeClient(root, context.getVersion());
c = TerminologyClientFactory.makeClient(root, "fhir/validator", context.getVersion());
return c.read(p[p.length - 2], p[p.length - 1]);
} else {
throw new FHIRException("The URL '" + url + "' is not known to the FHIR validator, and has not been provided as part of the setup / parameters");

View File

@ -265,7 +265,7 @@ public class ValidationService {
System.out.println("No such cached session exists for session id " + sessionId + ", re-instantiating validator.");
}
System.out.print(" Load FHIR v" + cliContext.getSv() + " from " + definitions);
ValidationEngine validator = new ValidationEngine(definitions, cliContext.getSv(), tt);
ValidationEngine validator = new ValidationEngine(definitions, cliContext.getSv(), tt, "fhir/validator");
sessionId = sessionCache.cacheSession(validator);
FhirPublication ver = FhirPublication.fromCode(cliContext.getSv());

View File

@ -87,7 +87,7 @@ public class Common {
public static ValidationEngine getValidationEngine(String version, String txServer, String definitions, String txLog, TimeTracker tt) throws Exception {
System.out.println("Loading (v = " + version + ", tx server -> " + txServer + ")");
ValidationEngine ve = new ValidationEngine(definitions, version, tt);
ValidationEngine ve = new ValidationEngine(definitions, version, tt, "fhir/validator");
ve.connectToTSServer(txServer, txLog, FhirPublication.fromCode(version));
return ve;
}

View File

@ -17,8 +17,8 @@ import org.junit.jupiter.api.Test;
public class ValidationEngineTests {
private static final String DEF_TX = "http://tx.fhir.org";
private static final String DBG_TX = "http://local.fhir.org:960";
// public static final String DEF_TX = "http://tx.fhir.org";
public static final String DEF_TX = "http://local.fhir.org:960";
public static boolean inbuild;
@ -26,7 +26,7 @@ public class ValidationEngineTests {
public void testCurrentXml() throws Exception {
if (!TestUtilities.silent)
System.out.println("TestCurrentXml: Validate patient-example.xml in Current version");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, null, FhirPublication.R4, "4.0.1");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, null, FhirPublication.R4, "4.0.1", "fhir/test-cases");
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient-example.xml"), null);
int e = errors(op);
int w = warnings(op);
@ -46,7 +46,7 @@ public class ValidationEngineTests {
public void testCurrentJson() throws Exception {
if (!TestUtilities.silent)
System.out.println("TestCurrentJson: Validate patient-example.json in Current version");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, null, FhirPublication.R4, "4.0.1");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, null, FhirPublication.R4, "4.0.1", "fhir/test-cases");
OperationOutcome op = ve.validate(FhirFormat.JSON, TestingUtilities.loadTestResourceStream("validator", "patient-example.json"), null);
int e = errors(op);
int w = warnings(op);
@ -66,8 +66,8 @@ public class ValidationEngineTests {
}
if (!TestUtilities.silent)
System.out.println("Test140: Validate patient-example.xml in v1.4.0 version");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r2b.core#1.4.0", DEF_TX, null, FhirPublication.DSTU2016May, "1.4.0");
ve.setNoInvariantChecks(true);
ValidationEngine ve = new ValidationEngine("hl7.fhir.r2b.core#1.4.0", DEF_TX, null, FhirPublication.DSTU2016May, "1.4.0", "fhir/test-cases");
ve.getContext().setUserAgent("fhir/test-cases");
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient140.xml"), null);
if (!TestUtilities.silent)
for (OperationOutcomeIssueComponent iss : op.getIssue()) {
@ -91,7 +91,7 @@ public class ValidationEngineTests {
}
if (!org.hl7.fhir.validation.tests.utilities.TestUtilities.silent)
System.out.println("Test102: Validate patient-example.xml in v1.0.2 version");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, "1.0.2");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, "1.0.2", "fhir/test-cases");
ve.setNoInvariantChecks(true);
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient102.xml"), null);
if (!TestUtilities.silent)
@ -116,7 +116,7 @@ public class ValidationEngineTests {
}
if (!TestUtilities.silent)
System.out.println("TestObs102: Validate patient-example.xml in v1.0.2 version");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, "1.0.2");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, "1.0.2", "fhir/test-cases");
ve.setNoInvariantChecks(true);
OperationOutcome op = ve.validate(FhirFormat.JSON, TestingUtilities.loadTestResourceStream("validator", "observation102.json"), null);
if (!TestUtilities.silent)
@ -138,7 +138,7 @@ public class ValidationEngineTests {
public void test301() throws Exception {
if (!TestUtilities.silent)
System.out.println("Test301: Validate observation301.xml against Core");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, null, FhirPublication.STU3, "3.0.2");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, null, FhirPublication.STU3, "3.0.2", "fhir/test-cases");
if (!TestUtilities.silent)
System.out.println(" .. load USCore");
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "observation301.xml"), null);
@ -157,7 +157,7 @@ public class ValidationEngineTests {
public void test301USCore() throws Exception {
if (!TestUtilities.silent)
System.out.println("Test301USCore: Validate patient300.xml against US-Core");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, null, FhirPublication.STU3, "3.0.2");
ValidationEngine ve = new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, null, FhirPublication.STU3, "3.0.2", "fhir/test-cases");
IgLoader igLoader = new IgLoader(ve.getPcm(), ve.getContext(), ve.getVersion(), true);
if (!TestUtilities.silent)
System.out.println(" .. load USCore");

View File

@ -111,8 +111,6 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
private String version;
private String name;
private static final String DEF_TX = "http://tx.fhir.org";
// private static final String DEF_TX = "http://local.fhir.org:960";
private static Map<String, ValidationEngine> ve = new HashMap<>();
private static ValidationEngine vCurr;
private static IgLoader igLoader;
@ -143,19 +141,20 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
version = VersionUtilities.getMajMin(version);
if (!ve.containsKey(version)) {
if (version.startsWith("5.0"))
ve.put(version, new ValidationEngine("hl7.fhir.r5.core#4.5.0", DEF_TX, txLog, FhirPublication.R5, true, "4.5.0"));
ve.put(version, new ValidationEngine("hl7.fhir.r5.core#4.5.0", ValidationEngineTests.DEF_TX, txLog, FhirPublication.R5, true, "4.5.0", "fhir/test-cases"));
else if (version.startsWith("3.0"))
ve.put(version, new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, txLog, FhirPublication.STU3, true, "3.0.2"));
ve.put(version, new ValidationEngine("hl7.fhir.r3.core#3.0.2", ValidationEngineTests.DEF_TX, txLog, FhirPublication.STU3, true, "3.0.2", "fhir/test-cases"));
else if (version.startsWith("4.0"))
ve.put(version, new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, txLog, FhirPublication.R4, true, "4.0.1"));
ve.put(version, new ValidationEngine("hl7.fhir.r4.core#4.0.1", ValidationEngineTests.DEF_TX, txLog, FhirPublication.R4, true, "4.0.1", "fhir/test-cases"));
else if (version.startsWith("1.0"))
ve.put(version, new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, txLog, FhirPublication.DSTU2, true, "1.0.2"));
ve.put(version, new ValidationEngine("hl7.fhir.r2.core#1.0.2", ValidationEngineTests.DEF_TX, txLog, FhirPublication.DSTU2, true, "1.0.2", "fhir/test-cases"));
else if (version.startsWith("1.4"))
ve.put(version, new ValidationEngine("hl7.fhir.r2b.core#1.4.0", DEF_TX, txLog, FhirPublication.DSTU2016May, true, "1.4.0"));
ve.put(version, new ValidationEngine("hl7.fhir.r2b.core#1.4.0", ValidationEngineTests.DEF_TX, txLog, FhirPublication.DSTU2016May, true, "1.4.0", "fhir/test-cases"));
else
throw new Exception("unknown version " + version);
}
vCurr = ve.get(version);
vCurr.getContext().setUserAgent("fhir/test-cases");
igLoader = new IgLoader(vCurr.getPcm(), vCurr.getContext(), vCurr.getVersion(), true);
if (TestingUtilities.fcontexts == null) {
TestingUtilities.fcontexts = new HashMap<>();