/** * For example: * * <p>String json = solr.request( "/select?qt=dismax&wt=json&q=...", null ); String xml = * solr.request( "/update", "<add><doc><field ..." ); */ public String request(String pathAndParams, String body) throws Exception { String path = null; SolrParams params = null; int idx = pathAndParams.indexOf('?'); if (idx > 0) { path = pathAndParams.substring(0, idx); params = SolrRequestParsers.parseQueryString(pathAndParams.substring(idx + 1)); } else { path = pathAndParams; params = new MapSolrParams(new HashMap<String, String>()); } // Extract the handler from the path or params SolrRequestHandler handler = core.getRequestHandler(path); if (handler == null) { if ("/select".equals(path) || "/select/".equalsIgnoreCase(path)) { String qt = params.get(CommonParams.QT); handler = core.getRequestHandler(qt); if (handler == null) { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "unknown handler: " + qt); } } } if (handler == null) { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "unknown handler: " + path); } // Make a stream for the 'body' content List<ContentStream> streams = new ArrayList<ContentStream>(1); if (body != null && body.length() > 0) { streams.add(new ContentStreamBase.StringStream(body)); } SolrQueryRequest req = null; try { req = parser.buildRequestFrom(core, params, streams); SolrQueryResponse rsp = new SolrQueryResponse(); core.execute(handler, req, rsp); if (rsp.getException() != null) { throw rsp.getException(); } // Now write it out QueryResponseWriter responseWriter = core.getQueryResponseWriter(req); StringWriter out = new StringWriter(); responseWriter.write(out, req, rsp); return out.toString(); } finally { if (req != null) { req.close(); } } }
@Test public void testStreamURL() throws Exception { boolean ok = false; String url = "http://www.apache.org/dist/lucene/solr/"; String txt = null; try { URLConnection connection = new URL(url).openConnection(); connection.setConnectTimeout(5000); connection.setReadTimeout(5000); connection.connect(); txt = IOUtils.toString(connection.getInputStream()); } catch (Exception ex) { // TODO - should it fail/skip? fail("this test only works if you have a network connection."); return; } SolrCore core = h.getCore(); Map<String, String[]> args = new HashMap<String, String[]>(); args.put(CommonParams.STREAM_URL, new String[] {url}); // Make sure it got a single stream in and out ok List<ContentStream> streams = new ArrayList<ContentStream>(); parser.buildRequestFrom(core, new MultiMapSolrParams(args), streams); assertEquals(1, streams.size()); assertEquals(txt, IOUtils.toString(streams.get(0).getStream())); }
/** Extract handler from the URL path if not set. This returns true if the action is set. */ private void extractHandlerFromURLPath(SolrRequestParsers parser) throws Exception { if (handler == null && path.length() > 1) { // don't match "" or "/" as valid path handler = core.getRequestHandler(path); if (handler == null) { // may be a restlet path // Handle /schema/* paths via Restlet if (path.equals("/schema") || path.startsWith("/schema/")) { solrReq = parser.parse(core, path, req); SolrRequestInfo.setRequestInfo(new SolrRequestInfo(solrReq, new SolrQueryResponse())); if (path.equals(req.getServletPath())) { // avoid endless loop - pass through to Restlet via webapp action = PASSTHROUGH; return; } else { // forward rewritten URI (without path prefix and core/collection name) to Restlet action = FORWARD; return; } } } // no handler yet but allowed to handle select; let's check if (handler == null && parser.isHandleSelect()) { if ("/select".equals(path) || "/select/".equals(path)) { solrReq = parser.parse(core, path, req); invalidStates = checkStateIsValid(solrReq.getParams().get(CloudSolrClient.STATE_VERSION)); String qt = solrReq.getParams().get(CommonParams.QT); handler = core.getRequestHandler(qt); if (handler == null) { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "unknown handler: " + qt); } if (qt != null && qt.startsWith("/") && (handler instanceof ContentStreamHandlerBase)) { // For security reasons it's a bad idea to allow a leading '/', ex: /select?qt=/update // see SOLR-3161 // There was no restriction from Solr 1.4 thru 3.5 and it's not supported for update // handlers. throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Invalid Request Handler ('qt'). Do not use /select to access: " + qt); } } } } }
@Test public void testStreamBody() throws Exception { String body1 = "AMANAPLANPANAMA"; String body2 = "qwertasdfgzxcvb"; String body3 = "1234567890"; SolrCore core = h.getCore(); Map<String, String[]> args = new HashMap<String, String[]>(); args.put(CommonParams.STREAM_BODY, new String[] {body1}); // Make sure it got a single stream in and out ok List<ContentStream> streams = new ArrayList<ContentStream>(); parser.buildRequestFrom(core, new MultiMapSolrParams(args), streams); assertEquals(1, streams.size()); assertEquals(body1, IOUtils.toString(streams.get(0).getStream())); // Now add three and make sure they come out ok streams = new ArrayList<ContentStream>(); args.put(CommonParams.STREAM_BODY, new String[] {body1, body2, body3}); parser.buildRequestFrom(core, new MultiMapSolrParams(args), streams); assertEquals(3, streams.size()); ArrayList<String> input = new ArrayList<String>(); ArrayList<String> output = new ArrayList<String>(); input.add(body1); input.add(body2); input.add(body3); output.add(IOUtils.toString(streams.get(0).getStream())); output.add(IOUtils.toString(streams.get(1).getStream())); output.add(IOUtils.toString(streams.get(2).getStream())); // sort them so the output is consistent Collections.sort(input); Collections.sort(output); assertEquals(input.toString(), output.toString()); // set the contentType and make sure tat gets set String ctype = "text/xxx"; streams = new ArrayList<ContentStream>(); args.put(CommonParams.STREAM_CONTENTTYPE, new String[] {ctype}); parser.buildRequestFrom(core, new MultiMapSolrParams(args), streams); for (ContentStream s : streams) { assertEquals(ctype, s.getContentType()); } }
public HttpSolrCall( SolrDispatchFilter solrDispatchFilter, CoreContainer cores, HttpServletRequest request, HttpServletResponse response, boolean retry) { this.solrDispatchFilter = solrDispatchFilter; this.cores = cores; this.req = request; this.response = response; this.retry = retry; this.requestType = RequestType.UNKNOWN; queryParams = SolrRequestParsers.parseQueryString(req.getQueryString()); }
@Test public void testUrlParamParsing() { String[][] teststr = new String[][] { {"this is simple", "this%20is%20simple"}, {"this is simple", "this+is+simple"}, {"\u00FC", "%C3%BC"}, // lower-case "u" with diaeresis/umlaut {"\u0026", "%26"}, // & {"\u20AC", "%E2%82%AC"} // euro }; for (String[] tst : teststr) { MultiMapSolrParams params = SolrRequestParsers.parseQueryString("val=" + tst[1]); assertEquals(tst[0], params.get("val")); } }
protected void sendError(Throwable ex) throws IOException { Exception exp = null; SolrCore localCore = null; try { SolrQueryResponse solrResp = new SolrQueryResponse(); if (ex instanceof Exception) { solrResp.setException((Exception) ex); } else { solrResp.setException(new RuntimeException(ex)); } localCore = core; if (solrReq == null) { final SolrParams solrParams; if (req != null) { // use GET parameters if available: solrParams = SolrRequestParsers.parseQueryString(req.getQueryString()); } else { // we have no params at all, use empty ones: solrParams = new MapSolrParams(Collections.<String, String>emptyMap()); } solrReq = new SolrQueryRequestBase(core, solrParams) {}; } QueryResponseWriter writer = core.getQueryResponseWriter(solrReq); writeResponse(solrResp, writer, Method.GET); } catch (Exception e) { // This error really does not matter exp = e; } finally { try { if (exp != null) { SimpleOrderedMap info = new SimpleOrderedMap(); int code = ResponseUtils.getErrorInfo(ex, info, log); sendError(code, info.toString()); } } finally { if (core == null && localCore != null) { localCore.close(); } } } }
private void init() throws Exception { // The states of client that is invalid in this request Aliases aliases = null; String corename = ""; String origCorename = null; // set a request timer which can be reused by requests if needed 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(); } // check for management path String alternate = cores.getManagementPath(); if (alternate != null && path.startsWith(alternate)) { path = path.substring(0, alternate.length()); } // unused feature ? int idx = path.indexOf(':'); if (idx > 0) { // save the portion after the ':' for a 'handler' path parameter path = path.substring(0, idx); } boolean usingAliases = false; // Check for container handlers handler = cores.getRequestHandler(path); if (handler != null) { solrReq = SolrRequestParsers.DEFAULT.parse(null, path, req); solrReq.getContext().put(CoreContainer.class.getName(), cores); requestType = RequestType.ADMIN; action = ADMIN; return; } else { // otherwise, we should find a core from the path idx = path.indexOf("/", 1); if (idx > 1) { // try to get the corename as a request parameter first corename = path.substring(1, idx); // look at aliases if (cores.isZooKeeperAware()) { origCorename = corename; ZkStateReader reader = cores.getZkController().getZkStateReader(); aliases = reader.getAliases(); if (aliases != null && aliases.collectionAliasSize() > 0) { usingAliases = true; String alias = aliases.getCollectionAlias(corename); if (alias != null) { collectionsList = StrUtils.splitSmart(alias, ",", true); corename = collectionsList.get(0); } } } core = cores.getCore(corename); if (core != null) { path = path.substring(idx); } else if (cores.isCoreLoading( corename)) { // extra mem barriers, so don't look at this before trying to get core throw new SolrException(ErrorCode.SERVICE_UNAVAILABLE, "SolrCore is loading"); } else { // the core may have just finished loading core = cores.getCore(corename); if (core != null) { path = path.substring(idx); } } } if (core == null) { if (!cores.isZooKeeperAware()) { core = cores.getCore(""); } } } if (core == null && cores.isZooKeeperAware()) { // we couldn't find the core - lets make sure a collection was not specified instead core = getCoreByCollection(corename); if (core != null) { // we found a core, update the path path = path.substring(idx); if (collectionsList == null) collectionsList = new ArrayList<>(); collectionsList.add(corename); } // if we couldn't find it locally, look on other nodes extractRemotePath(corename, origCorename, idx); if (action != null) return; } // With a valid core... if (core != null) { MDCLoggingContext.setCore(core); config = core.getSolrConfig(); // get or create/cache the parser for the core SolrRequestParsers parser = config.getRequestParsers(); // Determine the handler from the url path if not set // (we might already have selected the cores handler) extractHandlerFromURLPath(parser); if (action != null) return; // With a valid handler and a valid core... if (handler != null) { // if not a /select, create the request if (solrReq == null) { solrReq = parser.parse(core, path, req); } if (usingAliases) { processAliases(aliases, collectionsList); } action = PROCESS; return; // we are done with a valid handler } } log.debug("no handler or core retrieved for " + path + ", follow through..."); action = PASSTHROUGH; }