001package ca.uhn.fhir.rest.server.servlet; 002 003/* 004 * #%L 005 * HAPI FHIR - Server Framework 006 * %% 007 * Copyright (C) 2014 - 2022 Smile CDR, Inc. 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import ca.uhn.fhir.rest.api.Constants; 024import ca.uhn.fhir.rest.api.MethodOutcome; 025import ca.uhn.fhir.rest.api.server.ParseAction; 026import ca.uhn.fhir.rest.server.RestfulResponse; 027import org.hl7.fhir.instance.model.api.IBaseBinary; 028 029import javax.servlet.ServletOutputStream; 030import javax.servlet.http.HttpServletResponse; 031import java.io.IOException; 032import java.io.OutputStream; 033import java.io.OutputStreamWriter; 034import java.io.Writer; 035import java.nio.charset.StandardCharsets; 036import java.util.List; 037import java.util.Map.Entry; 038import java.util.zip.GZIPOutputStream; 039 040public class ServletRestfulResponse extends RestfulResponse<ServletRequestDetails> { 041 042 /** 043 * Constructor 044 */ 045 public ServletRestfulResponse(ServletRequestDetails servletRequestDetails) { 046 super(servletRequestDetails); 047 } 048 049 @Override 050 public OutputStream sendAttachmentResponse(IBaseBinary theBinary, int theStatusCode, String contentType) throws IOException { 051 addHeaders(); 052 HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse(); 053 theHttpResponse.setStatus(theStatusCode); 054 theHttpResponse.setContentType(contentType); 055 theHttpResponse.setCharacterEncoding(null); 056 if (theBinary.getContent() == null || theBinary.getContent().length == 0) { 057 return theHttpResponse.getOutputStream(); 058 } 059 theHttpResponse.setContentLength(theBinary.getContent().length); 060 ServletOutputStream oos = theHttpResponse.getOutputStream(); 061 oos.write(theBinary.getContent()); 062 return oos; 063 } 064 065 @Override 066 public Writer getResponseWriter(int theStatusCode, String theStatusMessage, String theContentType, String theCharset, boolean theRespondGzip) throws IOException { 067 addHeaders(); 068 HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse(); 069 theHttpResponse.setCharacterEncoding(theCharset); 070 theHttpResponse.setStatus(theStatusCode); 071 theHttpResponse.setContentType(theContentType); 072 if (theRespondGzip) { 073 theHttpResponse.addHeader(Constants.HEADER_CONTENT_ENCODING, Constants.ENCODING_GZIP); 074 return new OutputStreamWriter(new GZIPOutputStream(theHttpResponse.getOutputStream()), StandardCharsets.UTF_8); 075 } 076 return theHttpResponse.getWriter(); 077 } 078 079 private void addHeaders() { 080 HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse(); 081 getRequestDetails().getServer().addHeadersToResponse(theHttpResponse); 082 for (Entry<String, List<String>> header : getHeaders().entrySet()) { 083 final String key = header.getKey(); 084 boolean first = true; 085 for (String value : header.getValue()) { 086 // existing headers should be overridden 087 if (first) { 088 theHttpResponse.setHeader(key, value); 089 first = false; 090 } else { 091 theHttpResponse.addHeader(key, value); 092 } 093 } 094 } 095 } 096 097 @Override 098 public final Writer sendWriterResponse(int theStatus, String theContentType, String theCharset, Writer theWriter) { 099 return theWriter; 100 } 101 102 @Override 103 public Object returnResponse(ParseAction<?> outcome, int operationStatus, boolean allowPrefer, MethodOutcome response, String resourceName) throws IOException { 104 addHeaders(); 105 return getRequestDetails().getServer().returnResponse(getRequestDetails(), outcome, operationStatus, allowPrefer, response, resourceName); 106 } 107}