protected void streamOperationOutcome( BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, RequestDetails theRequest) throws IOException { theResponse.setStatus(theE.getStatusCode()); theServer.addHeadersToResponse(theResponse); if (theE.getOperationOutcome() != null) { theResponse.setContentType(theEncodingNotNull.getResourceContentType()); IParser parser = theEncodingNotNull.newParser(theServer.getFhirContext()); parser.setPrettyPrint(RestfulServerUtils.prettyPrintResponse(theServer, theRequest)); Writer writer = theResponse.getWriter(); try { parser.encodeResourceToWriter(theE.getOperationOutcome(), writer); } finally { writer.close(); } } else { theResponse.setContentType(Constants.CT_TEXT); Writer writer = theResponse.getWriter(); try { writer.append(theE.getMessage()); } finally { writer.close(); } } }
@Override public Bundle invokeClient( String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException { EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType); if (respType == null) { throw NonFhirResponseException.newInstance( theResponseStatusCode, theResponseMimeType, theResponseReader); } IParser parser = respType.newParser(myContext); return parser.parseBundle(myType, theResponseReader); }
protected IResource parseResourceBody(String theResourceBody) { EncodingEnum encoding = null; for (int i = 0; i < theResourceBody.length() && encoding == null; i++) { switch (theResourceBody.charAt(i)) { case '<': encoding = EncodingEnum.XML; break; case '{': encoding = EncodingEnum.JSON; break; } } if (encoding == null) { throw new InvalidRequestException("FHIR client can't determine resource encoding"); } return encoding.newParser(myContext).parseResource(theResourceBody); }
@Override public T invokeClient( String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException { EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType); if (respType == null) { throw NonFhirResponseException.newInstance( theResponseStatusCode, theResponseMimeType, theResponseReader); } IParser parser = respType.newParser(myContext); T retVal = parser.parseResource(myType, theResponseReader); if (myId != null) { retVal.setId(myId); } MethodUtil.parseClientRequestResourceHeaders(theHeaders, retVal); return retVal; }
@Override public OperationOutcome invokeClient( String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException { EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType); if (respType == null) { return null; } IParser parser = respType.newParser(myContext); OperationOutcome retVal; try { retVal = parser.parseResource(OperationOutcome.class, theResponseReader); } catch (DataFormatException e) { ourLog.warn("Failed to parse OperationOutcome response", e); return null; } MethodUtil.parseClientRequestResourceHeaders(theHeaders, retVal); return retVal; }
private String parseNarrative( HomeRequest theRequest, EncodingEnum theCtEnum, String theResultBody) { try { IBaseResource par = theCtEnum.newParser(getContext(theRequest)).parseResource(theResultBody); String retVal; if (par instanceof IResource) { IResource resource = (IResource) par; retVal = resource.getText().getDiv().getValueAsString(); } else if (par instanceof IDomainResource) { retVal = ((IDomainResource) par).getText().getDivAsString(); } else { retVal = null; } return StringUtils.defaultString(retVal); } catch (Exception e) { ourLog.error("Failed to parse resource", e); return ""; } }
@Override public String lookup(String theKey) { /* * TODO: this method could be made more efficient through some sort of lookup map */ if ("operationType".equals(theKey)) { if (myRequestDetails.getRestOperationType() != null) { return myRequestDetails.getRestOperationType().getCode(); } return ""; } else if ("operationName".equals(theKey)) { if (myRequestDetails.getRestOperationType() != null) { switch (myRequestDetails.getRestOperationType()) { case EXTENDED_OPERATION_INSTANCE: case EXTENDED_OPERATION_SERVER: case EXTENDED_OPERATION_TYPE: return myRequestDetails.getOperation(); default: return ""; } } else { return ""; } } else if ("id".equals(theKey)) { if (myRequestDetails.getId() != null) { return myRequestDetails.getId().getValue(); } return ""; } else if ("servletPath".equals(theKey)) { return StringUtils.defaultString(myRequest.getServletPath()); } else if ("idOrResourceName".equals(theKey)) { if (myRequestDetails.getId() != null) { return myRequestDetails.getId().getValue(); } if (myRequestDetails.getResourceName() != null) { return myRequestDetails.getResourceName(); } return ""; } else if (theKey.equals("requestParameters")) { StringBuilder b = new StringBuilder(); for (Entry<String, String[]> next : myRequestDetails.getParameters().entrySet()) { for (String nextValue : next.getValue()) { if (b.length() == 0) { b.append('?'); } else { b.append('&'); } try { b.append(URLEncoder.encode(next.getKey(), "UTF-8")); b.append('='); b.append(URLEncoder.encode(nextValue, "UTF-8")); } catch (UnsupportedEncodingException e) { throw new ca.uhn.fhir.context.ConfigurationException("UTF-8 not supported", e); } } } return b.toString(); } else if (theKey.startsWith("requestHeader.")) { String val = myRequest.getHeader(theKey.substring("requestHeader.".length())); return StringUtils.defaultString(val); } else if (theKey.startsWith("remoteAddr")) { return StringUtils.defaultString(myRequest.getRemoteAddr()); } else if (theKey.equals("responseEncodingNoDefault")) { EncodingEnum encoding = RestfulServerUtils.determineResponseEncodingNoDefault( myRequestDetails, myRequestDetails.getServer().getDefaultResponseEncoding()); if (encoding != null) { return encoding.name(); } else { return ""; } } else if (theKey.equals("exceptionMessage")) { return myException != null ? myException.getMessage() : null; } else if (theKey.equals("requestUrl")) { return myRequest.getRequestURL().toString(); } else if (theKey.equals("requestVerb")) { return myRequest.getMethod(); } else if (theKey.equals("requestBodyFhir")) { String contentType = myRequest.getContentType(); if (isNotBlank(contentType)) { int colonIndex = contentType.indexOf(';'); if (colonIndex != -1) { contentType = contentType.substring(0, colonIndex); } contentType = contentType.trim(); EncodingEnum encoding = EncodingEnum.forContentType(contentType); if (encoding != null) { byte[] requestContents = myRequestDetails.loadRequestContents(); return new String(requestContents, Charsets.UTF_8); } } return ""; } return "!VAL!"; }
protected void processAndAddLastClientInvocation( GenericClient theClient, ResultType theResultType, ModelMap theModelMap, long theLatency, String outcomeDescription, CaptureInterceptor theInterceptor, HomeRequest theRequest) { try { HttpRequestBase lastRequest = theInterceptor.getLastRequest(); HttpResponse lastResponse = theInterceptor.getLastResponse(); String requestBody = null; String requestUrl = lastRequest != null ? lastRequest.getURI().toASCIIString() : null; String action = lastRequest != null ? lastRequest.getMethod() : null; String resultStatus = lastResponse != null ? lastResponse.getStatusLine().toString() : null; String resultBody = StringUtils.defaultString(theInterceptor.getLastResponseBody()); if (lastRequest instanceof HttpEntityEnclosingRequest) { HttpEntity entity = ((HttpEntityEnclosingRequest) lastRequest).getEntity(); if (entity.isRepeatable()) { requestBody = IOUtils.toString(entity.getContent()); } } ContentType ct = lastResponse != null ? ContentType.get(lastResponse.getEntity()) : null; String mimeType = ct != null ? ct.getMimeType() : null; EncodingEnum ctEnum = EncodingEnum.forContentType(mimeType); String narrativeString = ""; StringBuilder resultDescription = new StringBuilder(); Bundle bundle = null; IBaseResource riBundle = null; FhirContext context = getContext(theRequest); if (ctEnum == null) { resultDescription.append("Non-FHIR response"); } else { switch (ctEnum) { case JSON: if (theResultType == ResultType.RESOURCE) { narrativeString = parseNarrative(theRequest, ctEnum, resultBody); resultDescription.append("JSON resource"); } else if (theResultType == ResultType.BUNDLE) { resultDescription.append("JSON bundle"); if (context.getVersion().getVersion().isRi()) { riBundle = context.newJsonParser().parseResource(resultBody); } else { bundle = context.newJsonParser().parseBundle(resultBody); } } break; case XML: default: if (theResultType == ResultType.RESOURCE) { narrativeString = parseNarrative(theRequest, ctEnum, resultBody); resultDescription.append("XML resource"); } else if (theResultType == ResultType.BUNDLE) { resultDescription.append("XML bundle"); if (context.getVersion().getVersion().isRi()) { riBundle = context.newXmlParser().parseResource(resultBody); } else { bundle = context.newXmlParser().parseBundle(resultBody); } } break; } } resultDescription.append(" (").append(resultBody.length() + " bytes)"); Header[] requestHeaders = lastRequest != null ? applyHeaderFilters(lastRequest.getAllHeaders()) : new Header[0]; Header[] responseHeaders = lastResponse != null ? applyHeaderFilters(lastResponse.getAllHeaders()) : new Header[0]; theModelMap.put("outcomeDescription", outcomeDescription); theModelMap.put("resultDescription", resultDescription.toString()); theModelMap.put("action", action); theModelMap.put("bundle", bundle); theModelMap.put("riBundle", riBundle); theModelMap.put("resultStatus", resultStatus); theModelMap.put("requestUrl", requestUrl); theModelMap.put("requestUrlText", formatUrl(theClient.getUrlBase(), requestUrl)); String requestBodyText = format(requestBody, ctEnum); theModelMap.put("requestBody", requestBodyText); String resultBodyText = format(resultBody, ctEnum); theModelMap.put("resultBody", resultBodyText); theModelMap.put("resultBodyIsLong", resultBodyText.length() > 1000); theModelMap.put("requestHeaders", requestHeaders); theModelMap.put("responseHeaders", responseHeaders); theModelMap.put("narrative", narrativeString); theModelMap.put("latencyMs", theLatency); } catch (Exception e) { ourLog.error("Failure during processing", e); theModelMap.put("errorMsg", "Error during processing: " + e.getMessage()); } }
<T> T invokeClient( FhirContext theContext, IClientResponseHandler<T> binding, BaseHttpClientInvocation clientInvocation, EncodingEnum theEncoding, Boolean thePrettyPrint, boolean theLogRequestAndResponse) { if (!myDontValidateConformance) { myFactory.validateServerBaseIfConfiguredToDoSo(myUrlBase, myClient, this); } // TODO: handle non 2xx status codes by throwing the correct exception, // and ensure it's passed upwards HttpRequestBase httpRequest; HttpResponse response; try { Map<String, List<String>> params = createExtraParams(); if (theEncoding == EncodingEnum.XML) { params.put(Constants.PARAM_FORMAT, Collections.singletonList("xml")); } else if (theEncoding == EncodingEnum.JSON) { params.put(Constants.PARAM_FORMAT, Collections.singletonList("json")); } if (thePrettyPrint == Boolean.TRUE) { params.put( Constants.PARAM_PRETTY, Collections.singletonList(Constants.PARAM_PRETTY_VALUE_TRUE)); } EncodingEnum encoding = getEncoding(); if (theEncoding != null) { encoding = theEncoding; } httpRequest = clientInvocation.asHttpRequest(myUrlBase, params, encoding, thePrettyPrint); if (theLogRequestAndResponse) { ourLog.info("Client invoking: {}", httpRequest); if (httpRequest instanceof HttpEntityEnclosingRequest) { HttpEntity entity = ((HttpEntityEnclosingRequest) httpRequest).getEntity(); if (entity.isRepeatable()) { String content = IOUtils.toString(entity.getContent()); ourLog.info("Client request body: {}", content); } } } for (IClientInterceptor nextInterceptor : myInterceptors) { nextInterceptor.interceptRequest(httpRequest); } response = myClient.execute(httpRequest); for (IClientInterceptor nextInterceptor : myInterceptors) { nextInterceptor.interceptResponse(response); } } catch (DataFormatException e) { throw new FhirClientConnectionException(e); } catch (IOException e) { throw new FhirClientConnectionException(e); } try { String mimeType; if (Constants.STATUS_HTTP_204_NO_CONTENT == response.getStatusLine().getStatusCode()) { mimeType = null; } else { ContentType ct = ContentType.get(response.getEntity()); mimeType = ct != null ? ct.getMimeType() : null; } Map<String, List<String>> headers = new HashMap<String, List<String>>(); if (response.getAllHeaders() != null) { for (Header next : response.getAllHeaders()) { String name = next.getName().toLowerCase(); List<String> list = headers.get(name); if (list == null) { list = new ArrayList<String>(); headers.put(name, list); } list.add(next.getValue()); } } if (response.getStatusLine().getStatusCode() < 200 || response.getStatusLine().getStatusCode() > 299) { String body = null; Reader reader = null; try { reader = createReaderFromResponse(response); body = IOUtils.toString(reader); } catch (Exception e) { ourLog.debug("Failed to read input stream", e); } finally { IOUtils.closeQuietly(reader); } String message = "HTTP " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase(); BaseOperationOutcome oo = null; if (Constants.CT_TEXT.equals(mimeType)) { message = message + ": " + body; } else { EncodingEnum enc = EncodingEnum.forContentType(mimeType); if (enc != null) { IParser p = enc.newParser(theContext); try { // TODO: handle if something other than OO comes back oo = (BaseOperationOutcome) p.parseResource(body); if (oo.getIssueFirstRep().getDetailsElement().isEmpty() == false) { message = message + ": " + oo.getIssueFirstRep().getDetailsElement().getValue(); } } catch (Exception e) { ourLog.debug("Failed to process OperationOutcome response"); } } } keepResponseAndLogIt(theLogRequestAndResponse, response, body); BaseServerResponseException exception = BaseServerResponseException.newInstance( response.getStatusLine().getStatusCode(), message); exception.setOperationOutcome(oo); if (body != null) { exception.setResponseBody(body); } throw exception; } if (binding instanceof IClientResponseHandlerHandlesBinary) { IClientResponseHandlerHandlesBinary<T> handlesBinary = (IClientResponseHandlerHandlesBinary<T>) binding; if (handlesBinary.isBinary()) { InputStream reader = response.getEntity().getContent(); try { if (ourLog.isTraceEnabled() || myKeepResponses || theLogRequestAndResponse) { byte[] responseBytes = IOUtils.toByteArray(reader); if (myKeepResponses) { myLastResponse = response; myLastResponseBody = null; } String message = "HTTP " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase(); if (theLogRequestAndResponse) { ourLog.info("Client response: {} - {} bytes", message, responseBytes.length); } else { ourLog.trace("Client response: {} - {} bytes", message, responseBytes.length); } reader = new ByteArrayInputStream(responseBytes); } return handlesBinary.invokeClient( mimeType, reader, response.getStatusLine().getStatusCode(), headers); } finally { IOUtils.closeQuietly(reader); } } } Reader reader = createReaderFromResponse(response); if (ourLog.isTraceEnabled() || myKeepResponses || theLogRequestAndResponse) { String responseString = IOUtils.toString(reader); keepResponseAndLogIt(theLogRequestAndResponse, response, responseString); reader = new StringReader(responseString); } try { return binding.invokeClient( mimeType, reader, response.getStatusLine().getStatusCode(), headers); } finally { IOUtils.closeQuietly(reader); } } catch (IllegalStateException e) { throw new FhirClientConnectionException(e); } catch (IOException e) { throw new FhirClientConnectionException(e); } finally { if (response instanceof CloseableHttpResponse) { try { ((CloseableHttpResponse) response).close(); } catch (IOException e) { ourLog.debug("Failed to close response", e); } } } }