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; 021 022import jakarta.servlet.ServletContext; 023import jakarta.servlet.http.HttpServletRequest; 024import org.apache.commons.lang3.StringUtils; 025 026/** 027 * Determines the server's base using the incoming request 028 */ 029public class IncomingRequestAddressStrategy implements IServerAddressStrategy { 030 031 private String myServletPath; 032 033 @Override 034 public String determineServerBase(ServletContext theServletContext, HttpServletRequest theRequest) { 035 if (theRequest == null) { 036 return null; 037 } 038 String requestFullPath = StringUtils.defaultString(theRequest.getRequestURI()); 039 040 String servletPath; 041 if (myServletPath != null) { 042 servletPath = myServletPath; 043 } else { 044 servletPath = StringUtils.defaultString(theRequest.getServletPath()); 045 } 046 047 StringBuffer requestUrl = theRequest.getRequestURL(); 048 String servletContextPath = StringUtils.defaultString(theRequest.getContextPath()); 049 050 String requestPath = requestFullPath.substring(servletContextPath.length() + servletPath.length()); 051 if (requestPath.length() > 0 && requestPath.charAt(0) == '/') { 052 requestPath = requestPath.substring(1); 053 } 054 055 int startOfPath = requestUrl.indexOf("//"); 056 int requestUrlLength = requestUrl.length(); 057 058 if (startOfPath != -1 && (startOfPath + 2) < requestUrlLength) { 059 startOfPath = requestUrl.indexOf("/", startOfPath + 2); 060 } 061 if (startOfPath == -1) { 062 startOfPath = 0; 063 } 064 065 int contextIndex; 066 if (servletPath.length() == 0 || servletPath.equals("/")) { 067 if (requestPath.length() == 0) { 068 contextIndex = requestUrlLength; 069 } else { 070 contextIndex = requestUrl.indexOf(requestPath, startOfPath); 071 } 072 } else { 073 // servletContextPath can start with servletPath 074 contextIndex = requestUrl.indexOf(servletPath + "/", startOfPath); 075 if (contextIndex == -1) { 076 contextIndex = requestUrl.indexOf(servletPath, startOfPath); 077 } 078 } 079 080 String fhirServerBase; 081 int length = contextIndex + servletPath.length(); 082 if (length > requestUrlLength) { 083 length = requestUrlLength; 084 } 085 fhirServerBase = requestUrl.substring(0, length); 086 return fhirServerBase; 087 } 088 089 /** 090 * If set to a non-null value (default is <code>null</code>), this address strategy assumes that the FHIR endpoint is deployed to the given servlet path within the context. This is useful in some 091 * deployments where it isn't obvious to the servlet which part of the path is actually the root path to reach the servlet. 092 * <p> 093 * Example values could be: 094 * <ul> 095 * <li>null</li> 096 * <li>/</li> 097 * <li>/base</li> 098 * </ul> 099 * </p> 100 * <p> 101 * <b>Wildcards are not supported!</b> 102 * </p> 103 */ 104 public void setServletPath(String theServletPath) { 105 myServletPath = theServletPath; 106 } 107}