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