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();
      }
    }
  }
示例#2
0
 @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);
 }
示例#3
0
 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);
 }
示例#4
0
    @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;
    }
示例#5
0
    @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());
    }
  }
示例#9
0
  <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);
        }
      }
    }
  }