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}