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}