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