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