001package ca.uhn.fhir.rest.server.servlet;
002
003/*
004 * #%L
005 * HAPI FHIR - Server Framework
006 * %%
007 * Copyright (C) 2014 - 2021 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.context.FhirContext;
024import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
025import ca.uhn.fhir.rest.api.Constants;
026import ca.uhn.fhir.rest.api.server.RequestDetails;
027import ca.uhn.fhir.rest.server.RestfulServer;
028import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
029import org.apache.commons.io.IOUtils;
030import org.apache.commons.lang3.Validate;
031
032import javax.servlet.http.HttpServletRequest;
033import javax.servlet.http.HttpServletResponse;
034import java.io.ByteArrayInputStream;
035import java.io.IOException;
036import java.io.InputStream;
037import java.io.Reader;
038import java.nio.charset.Charset;
039import java.util.*;
040import java.util.zip.GZIPInputStream;
041
042import static org.apache.commons.lang3.StringUtils.isNotBlank;
043
044public class ServletRequestDetails extends RequestDetails {
045
046        private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServletRequestDetails.class);
047
048        private RestfulServer myServer;
049        private HttpServletRequest myServletRequest;
050        private HttpServletResponse myServletResponse;
051
052        /**
053         * Constructor for testing only
054         */
055        public ServletRequestDetails() {
056                this((IInterceptorBroadcaster)null);
057        }
058
059        /**
060         * Constructor
061         */
062        public ServletRequestDetails(IInterceptorBroadcaster theInterceptorBroadcaster) {
063                super(theInterceptorBroadcaster);
064                setResponse(new ServletRestfulResponse(this));
065        }
066
067        /**
068         * Copy constructor
069         */
070        public ServletRequestDetails(ServletRequestDetails theRequestDetails) {
071                super(theRequestDetails);
072
073                myServer = theRequestDetails.getServer();
074                myServletRequest = theRequestDetails.getServletRequest();
075                myServletResponse = theRequestDetails.getServletResponse();
076        }
077
078        @Override
079        protected byte[] getByteStreamRequestContents() {
080                try {
081                        InputStream inputStream = getInputStream();
082                        byte[] requestContents = IOUtils.toByteArray(inputStream);
083
084                        if (myServer.isUncompressIncomingContents()) {
085                                String contentEncoding = myServletRequest.getHeader(Constants.HEADER_CONTENT_ENCODING);
086                                if ("gzip".equals(contentEncoding)) {
087                                        ourLog.debug("Uncompressing (GZip) incoming content");
088                                        if (requestContents.length > 0) {
089                                                GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(requestContents));
090                                                requestContents = IOUtils.toByteArray(gis);
091                                        }
092                                }
093                        }
094                        return requestContents;
095                } catch (IOException e) {
096                        ourLog.error("Could not load request resource", e);
097                        throw new InvalidRequestException(String.format("Could not load request resource: %s", e.getMessage()));
098                }
099        }
100
101        @Override
102        public Charset getCharset() {
103                Charset charset = null;
104
105                String charsetString = myServletRequest.getCharacterEncoding();
106                if (isNotBlank(charsetString)) {
107                        charset = Charset.forName(charsetString);
108                }
109
110                return charset;
111        }
112
113        @Override
114        public FhirContext getFhirContext() {
115                return getServer().getFhirContext();
116        }
117
118        @Override
119        public String getHeader(String name) {
120                return getServletRequest().getHeader(name);
121        }
122
123        @Override
124        public List<String> getHeaders(String name) {
125                Enumeration<String> headers = getServletRequest().getHeaders(name);
126                return headers == null ? Collections.emptyList() : Collections.list(getServletRequest().getHeaders(name));
127        }
128
129        @Override
130        public Object getAttribute(String theAttributeName) {
131                Validate.notBlank(theAttributeName, "theAttributeName must not be null or blank");
132                return getServletRequest().getAttribute(theAttributeName);
133        }
134
135        @Override
136        public void setAttribute(String theAttributeName, Object theAttributeValue) {
137                Validate.notBlank(theAttributeName, "theAttributeName must not be null or blank");
138                getServletRequest().setAttribute(theAttributeName, theAttributeValue);
139        }
140
141        @Override
142        public InputStream getInputStream() throws IOException {
143                return getServletRequest().getInputStream();
144        }
145
146        @Override
147        public Reader getReader() throws IOException {
148                return getServletRequest().getReader();
149        }
150
151        @Override
152        public RestfulServer getServer() {
153                return myServer;
154        }
155
156        @Override
157        public String getServerBaseForRequest() {
158                return getServer().getServerBaseForRequest(this);
159        }
160
161        public HttpServletRequest getServletRequest() {
162                return myServletRequest;
163        }
164
165        public HttpServletResponse getServletResponse() {
166                return myServletResponse;
167        }
168
169        public void setServer(RestfulServer theServer) {
170                this.myServer = theServer;
171        }
172
173        public ServletRequestDetails setServletRequest(HttpServletRequest myServletRequest) {
174                this.myServletRequest = myServletRequest;
175                return this;
176        }
177
178        public void setServletResponse(HttpServletResponse myServletResponse) {
179                this.myServletResponse = myServletResponse;
180        }
181
182        public Map<String,List<String>> getHeaders() {
183                Map<String, List<String>> retVal = new HashMap<>();
184                Enumeration<String> names = myServletRequest.getHeaderNames();
185                while (names.hasMoreElements()) {
186                        String nextName = names.nextElement();
187                        ArrayList<String> headerValues = new ArrayList<>();
188                        retVal.put(nextName, headerValues);
189                        Enumeration<String> valuesEnum = myServletRequest.getHeaders(nextName);
190                        while (valuesEnum.hasMoreElements()) {
191                                headerValues.add(valuesEnum.nextElement());
192                        }
193                }
194                return Collections.unmodifiableMap(retVal);
195        }
196}