From c7ccbb0110e77eb34731f6eb71da2d3470de6a27 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 10 Oct 2024 19:29:58 +0800 Subject: [PATCH] more work on http client --- .../client/network/FhirRequestBuilder.java | 44 +++++++++++++--- .../client/network/FhirRequestBuilder.java | 52 +++++++++++++++---- .../client/network/FhirRequestBuilder.java | 46 +++++++++++++--- .../hl7/fhir/utilities/xhtml/XhtmlNode.java | 8 ++- .../hl7/fhir/utilities/xhtml/XhtmlUtils.java | 6 ++- 5 files changed, 127 insertions(+), 29 deletions(-) diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/network/FhirRequestBuilder.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/network/FhirRequestBuilder.java index 1e3098b59..68e60979f 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/network/FhirRequestBuilder.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/network/FhirRequestBuilder.java @@ -258,34 +258,59 @@ public class FhirRequestBuilder { */ @SuppressWarnings("unchecked") protected T unmarshalReference(Response response, String format, String resourceType) { + int code = response.code(); + boolean ok = code >= 200 && code < 300; if (response.body() == null) { - return null; + if (!ok) { + throw new EFhirClientException(response.message()); + } else { + return null; + } } + String body; + Resource resource = null; try { + body = response.body().string(); String ct = response.header("Content-Type"); if (ct == null) { - resource = getParser(format).parse(response.body().bytes()); + if (ok) { + resource = getParser(format).parse(body); + } else { + System.out.println("Got error response with no Content-Type from "+source+" with status "+code); + System.out.println(body); + resource = OperationOutcomeUtilities.outcomeFromTextError(body); + } } else { + if (ct.contains(";")) { + ct = ct.substring(0, ct.indexOf(";")); + } switch (ct) { case "application/json": case "application/fhir+json": - resource = getParser(ResourceFormat.RESOURCE_JSON.getHeader()).parse(response.body().bytes()); + if (!format.contains("json")) { + System.out.println("Got json response expecting "+format+" from "+source+" with status "+code); + } + resource = getParser(ResourceFormat.RESOURCE_JSON.getHeader()).parse(body); break; case "application/xml": case "application/fhir+xml": case "text/xml": + if (!format.contains("xml")) { + System.out.println("Got xml response expecting "+format+" from "+source+" with status "+code); + } resource = getParser(ResourceFormat.RESOURCE_XML.getHeader()).parse(response.body().bytes()); break; case "text/plain": - resource = outcomeFromTextError(response.body().string()); + resource = OperationOutcomeUtilities.outcomeFromTextError(body); break; case "text/html" : - resource = OperationOutcomeUtilities.outcomeFromTextError(XhtmlUtils.convertHtmlToText(response.body().string())); + resource = OperationOutcomeUtilities.outcomeFromTextError(XhtmlUtils.convertHtmlToText(response.body().string(), source)); break; default: // not sure what else to do? System.out.println("Got content-type '"+ct+"' from "+source); - resource = OperationOutcomeUtilities.outcomeFromTextError(response.body().string()); + System.out.println(body); + resource = OperationOutcomeUtilities.outcomeFromTextError(body); } } } catch (IOException ioe) { @@ -293,15 +318,20 @@ public class FhirRequestBuilder { } catch (Exception e) { throw new EFhirClientException("Error parsing response message from "+source+": "+e.getMessage(), e); } - if (resource instanceof OperationOutcome && !"OperationOutcome".equals(resourceType)) { + if (resource instanceof OperationOutcome && (!"OperationOutcome".equals(resourceType) || !ok)) { OperationOutcome error = (OperationOutcome) resource; if (hasError((OperationOutcome) resource)) { throw new EFhirClientException("Error from "+source+": " + ResourceUtilities.getErrorDescription(error), error); } else { // umm, weird... + System.out.println("Got OperationOutcome with no error from "+source+" with status "+code); + System.out.println(body); + return null; } } if (resource == null) { + System.out.println("No resource from "+source+" with status "+code); + System.out.println(body); return null; // shouldn't get here? } if (resourceType != null && !resource.fhirType().equals(resourceType)) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/utils/client/network/FhirRequestBuilder.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/utils/client/network/FhirRequestBuilder.java index 4d7d9a229..fa7a66300 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/utils/client/network/FhirRequestBuilder.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/utils/client/network/FhirRequestBuilder.java @@ -248,34 +248,59 @@ public class FhirRequestBuilder { */ @SuppressWarnings("unchecked") protected T unmarshalReference(Response response, String format, String resourceType) { + int code = response.code(); + boolean ok = code >= 200 && code < 300; if (response.body() == null) { - return null; - } + if (!ok) { + throw new EFhirClientException(response.message()); + } else { + return null; + } + } + String body; + Resource resource = null; try { + body = response.body().string(); String ct = response.header("Content-Type"); if (ct == null) { - resource = getParser(format).parse(response.body().bytes()); - } else { + if (ok) { + resource = getParser(format).parse(body); + } else { + System.out.println("Got error response with no Content-Type from "+source+" with status "+code); + System.out.println(body); + resource = OperationOutcomeUtilities.outcomeFromTextError(body); + } + } else { + if (ct.contains(";")) { + ct = ct.substring(0, ct.indexOf(";")); + } switch (ct) { case "application/json": case "application/fhir+json": - resource = getParser(ResourceFormat.RESOURCE_JSON.getHeader()).parse(response.body().bytes()); + if (!format.contains("json")) { + System.out.println("Got json response expecting "+format+" from "+source+" with status "+code); + } + resource = getParser(ResourceFormat.RESOURCE_JSON.getHeader()).parse(body); break; case "application/xml": case "application/fhir+xml": case "text/xml": - resource = getParser(ResourceFormat.RESOURCE_XML.getHeader()).parse(response.body().bytes()); + if (!format.contains("xml")) { + System.out.println("Got xml response expecting "+format+" from "+source+" with status "+code); + } + resource = getParser(ResourceFormat.RESOURCE_XML.getHeader()).parse(body); break; case "text/plain": - resource = OperationOutcomeUtilities.outcomeFromTextError(response.body().string()); + resource = OperationOutcomeUtilities.outcomeFromTextError(body); break; case "text/html" : - resource = OperationOutcomeUtilities.outcomeFromTextError(XhtmlUtils.convertHtmlToText(response.body().string())); + resource = OperationOutcomeUtilities.outcomeFromTextError(XhtmlUtils.convertHtmlToText(response.body().string(), source)); break; default: // not sure what else to do? System.out.println("Got content-type '"+ct+"' from "+source); - resource = OperationOutcomeUtilities.outcomeFromTextError(response.body().string()); + System.out.println(body); + resource = OperationOutcomeUtilities.outcomeFromTextError(body); } } } catch (IOException ioe) { @@ -283,21 +308,26 @@ public class FhirRequestBuilder { } catch (Exception e) { throw new EFhirClientException("Error parsing response message from "+source+": "+e.getMessage(), e); } - if (resource instanceof OperationOutcome && !"OperationOutcome".equals(resourceType)) { + if (resource instanceof OperationOutcome && (!"OperationOutcome".equals(resourceType) || !ok)) { OperationOutcome error = (OperationOutcome) resource; if (hasError((OperationOutcome) resource)) { throw new EFhirClientException("Error from "+source+": " + ResourceUtilities.getErrorDescription(error), error); } else { // umm, weird... + System.out.println("Got OperationOutcome with no error from "+source+" with status "+code); + System.out.println(body); + return null; } } if (resource == null) { + System.out.println("No resource from "+source+" with status "+code); + System.out.println(body); return null; // shouldn't get here? } if (resourceType != null && !resource.fhirType().equals(resourceType)) { throw new EFhirClientException("Error parsing response message from "+source+": Found an "+resource.fhirType()+" looking for a "+resourceType); } - return (T) resource; + return (T) resource; } /** diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/network/FhirRequestBuilder.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/network/FhirRequestBuilder.java index 14153a38b..5704247be 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/network/FhirRequestBuilder.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/network/FhirRequestBuilder.java @@ -251,34 +251,59 @@ public class FhirRequestBuilder { */ @SuppressWarnings("unchecked") protected T unmarshalReference(Response response, String format, String resourceType) { + int code = response.code(); + boolean ok = code >= 200 && code < 300; if (response.body() == null) { - return null; + if (!ok) { + throw new EFhirClientException(response.message()); + } else { + return null; + } } + String body; + Resource resource = null; try { + body = response.body().string(); String ct = response.header("Content-Type"); if (ct == null) { - resource = getParser(format).parse(response.body().bytes()); + if (ok) { + resource = getParser(format).parse(body); + } else { + System.out.println("Got error response with no Content-Type from "+source+" with status "+code); + System.out.println(body); + resource = OperationOutcomeUtilities.outcomeFromTextError(body); + } } else { + if (ct.contains(";")) { + ct = ct.substring(0, ct.indexOf(";")); + } switch (ct) { case "application/json": case "application/fhir+json": - resource = getParser(ResourceFormat.RESOURCE_JSON.getHeader()).parse(response.body().bytes()); + if (!format.contains("json")) { + System.out.println("Got json response expecting "+format+" from "+source+" with status "+code); + } + resource = getParser(ResourceFormat.RESOURCE_JSON.getHeader()).parse(body); break; case "application/xml": case "application/fhir+xml": case "text/xml": - resource = getParser(ResourceFormat.RESOURCE_XML.getHeader()).parse(response.body().bytes()); + if (!format.contains("xml")) { + System.out.println("Got xml response expecting "+format+" from "+source+" with status "+code); + } + resource = getParser(ResourceFormat.RESOURCE_XML.getHeader()).parse(body); break; case "text/plain": - resource = OperationOutcomeUtilities.outcomeFromTextError(response.body().string()); + resource = OperationOutcomeUtilities.outcomeFromTextError(body); break; case "text/html" : - resource = OperationOutcomeUtilities.outcomeFromTextError(XhtmlUtils.convertHtmlToText(response.body().string())); + resource = OperationOutcomeUtilities.outcomeFromTextError(XhtmlUtils.convertHtmlToText(response.body().string(), source)); break; default: // not sure what else to do? System.out.println("Got content-type '"+ct+"' from "+source); - resource = OperationOutcomeUtilities.outcomeFromTextError(response.body().string()); + System.out.println(body); + resource = OperationOutcomeUtilities.outcomeFromTextError(body); } } } catch (IOException ioe) { @@ -286,15 +311,20 @@ public class FhirRequestBuilder { } catch (Exception e) { throw new EFhirClientException("Error parsing response message from "+source+": "+e.getMessage(), e); } - if (resource instanceof OperationOutcome && !"OperationOutcome".equals(resourceType)) { + if (resource instanceof OperationOutcome && (!"OperationOutcome".equals(resourceType) || !ok)) { OperationOutcome error = (OperationOutcome) resource; if (hasError((OperationOutcome) resource)) { throw new EFhirClientException("Error from "+source+": " + ResourceUtilities.getErrorDescription(error), error); } else { // umm, weird... + System.out.println("Got OperationOutcome with no error from "+source+" with status "+code); + System.out.println(body); + return null; } } if (resource == null) { + System.out.println("No resource from "+source+" with status "+code); + System.out.println(body); return null; // shouldn't get here? } if (resourceType != null && !resource.fhirType().equals(resourceType)) { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java index 72e251336..fd10795d3 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java @@ -348,7 +348,13 @@ public class XhtmlNode extends XhtmlFluent implements IBaseXhtml { } } if (n.getNodeType() == NodeType.Element) { - b.append(n.allText()); + if (!Utilities.existsInList(n.getName(), "img")) { + b.append(n.allText()); + } else if (n.hasAttribute("alt")) { + b.append(n.getAttribute("alt")); + } else { + b.append("[image]"); + } if (Utilities.existsInList(n.getName(), "p", "div", "tr", "th", "ul", "ol", "li", "h1", "h2", "h3", "h4", "h5", "h6")) { b.append("\r\n"); } else if (Utilities.existsInList(n.getName(), "th", "td", "span")) { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlUtils.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlUtils.java index c793191d0..4a48b6056 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlUtils.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlUtils.java @@ -2,13 +2,15 @@ package org.hl7.fhir.utilities.xhtml; public class XhtmlUtils { - public static String convertHtmlToText(String source) { + public static String convertHtmlToText(String source, String desc) { try { XhtmlDocument doc = new XhtmlParser().parse(source, "html"); return doc.getDocumentElement().allText(); } catch (Exception e) { - e.printStackTrace(); // todo - should we try another way? + System.err.println("XHTML content could not be parsed from "+desc); + e.printStackTrace(); + System.err.println(source); return "Unparseable HTML"; } }