diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 36708be7309..94da1bfc33f 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -105,6 +105,8 @@ Bug Fixes * SOLR-13921: Processing UpdateRequest with delegation token throws NullPointerException (Istvan Farkas via Kevin Risden) +* SOLR-13941: Tests configure Jetty differently than when running via start.jar (janhoy, Uwe Schindler) + Other Changes --------------------- diff --git a/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java b/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java index c1e8bc24fcf..7ee1c0823e7 100644 --- a/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java +++ b/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java @@ -16,6 +16,16 @@ */ package org.apache.solr.client.solrj.embedded; +import javax.servlet.DispatcherType; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.invoke.MethodHandles; import java.net.BindException; @@ -34,17 +44,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import javax.servlet.DispatcherType; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.apache.lucene.util.Constants; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.cloud.SocketProxy; @@ -112,7 +111,7 @@ public class JettySolrRunner { private LinkedList extraFilters; - private static final String excludePatterns = "/css/.+,/js/.+,/img/.+,/tpl/.+"; + private static final String excludePatterns = "/partials/.+,/libs/.+,/css/.+,/js/.+,/img/.+,/templates/.+"; private int proxyPort = -1; @@ -369,7 +368,7 @@ public class JettySolrRunner { log.info("Jetty properties: {}", nodeProperties); - debugFilter = root.addFilter(DebugFilter.class, "*", EnumSet.of(DispatcherType.REQUEST) ); + debugFilter = root.addFilter(DebugFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST) ); extraFilters = new LinkedList<>(); for (Map.Entry, String> entry : config.extraFilters.entrySet()) { extraFilters.add(root.addFilter(entry.getKey(), entry.getValue(), EnumSet.of(DispatcherType.REQUEST))); @@ -381,7 +380,8 @@ public class JettySolrRunner { dispatchFilter = root.getServletHandler().newFilterHolder(Source.EMBEDDED); dispatchFilter.setHeldClass(SolrDispatchFilter.class); dispatchFilter.setInitParameter("excludePatterns", excludePatterns); - root.addFilter(dispatchFilter, "*", EnumSet.of(DispatcherType.REQUEST)); + // Map dispatchFilter in same path as in web.xml + root.addFilter(dispatchFilter, "/*", EnumSet.of(DispatcherType.REQUEST)); synchronized (JettySolrRunner.this) { waitOnSolr = true; @@ -394,8 +394,8 @@ public class JettySolrRunner { System.clearProperty("hostPort"); } }); - // for some reason, there must be a servlet for this to get applied - root.addServlet(Servlet404.class, "/*"); + // Default servlet as a fall-through + root.addServlet(Servlet404.class, "/"); chain = root; } diff --git a/solr/core/src/java/org/apache/solr/security/AuditEvent.java b/solr/core/src/java/org/apache/solr/security/AuditEvent.java index 492384ee69a..4fee14bd185 100644 --- a/solr/core/src/java/org/apache/solr/security/AuditEvent.java +++ b/solr/core/src/java/org/apache/solr/security/AuditEvent.java @@ -31,6 +31,7 @@ import java.util.stream.Collectors; import org.apache.solr.common.SolrException; import org.apache.solr.common.cloud.ZkStateReader; +import org.apache.solr.servlet.ServletUtils; import org.apache.solr.servlet.SolrRequestParsers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -130,7 +131,7 @@ public class AuditEvent { this.solrPort = httpRequest.getLocalPort(); this.solrIp = httpRequest.getLocalAddr(); this.clientIp = httpRequest.getRemoteAddr(); - this.resource = httpRequest.getPathInfo(); + this.resource = ServletUtils.getPathAfterContext(httpRequest); this.httpMethod = httpRequest.getMethod(); this.httpQueryString = httpRequest.getQueryString(); this.headers = getHeadersFromRequest(httpRequest); diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java index 72f6fe32c98..9c1d3575629 100644 --- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java +++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java @@ -192,11 +192,7 @@ public class HttpSolrCall { req.setAttribute(SolrRequestParsers.REQUEST_TIMER_SERVLET_ATTRIBUTE, new RTimerTree()); // put the core container in request attribute req.setAttribute("org.apache.solr.CoreContainer", cores); - path = req.getServletPath(); - if (req.getPathInfo() != null) { - // this lets you handle /update/commit when /update is a servlet - path += req.getPathInfo(); - } + path = ServletUtils.getPathAfterContext(req); } public String getPath() { diff --git a/solr/core/src/java/org/apache/solr/servlet/ServletUtils.java b/solr/core/src/java/org/apache/solr/servlet/ServletUtils.java new file mode 100644 index 00000000000..e61831ac4e7 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/servlet/ServletUtils.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.servlet; + +import javax.servlet.http.HttpServletRequest; + +/** + * Various Util methods for interaction on servlet level, i.e. HttpServletRequest + */ +public abstract class ServletUtils { + private ServletUtils() { /* only static methods in this class */ } + + /** + * Use this to get the full path after context path "/solr", which is a combination of + * servletPath and pathInfo. + * @param request the HttpServletRequest object + * @return String with path starting with a "/", or empty string if no path + */ + public static String getPathAfterContext(HttpServletRequest request) { + return request.getServletPath() + (request.getPathInfo() != null ? request.getPathInfo() : ""); + } +} diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java index 3c3e26ff7eb..4ff013835d8 100644 --- a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java +++ b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java @@ -371,14 +371,9 @@ public class SolrDispatchFilter extends BaseSolrFilter { } } - String requestPath = request.getServletPath(); + String requestPath = ServletUtils.getPathAfterContext(request); // No need to even create the HttpSolrCall object if this path is excluded. if (excludePatterns != null) { - String extraPath = request.getPathInfo(); - if (extraPath != null) { - // In embedded mode, servlet path is empty - include all post-context path here for testing - requestPath += extraPath; - } for (Pattern p : excludePatterns) { Matcher matcher = p.matcher(requestPath); if (matcher.lookingAt()) { @@ -468,11 +463,7 @@ public class SolrDispatchFilter extends BaseSolrFilter { * want to add attributes to the request and send errors differently */ protected HttpSolrCall getHttpSolrCall(HttpServletRequest request, HttpServletResponse response, boolean retry) { - String path = request.getServletPath(); - if (request.getPathInfo() != null) { - // this lets you handle /update/commit when /update is a servlet - path += request.getPathInfo(); - } + String path = ServletUtils.getPathAfterContext(request); if (isV2Enabled && (path.startsWith("/____v2/") || path.equals("/____v2"))) { return new V2HttpCall(this, cores, request, response, false); @@ -492,11 +483,7 @@ public class SolrDispatchFilter extends BaseSolrFilter { return true; } else { // /admin/info/key must be always open. see SOLR-9188 - // tests work only w/ getPathInfo - //otherwise it's just enough to have getServletPath() - String requestPath = request.getPathInfo(); - if (requestPath == null) - requestPath = request.getServletPath(); + String requestPath = ServletUtils.getPathAfterContext(request); if (PublicKeyHandler.PATH.equals(requestPath)) { if (log.isDebugEnabled()) log.debug("Pass through PKI authentication endpoint"); diff --git a/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java index bafd6ca48a5..e9c09da2bcb 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java @@ -346,7 +346,7 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 { runner.stop(); } }); - assertTrue(rse.getMessage().contains("Can not find: /solr/corex/select")); + assertTrue(rse.getMessage(), rse.getMessage().contains("Problem accessing /solr/corex/select")); } @Test