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 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!"; }
/** * This method is called for nested bundles (e.g. if we received a transaction with an entry that * was a GET search, this method is called on the bundle for the search result, that will be * placed in the outer bundle). This method applies the _summary and _content parameters to the * output of that bundle. * * <p>TODO: This isn't the most efficient way of doing this.. hopefully we can come up with * something better in the future. */ private IBaseResource filterNestedBundle( RequestDetails theRequestDetails, IBaseResource theResource) { IParser p = getContext().newJsonParser(); RestfulServerUtils.configureResponseParser(theRequestDetails, p); return p.parseResource(theResource.getClass(), p.encodeResourceToString(theResource)); }
private Object returnResponse( IRestfulServer<?> theServer, RequestDetails theRequest, MethodOutcome response, IBaseResource originalOutcome, IBaseResource resource) throws IOException { boolean allowPrefer = false; int operationStatus = getOperationStatus(response); IBaseResource outcome = originalOutcome; if (ourOperationsWhichAllowPreferHeader.contains(getRestOperationType())) { allowPrefer = true; } if (resource != null && allowPrefer) { String prefer = theRequest.getHeader(Constants.HEADER_PREFER); PreferReturnEnum preferReturn = RestfulServerUtils.parsePreferHeader(prefer); if (preferReturn != null) { if (preferReturn == PreferReturnEnum.REPRESENTATION) { outcome = resource; } } } for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) { IServerInterceptor next = theServer.getInterceptors().get(i); boolean continueProcessing = next.outgoingResponse(theRequest, outcome); if (!continueProcessing) { return null; } } IRestfulResponse restfulResponse = theRequest.getResponse(); if (response != null) { if (response.getResource() != null) { restfulResponse.setOperationResourceLastUpdated( RestfulServerUtils.extractLastUpdatedFromResource(response.getResource())); } IIdType responseId = response.getId(); if (responseId != null && responseId.getResourceType() == null && responseId.hasIdPart()) { responseId = responseId.withResourceType(getResourceName()); } if (responseId != null) { String serverBase = theRequest.getFhirServerBase(); responseId = RestfulServerUtils.fullyQualifyResourceIdOrReturnNull( theServer, resource, serverBase, responseId); restfulResponse.setOperationResourceId(responseId); } } boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest); Set<SummaryEnum> summaryMode = Collections.emptySet(); return restfulResponse.streamResponseAsResource( outcome, prettyPrint, summaryMode, operationStatus, null, theRequest.isRespondGzip(), true); // return theRequest.getResponse().returnResponse(ParseAction.create(outcome), operationStatus, // allowPrefer, response, getResourceName()); }
@Override public void invokeServer(RestfulServer theServer, Request theRequest) throws BaseServerResponseException, IOException { // Pretty print boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest); // Narrative mode NarrativeModeEnum narrativeMode = RestfulServerUtils.determineNarrativeMode(theRequest); // Determine response encoding EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest.getServletRequest()); // Is this request coming from a browser String uaHeader = theRequest.getServletRequest().getHeader("user-agent"); boolean requestIsBrowser = false; if (uaHeader != null && uaHeader.contains("Mozilla")) { requestIsBrowser = true; } Object requestObject = parseRequestObject(theRequest); // Method params Object[] params = new Object[getParameters().size()]; for (int i = 0; i < getParameters().size(); i++) { IParameter param = getParameters().get(i); if (param != null) { params[i] = param.translateQueryParametersIntoServerArgument(theRequest, requestObject); } } Object resultObj = invokeServer(theRequest, params); Integer count = RestfulServerUtils.extractCountParameter(theRequest.getServletRequest()); boolean respondGzip = theRequest.isRespondGzip(); HttpServletResponse response = theRequest.getServletResponse(); switch (getReturnType()) { case BUNDLE: { if (getMethodReturnType() == MethodReturnTypeEnum.BUNDLE_RESOURCE) { IResource resource; if (resultObj instanceof IBundleProvider) { IBundleProvider result = (IBundleProvider) resultObj; resource = result.getResources(0, 1).get(0); } else { resource = (IResource) resultObj; } /* * We assume that the bundle we got back from the handling method may not have everything populated * (e.g. self links, bundle type, etc) so we do that here. */ IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory(); bundleFactory.initializeWithBundleResource(resource); bundleFactory.addRootPropertiesToBundle( null, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), count, getResponseBundleType()); for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) { IServerInterceptor next = theServer.getInterceptors().get(i); boolean continueProcessing = next.outgoingResponse( theRequest, resource, theRequest.getServletRequest(), theRequest.getServletResponse()); if (!continueProcessing) { ourLog.debug("Interceptor {} returned false, not continuing processing"); return; } } RestfulServerUtils.streamResponseAsResource( theServer, response, resource, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, respondGzip, theRequest.getFhirServerBase(), isAddContentLocationHeader()); break; } else { Set<Include> includes = getRequestIncludesFromParams(params); IBundleProvider result = (IBundleProvider) resultObj; if (count == null) { count = result.preferredPageSize(); } IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory(); bundleFactory.initializeBundleFromBundleProvider( theServer, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, 0, count, null, getResponseBundleType(), includes); Bundle bundle = bundleFactory.getDstu1Bundle(); if (bundle != null) { for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) { IServerInterceptor next = theServer.getInterceptors().get(i); boolean continueProcessing = next.outgoingResponse( theRequest, bundle, theRequest.getServletRequest(), theRequest.getServletResponse()); if (!continueProcessing) { ourLog.debug("Interceptor {} returned false, not continuing processing"); return; } } RestfulServerUtils.streamResponseAsBundle( theServer, response, bundle, responseEncoding, theRequest.getFhirServerBase(), prettyPrint, narrativeMode, respondGzip, requestIsBrowser); } else { IBaseResource resBundle = bundleFactory.getResourceBundle(); for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) { IServerInterceptor next = theServer.getInterceptors().get(i); boolean continueProcessing = next.outgoingResponse( theRequest, resBundle, theRequest.getServletRequest(), theRequest.getServletResponse()); if (!continueProcessing) { ourLog.debug("Interceptor {} returned false, not continuing processing"); return; } } RestfulServerUtils.streamResponseAsResource( theServer, response, (IResource) resBundle, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, theRequest.isRespondGzip(), theRequest.getFhirServerBase(), isAddContentLocationHeader()); } break; } } case RESOURCE: { IBundleProvider result = (IBundleProvider) resultObj; if (result.size() == 0) { throw new ResourceNotFoundException(theRequest.getId()); } else if (result.size() > 1) { throw new InternalErrorException("Method returned multiple resources"); } IResource resource = result.getResources(0, 1).get(0); for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) { IServerInterceptor next = theServer.getInterceptors().get(i); boolean continueProcessing = next.outgoingResponse( theRequest, resource, theRequest.getServletRequest(), theRequest.getServletResponse()); if (!continueProcessing) { return; } } RestfulServerUtils.streamResponseAsResource( theServer, response, resource, responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, Constants.STATUS_HTTP_200_OK, respondGzip, theRequest.getFhirServerBase(), isAddContentLocationHeader()); break; } } }