001/* 002 * #%L 003 * HAPI FHIR - Client Framework 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.rest.client.apache; 021 022import ca.uhn.fhir.i18n.Msg; 023import ca.uhn.fhir.rest.client.api.IHttpResponse; 024import ca.uhn.fhir.rest.client.impl.BaseHttpResponse; 025import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 026import ca.uhn.fhir.util.StopWatch; 027import org.apache.commons.io.IOUtils; 028import org.apache.http.client.methods.CloseableHttpResponse; 029 030import java.io.ByteArrayInputStream; 031import java.io.IOException; 032import java.io.InputStream; 033import java.io.InputStreamReader; 034import java.io.Reader; 035import java.nio.charset.StandardCharsets; 036import java.util.List; 037import java.util.Map; 038 039/** 040 * Process a modified copy of an existing {@link IHttpResponse} with a String containing new content. 041 * <p/> 042 * Meant to be used with custom interceptors that need to hijack an existing IHttpResponse with new content. 043 */ 044public class ModifiedStringApacheHttpResponse extends BaseHttpResponse implements IHttpResponse { 045 private static final org.slf4j.Logger ourLog = 046 org.slf4j.LoggerFactory.getLogger(ModifiedStringApacheHttpResponse.class); 047 private boolean myEntityBuffered = false; 048 private final String myNewContent; 049 private final IHttpResponse myOrigHttpResponse; 050 private byte[] myEntityBytes = null; 051 052 public ModifiedStringApacheHttpResponse( 053 IHttpResponse theOrigHttpResponse, String theNewContent, StopWatch theResponseStopWatch) { 054 super(theResponseStopWatch); 055 myOrigHttpResponse = theOrigHttpResponse; 056 myNewContent = theNewContent; 057 } 058 059 @Override 060 public void bufferEntity() throws IOException { 061 if (myEntityBuffered) { 062 return; 063 } 064 try (InputStream respEntity = readEntity()) { 065 if (respEntity != null) { 066 try { 067 myEntityBytes = IOUtils.toByteArray(respEntity); 068 } catch (IllegalStateException exception) { 069 throw new InternalErrorException(Msg.code(2447) + exception); 070 } 071 myEntityBuffered = true; 072 } 073 } 074 } 075 076 @Override 077 public void close() { 078 if (myOrigHttpResponse instanceof CloseableHttpResponse) { 079 try { 080 ((CloseableHttpResponse) myOrigHttpResponse).close(); 081 } catch (IOException exception) { 082 ourLog.debug("Failed to close response", exception); 083 } 084 } 085 } 086 087 @Override 088 public Reader createReader() throws IOException { 089 return new InputStreamReader(readEntity(), StandardCharsets.UTF_8); 090 } 091 092 @Override 093 public Map<String, List<String>> getAllHeaders() { 094 return myOrigHttpResponse.getAllHeaders(); 095 } 096 097 @Override 098 public List<String> getHeaders(String theName) { 099 return myOrigHttpResponse.getHeaders(theName); 100 } 101 102 @Override 103 public String getMimeType() { 104 return myOrigHttpResponse.getMimeType(); 105 } 106 107 @Override 108 public StopWatch getRequestStopWatch() { 109 return myOrigHttpResponse.getRequestStopWatch(); 110 } 111 112 @Override 113 public Object getResponse() { 114 return null; 115 } 116 117 @Override 118 public int getStatus() { 119 return myOrigHttpResponse.getStatus(); 120 } 121 122 @Override 123 public String getStatusInfo() { 124 return myOrigHttpResponse.getStatusInfo(); 125 } 126 127 @Override 128 public InputStream readEntity() { 129 if (myEntityBuffered) { 130 return new ByteArrayInputStream(myEntityBytes); 131 } else { 132 return new ByteArrayInputStream(myNewContent.getBytes()); 133 } 134 } 135}