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