
001package org.hl7.fhir.r4.utils.client.network; 002 003import java.io.IOException; 004import java.net.URI; 005import java.util.Collections; 006import java.util.Map; 007import java.util.concurrent.TimeUnit; 008 009import lombok.Getter; 010import lombok.Setter; 011import org.hl7.fhir.r4.model.Bundle; 012import org.hl7.fhir.r4.model.Resource; 013import org.hl7.fhir.r4.utils.client.EFhirClientException; 014import org.hl7.fhir.utilities.ToolingClientLogger; 015 016import org.hl7.fhir.utilities.http.HTTPHeader; 017import org.hl7.fhir.utilities.http.HTTPRequest; 018 019public class Client { 020 021 public static final String DEFAULT_CHARSET = "UTF-8"; 022 023 @Getter @Setter 024 private ToolingClientLogger logger; 025 026 @Getter @Setter 027 private int retryCount; 028 029 @Getter @Setter 030 private String base; 031 032 public <T extends Resource> ResourceRequest<T> issueOptionsRequest(URI optionsUri, String resourceFormat, 033 String message, long timeout) throws IOException { 034 035 HTTPRequest request = new HTTPRequest() 036 .withUrl(optionsUri.toURL()) 037 .withMethod(HTTPRequest.HttpMethod.OPTIONS); 038 return executeFhirRequest(request, resourceFormat, Collections.emptyList(), message, retryCount, timeout); 039 } 040 041 public <T extends Resource> ResourceRequest<T> issueGetResourceRequest(URI resourceUri, String resourceFormat, 042 Iterable<HTTPHeader> headers, String message, long timeout) throws IOException { 043 HTTPRequest request = new HTTPRequest() 044 .withUrl(resourceUri.toURL()) 045 .withMethod(HTTPRequest.HttpMethod.GET); 046 return executeFhirRequest(request, resourceFormat, headers, message, retryCount, timeout); 047 } 048 049 public <T extends Resource> ResourceRequest<T> issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, 050 String message, long timeout) throws IOException { 051 return issuePutRequest(resourceUri, payload, resourceFormat, Collections.emptyList(), message, timeout); 052 } 053 054 public <T extends Resource> ResourceRequest<T> issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, 055 Iterable<HTTPHeader> headers, String message, long timeout) throws IOException { 056 if (payload == null) 057 throw new EFhirClientException("PUT requests require a non-null payload"); 058 059 HTTPRequest request = new HTTPRequest() 060 .withUrl(resourceUri.toURL()) 061 .withMethod(HTTPRequest.HttpMethod.PUT) 062 .withBody(payload) 063 .withContentType(getContentTypeWithDefaultCharset(resourceFormat)); 064 065 return executeFhirRequest(request, resourceFormat, headers, message, retryCount, timeout); 066 } 067 068 public <T extends Resource> ResourceRequest<T> issuePostRequest(URI resourceUri, byte[] payload, 069 String resourceFormat, String message, long timeout) throws IOException { 070 return issuePostRequest(resourceUri, payload, resourceFormat, Collections.emptyList(), message, timeout); 071 } 072 073 public <T extends Resource> ResourceRequest<T> issuePostRequest(URI resourceUri, byte[] payload, 074 String resourceFormat, Iterable<HTTPHeader> headers, String message, long timeout) throws IOException { 075 if (payload == null) 076 throw new EFhirClientException("POST requests require a non-null payload"); 077 078 HTTPRequest request = new HTTPRequest() 079 .withUrl(resourceUri.toURL()) 080 .withMethod(HTTPRequest.HttpMethod.POST) 081 .withBody(payload) 082 .withContentType(getContentTypeWithDefaultCharset(resourceFormat)); 083 084 return executeFhirRequest(request, resourceFormat, headers, message, retryCount, timeout); 085 } 086 087 public boolean issueDeleteRequest(URI resourceUri, int timeout) throws IOException { 088 HTTPRequest request = new HTTPRequest() 089 .withUrl(resourceUri.toURL()) 090 .withMethod(HTTPRequest.HttpMethod.DELETE); 091 return executeFhirRequest(request, null, Collections.emptyList(), null, retryCount, timeout) 092 .isSuccessfulRequest(); 093 } 094 095 public Bundle issueGetFeedRequest(URI resourceUri, String resourceFormat, int timeout) throws IOException { 096 HTTPRequest request = new HTTPRequest() 097 .withUrl(resourceUri.toURL()) 098 .withMethod(HTTPRequest.HttpMethod.GET); 099 100 return executeBundleRequest(request, resourceFormat, Collections.emptyList(), null, retryCount, timeout); 101 } 102 103 public Bundle issuePostFeedRequest(URI resourceUri, Map<String, String> parameters, String resourceName, 104 Resource resource, String resourceFormat, int timeout) throws IOException { 105 String boundary = "----WebKitFormBoundarykbMUo6H8QaUnYtRy"; 106 byte[] payload = ByteUtils.encodeFormSubmission(parameters, resourceName, resource, boundary); 107 108 HTTPRequest request = new HTTPRequest() 109 .withUrl(resourceUri.toURL()) 110 .withMethod(HTTPRequest.HttpMethod.POST) 111 .withBody(payload) 112 .withContentType(getContentTypeWithDefaultCharset(resourceFormat)); 113 114 return executeBundleRequest(request, resourceFormat, Collections.emptyList(), null, retryCount, timeout); 115 } 116 117 public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout) 118 throws IOException { 119 if (payload == null) 120 throw new EFhirClientException("POST requests require a non-null payload"); 121 122 HTTPRequest request = new HTTPRequest() 123 .withUrl(resourceUri.toURL()) 124 .withMethod(HTTPRequest.HttpMethod.POST) 125 .withBody(payload) 126 .withContentType(getContentTypeWithDefaultCharset(resourceFormat)); 127 128 return executeBundleRequest(request, resourceFormat, Collections.emptyList(), message, retryCount, timeout); 129 } 130 131 private static String getContentTypeWithDefaultCharset(String resourceFormat) { 132 return resourceFormat + ";charset=" + DEFAULT_CHARSET; 133 } 134 135 public <T extends Resource> Bundle executeBundleRequest(HTTPRequest request, String resourceFormat, 136 Iterable<HTTPHeader> headers, String message, int retryCount, long timeout) throws IOException { 137 return new FhirRequestBuilder(request, base).withLogger(logger).withResourceFormat(resourceFormat) 138 .withRetryCount(retryCount).withMessage(message) 139 .withHeaders(headers == null ? Collections.emptyList() : headers) 140 .withTimeout(timeout, TimeUnit.MILLISECONDS).executeAsBatch(); 141 } 142 143 public <T extends Resource> ResourceRequest<T> executeFhirRequest(HTTPRequest request, String resourceFormat, 144 Iterable<HTTPHeader> headers, String message, int retryCount, long timeout) throws IOException { 145 return new FhirRequestBuilder(request, base).withLogger(logger).withResourceFormat(resourceFormat) 146 .withRetryCount(retryCount).withMessage(message) 147 .withHeaders(headers == null ? Collections.emptyList() : headers) 148 .withTimeout(timeout, TimeUnit.MILLISECONDS).execute(); 149 } 150}