001package ca.uhn.fhir.okhttp.client;
002
003import java.io.*;
004import java.util.List;
005import java.util.Map;
006
007import ca.uhn.fhir.rest.client.impl.BaseHttpResponse;
008import ca.uhn.fhir.util.StopWatch;
009import org.apache.commons.io.IOUtils;
010
011import ca.uhn.fhir.rest.api.Constants;
012
013/*
014 * #%L
015 * HAPI FHIR OkHttp Client
016 * %%
017 * Copyright (C) 2014 - 2021 Smile CDR, Inc.
018 * %%
019 * Licensed under the Apache License, Version 2.0 (the "License");
020 * you may not use this file except in compliance with the License.
021 * You may obtain a copy of the License at
022 *
023 * http://www.apache.org/licenses/LICENSE-2.0
024 *
025 * Unless required by applicable law or agreed to in writing, software
026 * distributed under the License is distributed on an "AS IS" BASIS,
027 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
028 * See the License for the specific language governing permissions and
029 * limitations under the License.
030 * #L%
031 */
032
033import ca.uhn.fhir.rest.client.api.IHttpResponse;
034import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
035import okhttp3.MediaType;
036import okhttp3.Response;
037
038/**
039 * Wraps an OkHttp {@link Response}
040 *
041 * @author Matthew Clarke | matthew.clarke@orionhealth.com | Orion Health
042 */
043public class OkHttpRestfulResponse extends BaseHttpResponse implements IHttpResponse {
044
045        private boolean myEntityBuffered = false;
046        private byte[] myEntityBytes;
047        private Response myResponse;
048
049        public OkHttpRestfulResponse(Response theResponse, StopWatch theResponseStopWatch) {
050                super(theResponseStopWatch);
051                this.myResponse = theResponse;
052        }
053
054        @Override
055        public void bufferEntity() throws IOException {
056                if (myEntityBuffered) {
057                        return;
058                }
059                try (InputStream responseEntity = readEntity()) {
060                        if (responseEntity != null) {
061                                myEntityBuffered = true;
062                                try {
063                                        myEntityBytes = IOUtils.toByteArray(responseEntity);
064                                } catch (IllegalStateException e) {
065                                        throw new InternalErrorException(e);
066                                }
067                        }
068                }
069        }
070
071        @Override
072        public void close() {
073                myResponse.close();
074        }
075
076        @Override
077        public Reader createReader() throws IOException {
078                if (!myEntityBuffered && myResponse.body() == null) {
079                        return new StringReader("");
080                } else {
081                        return new InputStreamReader(readEntity());
082                }
083        }
084
085        @Override
086        public Map<String, List<String>> getAllHeaders() {
087                return myResponse.headers().toMultimap();
088        }
089
090        @Override
091        public List<String> getHeaders(String theName) {
092                return myResponse.headers(theName);
093        }
094
095        @Override
096        public String getMimeType() {
097                String contentType = myResponse.header(Constants.HEADER_CONTENT_TYPE);
098                MediaType mediaType = null;
099                if (contentType == null) {
100                        if (myResponse.body() != null) {
101                                mediaType = myResponse.body().contentType();
102                        }
103                } else {
104                        mediaType = MediaType.parse(contentType);
105                }
106
107                if (mediaType == null) {
108                        return null;
109                }
110
111                return typeAndSubtypeOnly(mediaType).toString();
112        }
113
114        @Override
115        public Object getResponse() {
116                return myResponse;
117        }
118
119        @Override
120        public int getStatus() {
121                return myResponse.code();
122        }
123
124        @Override
125        public String getStatusInfo() {
126                return myResponse.message();
127        }
128
129        @Override
130        public InputStream readEntity() throws IOException {
131                if (this.myEntityBuffered) {
132                        return new ByteArrayInputStream(myEntityBytes);
133                } else if (myResponse.body() != null) {
134                        return myResponse.body().byteStream();
135                } else {
136                        return null;
137                }
138        }
139
140        private MediaType typeAndSubtypeOnly(MediaType input) {
141                return MediaType.parse(input.type() + "/" + input.subtype());
142        }
143
144}