001/*-
002 * #%L
003 * HAPI FHIR - Server 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.server.interceptor;
021
022import ca.uhn.fhir.context.FhirContext;
023import ca.uhn.fhir.interceptor.api.Hook;
024import ca.uhn.fhir.interceptor.api.Interceptor;
025import ca.uhn.fhir.interceptor.api.Pointcut;
026import ca.uhn.fhir.rest.api.Constants;
027import ca.uhn.fhir.rest.api.server.RequestDetails;
028import ca.uhn.fhir.util.MetaUtil;
029import org.hl7.fhir.instance.model.api.IBaseResource;
030import org.slf4j.Logger;
031import org.slf4j.LoggerFactory;
032
033import static org.apache.commons.lang3.StringUtils.isNotBlank;
034
035/**
036 * This interceptor examines a header on the incoming request and places it in
037 * <code>Resource.meta.source</code> (R4 and above) or in an extension on <code>Resource.meta</code>
038 * with the URL <code>http://hapifhir.io/fhir/StructureDefinition/resource-meta-source</code> (DSTU3).
039 * <p>
040 * This interceptor does not support versions of FHIR below DSTU3.
041 * </p>
042 *
043 * @see <a href="http://hl7.org/fhir/resource-definitions.html#Resource.meta">Meta.source</a>
044 */
045@Interceptor
046public class CaptureResourceSourceFromHeaderInterceptor {
047
048        private static final Logger ourLog = LoggerFactory.getLogger(CaptureResourceSourceFromHeaderInterceptor.class);
049        private final FhirContext myFhirContext;
050        private String myHeaderName;
051
052        public CaptureResourceSourceFromHeaderInterceptor(FhirContext theFhirContext) {
053                myFhirContext = theFhirContext;
054                setHeaderName(Constants.HEADER_REQUEST_SOURCE);
055        }
056
057        /**
058         * Provides the header name to examine in incoming requests. Default is {@link ca.uhn.fhir.rest.api.Constants#HEADER_REQUEST_SOURCE "X-Request-Source"}.
059         */
060        @SuppressWarnings("WeakerAccess")
061        public String getHeaderName() {
062                return myHeaderName;
063        }
064
065        /**
066         * Provides the header name to examine in incoming requests. Default is {@link ca.uhn.fhir.rest.api.Constants#HEADER_REQUEST_SOURCE "X-Request-Source"}.
067         */
068        @SuppressWarnings("WeakerAccess")
069        public void setHeaderName(String theHeaderName) {
070                myHeaderName = theHeaderName;
071        }
072
073        @Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED)
074        public void extractSource(RequestDetails theRequestDetails) {
075                IBaseResource resource = theRequestDetails.getResource();
076                if (resource != null) {
077                        String requestSource = theRequestDetails.getHeader(getHeaderName());
078                        if (isNotBlank(requestSource)) {
079                                ourLog.trace("Setting Meta.source to \"{}\" because of header \"{}\"", requestSource, getHeaderName());
080                                MetaUtil.setSource(myFhirContext, resource, requestSource);
081                        }
082                }
083        }
084}