Adding changes for logging request and resp
This commit is contained in:
parent
83b1702cc5
commit
7bcd2b6434
|
@ -0,0 +1 @@
|
|||
* Updating client logger to log both req and resp
|
|
@ -1,33 +1,33 @@
|
|||
package org.hl7.fhir.r4.context;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -276,15 +276,9 @@ public class FHIRToolingClient {
|
|||
URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps);
|
||||
if (complex) {
|
||||
byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()));
|
||||
if (client.getLogger() != null) {
|
||||
client.getLogger().logRequest("POST", url.toString(), null, body);
|
||||
}
|
||||
result = client.issuePostRequest(url, body, getPreferredResourceFormat(), generateHeaders(),
|
||||
"POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
|
||||
} else {
|
||||
if (client.getLogger() != null) {
|
||||
client.getLogger().logRequest("GET", url.toString(), null, null);
|
||||
}
|
||||
result = client.issueGetResourceRequest(url, getPreferredResourceFormat(), generateHeaders(), "GET " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
|
||||
}
|
||||
if (result.isUnsuccessfulRequest()) {
|
||||
|
|
|
@ -19,6 +19,7 @@ public class Client {
|
|||
public static final String DEFAULT_CHARSET = "UTF-8";
|
||||
private static final long DEFAULT_TIMEOUT = 5000;
|
||||
private ToolingClientLogger logger;
|
||||
private FhirLoggingInterceptor fhirLoggingInterceptor;
|
||||
private int retryCount;
|
||||
private long timeout = DEFAULT_TIMEOUT;
|
||||
|
||||
|
@ -28,6 +29,7 @@ public class Client {
|
|||
|
||||
public void setLogger(ToolingClientLogger logger) {
|
||||
this.logger = logger;
|
||||
this.fhirLoggingInterceptor = new FhirLoggingInterceptor(logger);
|
||||
}
|
||||
|
||||
public int getRetryCount() {
|
||||
|
@ -167,7 +169,7 @@ public class Client {
|
|||
int retryCount,
|
||||
long timeout) throws IOException {
|
||||
return new FhirRequestBuilder(request)
|
||||
.withLogger(logger)
|
||||
.withLogger(fhirLoggingInterceptor)
|
||||
.withResourceFormat(resourceFormat)
|
||||
.withRetryCount(retryCount)
|
||||
.withMessage(message)
|
||||
|
@ -183,7 +185,7 @@ public class Client {
|
|||
int retryCount,
|
||||
long timeout) throws IOException {
|
||||
return new FhirRequestBuilder(request)
|
||||
.withLogger(logger)
|
||||
.withLogger(fhirLoggingInterceptor)
|
||||
.withResourceFormat(resourceFormat)
|
||||
.withRetryCount(retryCount)
|
||||
.withMessage(message)
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package org.hl7.fhir.r4.utils.client.network;
|
||||
|
||||
import okhttp3.*;
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FhirLoggingInterceptor implements Interceptor {
|
||||
|
||||
private ToolingClientLogger logger;
|
||||
|
||||
public FhirLoggingInterceptor(ToolingClientLogger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public FhirLoggingInterceptor setLogger(ToolingClientLogger logger) {
|
||||
this.logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Response intercept(@NotNull Interceptor.Chain chain) throws IOException {
|
||||
// Log Request
|
||||
Request request = chain.request();
|
||||
logger.logRequest(request.method(), request.url().toString(), new ArrayList<>(request.headers().names()),
|
||||
request.body() != null ? request.body().toString().getBytes() : null);
|
||||
|
||||
// Log Response
|
||||
Response response = null;
|
||||
response = chain.proceed(chain.request());
|
||||
|
||||
MediaType contentType = null;
|
||||
byte[] bodyBytes = null;
|
||||
if (response.body() != null) {
|
||||
contentType = response.body().contentType();
|
||||
bodyBytes = response.body().bytes();
|
||||
}
|
||||
|
||||
// Get Headers as List
|
||||
List<String> headerList = new ArrayList<>();
|
||||
Map<String, List<String>> headerMap = response.headers().toMultimap();
|
||||
headerMap.keySet().forEach(key -> headerMap.get(key).forEach(value -> headerList.add(key + ":" + value)));
|
||||
|
||||
logger.logResponse(Integer.toString(response.code()), headerList, bodyBytes);
|
||||
|
||||
// Reading byte[] clears body. Need to recreate.
|
||||
ResponseBody body = ResponseBody.create(bodyBytes, contentType);
|
||||
return response.newBuilder().body(body).build();
|
||||
}
|
||||
}
|
|
@ -45,10 +45,11 @@ public class FhirRequestBuilder {
|
|||
* Time unit for {@link FhirRequestBuilder#timeout}.
|
||||
*/
|
||||
private TimeUnit timeoutUnit = TimeUnit.MILLISECONDS;
|
||||
|
||||
/**
|
||||
* {@link ToolingClientLogger} for log output.
|
||||
* {@link FhirLoggingInterceptor} for log output.
|
||||
*/
|
||||
private ToolingClientLogger logger = null;
|
||||
private FhirLoggingInterceptor logger = null;
|
||||
|
||||
public FhirRequestBuilder(Request.Builder httpRequest) {
|
||||
this.httpRequest = httpRequest;
|
||||
|
@ -160,7 +161,11 @@ public class FhirRequestBuilder {
|
|||
.build();
|
||||
};
|
||||
|
||||
return okHttpClient.newBuilder()
|
||||
OkHttpClient.Builder builder = okHttpClient.newBuilder();
|
||||
if (logger != null) builder.addInterceptor(logger);
|
||||
builder.addInterceptor(new RetryInterceptor(retryCount));
|
||||
|
||||
return builder.connectTimeout(timeout, timeoutUnit)
|
||||
.addInterceptor(new RetryInterceptor(retryCount))
|
||||
.connectTimeout(timeout, timeoutUnit)
|
||||
.writeTimeout(timeout, timeoutUnit)
|
||||
|
@ -189,7 +194,7 @@ public class FhirRequestBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public FhirRequestBuilder withLogger(ToolingClientLogger logger) {
|
||||
public FhirRequestBuilder withLogger(FhirLoggingInterceptor logger) {
|
||||
this.logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
@ -228,7 +233,6 @@ public class FhirRequestBuilder {
|
|||
if (response.body() != null) {
|
||||
try {
|
||||
byte[] body = response.body().bytes();
|
||||
log(response.code(), response.headers(), body);
|
||||
resource = (T) getParser(format).parse(body);
|
||||
if (resource instanceof OperationOutcome && hasError((OperationOutcome) resource)) {
|
||||
error = (OperationOutcome) resource;
|
||||
|
@ -255,7 +259,6 @@ public class FhirRequestBuilder {
|
|||
OperationOutcome error = null;
|
||||
try {
|
||||
byte[] body = response.body().bytes();
|
||||
log(response.code(), response.headers(), body);
|
||||
String contentType = response.header("Content-Type");
|
||||
if (body != null) {
|
||||
if (contentType.contains(ResourceFormat.RESOURCE_XML.getHeader()) || contentType.contains("text/xml+fhir")) {
|
||||
|
@ -301,30 +304,4 @@ public class FhirRequestBuilder {
|
|||
throw new EFhirClientException("Invalid format: " + format);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the given {@link Response}, using the current {@link ToolingClientLogger}. If the current
|
||||
* {@link FhirRequestBuilder#logger} is null, no action is taken.
|
||||
*
|
||||
* @param responseCode HTTP response code
|
||||
* @param responseHeaders {@link Headers} from response
|
||||
* @param responseBody Byte array response
|
||||
*/
|
||||
protected void log(int responseCode, Headers responseHeaders, byte[] responseBody) {
|
||||
if (logger != null) {
|
||||
List<String> headerList = new ArrayList<>(Collections.emptyList());
|
||||
Map<String, List<String>> headerMap = responseHeaders.toMultimap();
|
||||
headerMap.keySet().forEach(key -> headerMap.get(key).forEach(value -> headerList.add(key + ":" + value)));
|
||||
|
||||
try {
|
||||
logger.logResponse(Integer.toString(responseCode), headerList, responseBody);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error parsing response body passed in to logger ->\n" + e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
// else { // TODO fix logs
|
||||
// System.out.println("Call to log HTTP response with null ToolingClientLogger set... are you forgetting to " +
|
||||
// "initialize your logger?");
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,6 +107,12 @@
|
|||
<version>4.9.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>logging-interceptor</artifactId>
|
||||
<version>4.9.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
package org.hl7.fhir.r5.context;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
@ -42,7 +42,7 @@ import org.hl7.fhir.utilities.Utilities;
|
|||
|
||||
public class HTMLClientLogger extends BaseLogger implements ToolingClientLogger {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
private PrintStream file;
|
||||
|
||||
|
|
|
@ -308,15 +308,9 @@ public class FHIRToolingClient {
|
|||
URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps);
|
||||
if (complex) {
|
||||
byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()));
|
||||
if (client.getLogger() != null) {
|
||||
client.getLogger().logRequest("POST", url.toString(), null, body);
|
||||
}
|
||||
result = client.issuePostRequest(url, body, getPreferredResourceFormat(), generateHeaders(),
|
||||
"POST " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
|
||||
} else {
|
||||
if (client.getLogger() != null) {
|
||||
client.getLogger().logRequest("GET", url.toString(), null, null);
|
||||
}
|
||||
result = client.issueGetResourceRequest(url, getPreferredResourceFormat(), generateHeaders(), "GET " + resourceClass.getName() + "/$" + name, TIMEOUT_OPERATION_LONG);
|
||||
}
|
||||
if (result.isUnsuccessfulRequest()) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import okhttp3.Headers;
|
|||
import okhttp3.MediaType;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.utils.client.EFhirClientException;
|
||||
|
@ -19,6 +20,7 @@ public class Client {
|
|||
public static final String DEFAULT_CHARSET = "UTF-8";
|
||||
private static final long DEFAULT_TIMEOUT = 5000;
|
||||
private ToolingClientLogger logger;
|
||||
private FhirLoggingInterceptor fhirLoggingInterceptor;
|
||||
private int retryCount;
|
||||
private long timeout = DEFAULT_TIMEOUT;
|
||||
|
||||
|
@ -28,6 +30,7 @@ public class Client {
|
|||
|
||||
public void setLogger(ToolingClientLogger logger) {
|
||||
this.logger = logger;
|
||||
this.fhirLoggingInterceptor = new FhirLoggingInterceptor(logger);
|
||||
}
|
||||
|
||||
public int getRetryCount() {
|
||||
|
@ -168,7 +171,7 @@ public class Client {
|
|||
int retryCount,
|
||||
long timeout) throws IOException {
|
||||
return new FhirRequestBuilder(request)
|
||||
.withLogger(logger)
|
||||
.withLogger(fhirLoggingInterceptor)
|
||||
.withResourceFormat(resourceFormat)
|
||||
.withRetryCount(retryCount)
|
||||
.withMessage(message)
|
||||
|
@ -184,7 +187,7 @@ public class Client {
|
|||
int retryCount,
|
||||
long timeout) throws IOException {
|
||||
return new FhirRequestBuilder(request)
|
||||
.withLogger(logger)
|
||||
.withLogger(fhirLoggingInterceptor)
|
||||
.withResourceFormat(resourceFormat)
|
||||
.withRetryCount(retryCount)
|
||||
.withMessage(message)
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package org.hl7.fhir.r5.utils.client.network;
|
||||
|
||||
import okhttp3.*;
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FhirLoggingInterceptor implements Interceptor {
|
||||
|
||||
private ToolingClientLogger logger;
|
||||
|
||||
public FhirLoggingInterceptor(ToolingClientLogger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public FhirLoggingInterceptor setLogger(ToolingClientLogger logger) {
|
||||
this.logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Response intercept(@NotNull Interceptor.Chain chain) throws IOException {
|
||||
// Log Request
|
||||
Request request = chain.request();
|
||||
logger.logRequest(request.method(), request.url().toString(), new ArrayList<>(request.headers().names()),
|
||||
request.body() != null ? request.body().toString().getBytes() : null);
|
||||
|
||||
// Log Response
|
||||
Response response = null;
|
||||
response = chain.proceed(chain.request());
|
||||
|
||||
MediaType contentType = null;
|
||||
byte[] bodyBytes = null;
|
||||
if (response.body() != null) {
|
||||
contentType = response.body().contentType();
|
||||
bodyBytes = response.body().bytes();
|
||||
}
|
||||
|
||||
// Get Headers as List
|
||||
List<String> headerList = new ArrayList<>();
|
||||
Map<String, List<String>> headerMap = response.headers().toMultimap();
|
||||
headerMap.keySet().forEach(key -> headerMap.get(key).forEach(value -> headerList.add(key + ":" + value)));
|
||||
|
||||
logger.logResponse(Integer.toString(response.code()), headerList, bodyBytes);
|
||||
|
||||
// Reading byte[] clears body. Need to recreate.
|
||||
ResponseBody body = ResponseBody.create(bodyBytes, contentType);
|
||||
return response.newBuilder().body(body).build();
|
||||
}
|
||||
}
|
|
@ -45,10 +45,11 @@ public class FhirRequestBuilder {
|
|||
* Time unit for {@link FhirRequestBuilder#timeout}.
|
||||
*/
|
||||
private TimeUnit timeoutUnit = TimeUnit.MILLISECONDS;
|
||||
|
||||
/**
|
||||
* {@link ToolingClientLogger} for log output.
|
||||
* {@link FhirLoggingInterceptor} for log output.
|
||||
*/
|
||||
private ToolingClientLogger logger = null;
|
||||
private FhirLoggingInterceptor logger = null;
|
||||
|
||||
public FhirRequestBuilder(Request.Builder httpRequest) {
|
||||
this.httpRequest = httpRequest;
|
||||
|
@ -160,9 +161,11 @@ public class FhirRequestBuilder {
|
|||
.build();
|
||||
};
|
||||
|
||||
return okHttpClient.newBuilder()
|
||||
.addInterceptor(new RetryInterceptor(retryCount))
|
||||
.connectTimeout(timeout, timeoutUnit)
|
||||
OkHttpClient.Builder builder = okHttpClient.newBuilder();
|
||||
if (logger != null) builder.addInterceptor(logger);
|
||||
builder.addInterceptor(new RetryInterceptor(retryCount));
|
||||
|
||||
return builder.connectTimeout(timeout, timeoutUnit)
|
||||
.writeTimeout(timeout, timeoutUnit)
|
||||
.readTimeout(timeout, timeoutUnit)
|
||||
.proxyAuthenticator(proxyAuthenticator)
|
||||
|
@ -189,7 +192,7 @@ public class FhirRequestBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public FhirRequestBuilder withLogger(ToolingClientLogger logger) {
|
||||
public FhirRequestBuilder withLogger(FhirLoggingInterceptor logger) {
|
||||
this.logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
@ -228,7 +231,6 @@ public class FhirRequestBuilder {
|
|||
if (response.body() != null) {
|
||||
try {
|
||||
byte[] body = response.body().bytes();
|
||||
log(response.code(), response.headers(), body);
|
||||
resource = (T) getParser(format).parse(body);
|
||||
if (resource instanceof OperationOutcome && hasError((OperationOutcome) resource)) {
|
||||
error = (OperationOutcome) resource;
|
||||
|
@ -255,7 +257,6 @@ public class FhirRequestBuilder {
|
|||
OperationOutcome error = null;
|
||||
try {
|
||||
byte[] body = response.body().bytes();
|
||||
log(response.code(), response.headers(), body);
|
||||
String contentType = response.header("Content-Type");
|
||||
if (body != null) {
|
||||
if (contentType.contains(ResourceFormat.RESOURCE_XML.getHeader()) || contentType.contains("text/xml+fhir")) {
|
||||
|
@ -301,30 +302,4 @@ public class FhirRequestBuilder {
|
|||
throw new EFhirClientException("Invalid format: " + format);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the given {@link Response}, using the current {@link ToolingClientLogger}. If the current
|
||||
* {@link FhirRequestBuilder#logger} is null, no action is taken.
|
||||
*
|
||||
* @param responseCode HTTP response code
|
||||
* @param responseHeaders {@link Headers} from response
|
||||
* @param responseBody Byte array response
|
||||
*/
|
||||
protected void log(int responseCode, Headers responseHeaders, byte[] responseBody) {
|
||||
if (logger != null) {
|
||||
List<String> headerList = new ArrayList<>(Collections.emptyList());
|
||||
Map<String, List<String>> headerMap = responseHeaders.toMultimap();
|
||||
headerMap.keySet().forEach(key -> headerMap.get(key).forEach(value -> headerList.add(key + ":" + value)));
|
||||
|
||||
try {
|
||||
logger.logResponse(Integer.toString(responseCode), headerList, responseBody);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error parsing response body passed in to logger ->\n" + e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
// else { // TODO fix logs
|
||||
// System.out.println("Call to log HTTP response with null ToolingClientLogger set... are you forgetting to " +
|
||||
// "initialize your logger?");
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,11 @@ import okhttp3.HttpUrl;
|
|||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import org.hl7.fhir.r5.context.HTMLClientLogger;
|
||||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.model.*;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
@ -143,4 +145,24 @@ class ClientTest {
|
|||
Assertions.assertArrayEquals(payload, recordedRequest.getBody().readByteArray(),
|
||||
"POST request payload does not match send data.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Testing the logger works.")
|
||||
void test_logger() throws IOException, URISyntaxException, InterruptedException {
|
||||
byte[] payload = ByteUtils.resourceToByteArray(patient, true, false);
|
||||
server.enqueue(
|
||||
new MockResponse()
|
||||
.setResponseCode(200)
|
||||
.setBody(new String(payload))
|
||||
);
|
||||
HTMLClientLogger mockLogger = Mockito.mock(HTMLClientLogger.class);
|
||||
client.setLogger(mockLogger);
|
||||
client.issuePostRequest(new URI(serverUrl.toString()), payload,
|
||||
"xml", null, TIMEOUT);
|
||||
server.takeRequest();
|
||||
Mockito.verify(mockLogger, Mockito.times(1))
|
||||
.logRequest(Mockito.anyString(), Mockito.anyString(), Mockito.anyList(), Mockito.any());
|
||||
Mockito.verify(mockLogger, Mockito.times(1))
|
||||
.logResponse(Mockito.anyString(), Mockito.anyList(), Mockito.any());
|
||||
}
|
||||
}
|
|
@ -86,6 +86,12 @@
|
|||
<version>${validator_test_case_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>logging-interceptor</artifactId>
|
||||
<version>4.9.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package org.hl7.fhir.utilities;
|
||||
|
||||
package org.hl7.fhir.utilities;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
@ -28,17 +28,16 @@ package org.hl7.fhir.utilities;
|
|||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ToolingClientLogger {
|
||||
|
||||
public void logRequest(String method, String url, List<String> headers, byte[] body);
|
||||
public void logResponse(String outcome, List<String> headers, byte[] body);
|
||||
public String getLastId();
|
||||
public void clearLastId();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ToolingClientLogger {
|
||||
|
||||
void logRequest(String method, String url, List<String> headers, byte[] body);
|
||||
void logResponse(String outcome, List<String> headers, byte[] body);
|
||||
String getLastId();
|
||||
void clearLastId();
|
||||
|
||||
}
|
Loading…
Reference in New Issue