001package ca.uhn.fhir.rest.client.interceptor;
002
003/*-
004 * #%L
005 * HAPI FHIR - Client 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.interceptor.api.Hook;
024import ca.uhn.fhir.interceptor.api.Pointcut;
025import ca.uhn.fhir.rest.client.api.IHttpRequest;
026import ca.uhn.fhir.rest.client.api.IRestfulClient;
027import ca.uhn.fhir.rest.client.api.UrlSourceEnum;
028import org.apache.commons.lang3.Validate;
029
030import static org.apache.commons.lang3.StringUtils.isBlank;
031
032/**
033 * This interceptor adds a path element representing the tenant ID to each client request. It is primarily
034 * intended to be used with clients that are accessing servers using
035 * <a href="https://hapifhir.io/hapi-fhir/docs/server_plain/multitenancy.html#url-base-multitenancy">URL Base Multitenancy</a>.
036 */
037public class UrlTenantSelectionInterceptor {
038
039        private String myTenantId;
040
041        /**
042         * Constructor
043         */
044        public UrlTenantSelectionInterceptor() {
045                this(null);
046        }
047
048        /**
049         * Constructor
050         *
051         * @param theTenantId The tenant ID to add to URL base
052         */
053        public UrlTenantSelectionInterceptor(String theTenantId) {
054                myTenantId = theTenantId;
055        }
056
057        /**
058         * Returns the tenant ID
059         */
060        public String getTenantId() {
061                return myTenantId;
062        }
063
064        /**
065         * Sets the tenant ID
066         */
067        public void setTenantId(String theTenantId) {
068                myTenantId = theTenantId;
069        }
070
071        @Hook(value = Pointcut.CLIENT_REQUEST, order = InterceptorOrders.URL_TENANT_SELECTION_INTERCEPTOR_REQUEST)
072        public void request(IRestfulClient theClient, IHttpRequest theRequest) {
073                String tenantId = getTenantId();
074                if (isBlank(tenantId)) {
075                        return;
076                }
077                String requestUri = theRequest.getUri();
078                String serverBase = theClient.getServerBase();
079                if (serverBase.endsWith("/")) {
080                        serverBase = serverBase.substring(0, serverBase.length() - 1);
081                }
082
083                Validate.isTrue(requestUri.startsWith(serverBase), "Request URI %s does not start with server base %s", requestUri, serverBase);
084
085                if (theRequest.getUrlSource() == UrlSourceEnum.EXPLICIT) {
086                        return;
087                }
088
089                String newUri = serverBase + "/" + tenantId + requestUri.substring(serverBase.length());
090                theRequest.setUri(newUri);
091        }
092
093}