From b1410f593a2d5c86b7fd1f64b534cff9264ef6a0 Mon Sep 17 00:00:00 2001 From: luccioman Date: Wed, 25 Jul 2018 08:03:25 +0200 Subject: [PATCH] Fixed stylesheet relative URLs rendering in Solr html writer Relative URLs to CSS stylesheets were not properly rendered when using the Solr html response writer and the "/solr/collection1/select" entry point instead of "/solr/select". --- .../responsewriter/HTMLResponseWriter.java | 84 ++++++++++++++----- .../yacy/http/servlets/SolrSelectServlet.java | 9 +- 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/source/net/yacy/cora/federate/solr/responsewriter/HTMLResponseWriter.java b/source/net/yacy/cora/federate/solr/responsewriter/HTMLResponseWriter.java index 5815f44da..79abef90e 100644 --- a/source/net/yacy/cora/federate/solr/responsewriter/HTMLResponseWriter.java +++ b/source/net/yacy/cora/federate/solr/responsewriter/HTMLResponseWriter.java @@ -60,6 +60,7 @@ import org.apache.solr.search.SolrReturnFields; import net.yacy.cora.federate.solr.SolrType; import net.yacy.cora.lod.vocabulary.DublinCore; +import net.yacy.cora.util.CommonPattern; import net.yacy.document.parser.html.CharacterCoding; import net.yacy.search.schema.CollectionSchema; import net.yacy.search.schema.WebgraphSchema; @@ -291,7 +292,7 @@ public class HTMLResponseWriter implements QueryResponseWriter, SolrjResponseWri assert values.get("responseHeader") != null; assert values.get("response") != null; - writeHtmlHead(writer); + writeHtmlHead(writer, request); final String coreName = request.getCore().getName(); @@ -308,6 +309,7 @@ public class HTMLResponseWriter implements QueryResponseWriter, SolrjResponseWri } else if(responseObj instanceof ResultContext){ /* Regular response object */ final DocList documents = ((ResultContext)responseObj).getDocList(); + final String rootPath = getRootPath(request); sz = documents.size(); @@ -327,14 +329,14 @@ public class HTMLResponseWriter implements QueryResponseWriter, SolrjResponseWri writeApiLink(writer, request.getOriginalParams(), coreName); - writeDoc(writer, tdoc, coreName, rsp.getReturnFields()); + writeDoc(writer, tdoc, coreName, rsp.getReturnFields(), rootPath); while (iterator.hasNext()) { id = iterator.nextDoc(); doc = searcher.doc(id); tdoc = translateDoc(schema, doc, rsp.getReturnFields()); - writeDoc(writer, tdoc, coreName, rsp.getReturnFields()); + writeDoc(writer, tdoc, coreName, rsp.getReturnFields(), rootPath); } } else { writer.write("No Document Found\n\n"); @@ -358,7 +360,7 @@ public class HTMLResponseWriter implements QueryResponseWriter, SolrjResponseWri @Override public void write(final Writer writer, final SolrQueryRequest request, final String coreName, final QueryResponse rsp) throws IOException { - writeHtmlHead(writer); + writeHtmlHead(writer, request); final SolrDocumentList docsList = rsp.getResults(); final NamedList responseHeader = rsp.getHeader(); @@ -381,6 +383,7 @@ public class HTMLResponseWriter implements QueryResponseWriter, SolrjResponseWri final NamedList responseHeader, final String coreName, final SolrDocumentList docList) throws IOException { final int sz = docList.size(); + final String rootPath = getRootPath(request); if (sz > 0) { final Iterator iterator = docList.iterator(); @@ -395,12 +398,12 @@ public class HTMLResponseWriter implements QueryResponseWriter, SolrjResponseWri writeApiLink(writer, request.getOriginalParams(), coreName); - writeDoc(writer, translateDoc(doc, fieldsToReturn), coreName, fieldsToReturn); + writeDoc(writer, translateDoc(doc, fieldsToReturn), coreName, fieldsToReturn, rootPath); while (iterator.hasNext()) { doc = iterator.next(); - writeDoc(writer, translateDoc(doc, fieldsToReturn), coreName, fieldsToReturn); + writeDoc(writer, translateDoc(doc, fieldsToReturn), coreName, fieldsToReturn, rootPath); } } else { writer.write("No Document Found\n\n"); @@ -438,7 +441,9 @@ public class HTMLResponseWriter implements QueryResponseWriter, SolrjResponseWri * @param writer must not be null * @throws IOException when a write error occurred */ - private void writeHtmlHead(final Writer writer) throws IOException { + private void writeHtmlHead(final Writer writer, final SolrQueryRequest request) throws IOException { + final String rootPath = getRootPath(request); + writer.write("\n"); //writer.write("\n"); - writer.write("\n"); - writer.write("\n"); - //writer.write("\n"); - //writer.write("\n"); - //writer.write("\n"); + writer.write("\n"); + writer.write("\n"); + //writer.write("\n"); + //writer.write("\n"); + //writer.write("\n"); writer.write("\n"); - writer.write("\n"); + writer.write("\n"); //writer.write("\n"); //writer.write("\n"); writer.write("\n"); - writer.write("\n"); - writer.write("\n"); + writer.write("\n"); + writer.write("\n"); writer.write("\n"); writer.write("\n"); writer.write("\n"); writer.write("\n"); } + + /** + * Compute the root path as a relative URL prefix from the original servlet + * request URI if provided in the Solr request context, otherwise return a + * regular "/". Using relative URLs when possible makes deployment behind a + * reverse proxy more reliable and convenient as no URL rewriting is needed. + * + * @param request the Solr request. Must not be null. + * @return the root context path to use as a prefix for resources URLs such as + * stylesheets + */ + private String getRootPath(final SolrQueryRequest request) { + String rootPath = "/"; + final Map context = request.getContext(); + if (context != null) { + final Object requestUriObj = context.get("requestURI"); + if (requestUriObj instanceof String) { + String servletRequestUri = (String) requestUriObj; + if(servletRequestUri.startsWith("/")) { + servletRequestUri = servletRequestUri.substring(1); + + final String[] pathParts = CommonPattern.SLASH.split(servletRequestUri); + if(pathParts.length > 1) { + final StringBuilder sb = new StringBuilder(); + for(int i = 1; i < pathParts.length; i++) { + sb.append("../"); + } + rootPath = sb.toString(); + } + } + } + } + return rootPath; + } @@ -490,9 +529,10 @@ public class HTMLResponseWriter implements QueryResponseWriter, SolrjResponseWri * @param coreName the Solr core name. * @param returnFields the eventual fields return configuration, allowing for example to * rename fields with a pseudo in the result. May be null. + * @param rootPath the path prefix to append to other resources URLs. Must not be null. * @throws IOException when a write error occurred. */ - private static final void writeDoc(final Writer writer, final LinkedHashMap tdoc, final String coreName, final ReturnFields returnFields) throws IOException { + private static final void writeDoc(final Writer writer, final LinkedHashMap tdoc, final String coreName, final ReturnFields returnFields, final String rootPath) throws IOException { String title; if(CollectionSchema.CORE_NAME.equals(coreName)) { title = tdoc.get(CollectionSchema.title.getSolrFieldName()); @@ -510,7 +550,7 @@ public class HTMLResponseWriter implements QueryResponseWriter, SolrjResponseWri if(CollectionSchema.CORE_NAME.equals(coreName)) { String sku = tdoc.get(CollectionSchema.sku.getSolrFieldName()); if(sku != null) { - final String jsc= "javascript:w = window.open('../QuickCrawlLink_p.html?indexText=on&indexMedia=on&crawlingQ=on&followFrames=on&obeyHtmlRobotsNoindex=on&obeyHtmlRobotsNofollow=off&xdstopw=on&title=" + URLEncoder.encode(title, StandardCharsets.UTF_8.name()) + "&url='+escape('"+sku+"'),'_blank','height=250,width=600,resizable=yes,scrollbar=no,directory=no,menubar=no,location=no');w.focus();"; + final String jsc= "javascript:w = window.open('" + rootPath + "QuickCrawlLink_p.html?indexText=on&indexMedia=on&crawlingQ=on&followFrames=on&obeyHtmlRobotsNoindex=on&obeyHtmlRobotsNofollow=off&xdstopw=on&title=" + URLEncoder.encode(title, StandardCharsets.UTF_8.name()) + "&url='+escape('"+sku+"'),'_blank','height=250,width=600,resizable=yes,scrollbar=no,directory=no,menubar=no,location=no');w.focus();"; writer.write("
re-crawl url
\n"); } diff --git a/source/net/yacy/http/servlets/SolrSelectServlet.java b/source/net/yacy/http/servlets/SolrSelectServlet.java index aa9f92eb1..d5944f40f 100644 --- a/source/net/yacy/http/servlets/SolrSelectServlet.java +++ b/source/net/yacy/http/servlets/SolrSelectServlet.java @@ -233,7 +233,7 @@ public class SolrSelectServlet extends HttpServlet { } // get the embedded connector - String requestURI = hrequest.getRequestURI(); + final String requestURI = hrequest.getRequestURI(); boolean defaultConnector = (requestURI.startsWith("/solr/" + WebgraphSchema.CORE_NAME)) ? false : requestURI.startsWith("/solr/" + CollectionSchema.CORE_NAME) || mmsp.get("core", CollectionSchema.CORE_NAME).equals(CollectionSchema.CORE_NAME); mmsp.getMap().remove("core"); SolrConnector connector = defaultConnector ? sb.index.fulltext().getDefaultEmbeddedConnector() : sb.index.fulltext().getEmbeddedConnector(WebgraphSchema.CORE_NAME); @@ -259,6 +259,10 @@ public class SolrSelectServlet extends HttpServlet { final SolrQueryResponse rsp; if (connector instanceof EmbeddedSolrConnector) { req = ((EmbeddedSolrConnector) connector).request(mmsp); + + /* Add the servlet request URI to the context for eventual computation of relative paths in writers */ + req.getContext().put("requestURI", requestURI); + rsp = ((EmbeddedSolrConnector) connector).query(req); // prepare response @@ -317,6 +321,9 @@ public class SolrSelectServlet extends HttpServlet { * Be sure thath the responseWriter instance can handle this properly. */ req = new SolrQueryRequestBase(null, mmsp) {}; + /* Add the servlet request URI to the context for eventual computation of relative paths in writers */ + req.getContext().put("requestURI", requestURI); + rsp = new SolrQueryResponse(); rsp.setHttpCaching(false); rsp.setAllValues(queryRsp.getResponse());