/** * 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(); } } }
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(); } } } }
/** Writes the response to the search query to the HTTP response's output stream. */ private void writeResponse( SolrQuery query, HttpServletRequest httpRequest, HttpServletResponse httpResponse, QueryResponse queryResponse) throws IOException { SolrCore core = SearchActivator.getInstance().getSolrCore(); // this seems to be the only way to obtain the JSON response representation SolrQueryRequest solrRequest = new LocalSolrQueryRequest(core, query.toNamedList()); SolrQueryResponse solrResponse = new SolrQueryResponse(); // bash the query in the response to remove user info NamedList<Object> params = (NamedList<Object>) queryResponse.getHeader().get("params"); // $NON-NLS-1$ params.remove(CommonParams.Q); params.add(CommonParams.Q, httpRequest.getParameter(CommonParams.Q)); NamedList<Object> values = queryResponse.getResponse(); String contextPath = httpRequest.getContextPath(); if (contextPath.length() > 0) setSearchResultContext(values, contextPath); solrResponse.setAllValues(values); QueryResponseWriter writer = core.getQueryResponseWriter("json"); // $NON-NLS-1$ writer.write(httpResponse.getWriter(), solrRequest, solrResponse); }
/** This method processes the request. */ public Action call() throws IOException { MDCLoggingContext.reset(); MDCLoggingContext.setNode(cores); if (cores == null) { sendError(503, "Server is shutting down or failed to initialize"); return RETURN; } if (solrDispatchFilter.abortErrorMessage != null) { sendError(500, solrDispatchFilter.abortErrorMessage); return RETURN; } try { init(); /* Authorize the request if 1. Authorization is enabled, and 2. The requested resource is not a known static file */ if (cores.getAuthorizationPlugin() != null && shouldAuthorize()) { AuthorizationContext context = getAuthCtx(); log.debug("AuthorizationContext : {}", context); AuthorizationResponse authResponse = cores.getAuthorizationPlugin().authorize(context); if (authResponse.statusCode == AuthorizationResponse.PROMPT.statusCode) { Map<String, String> headers = (Map) getReq().getAttribute(AuthenticationPlugin.class.getName()); if (headers != null) { for (Map.Entry<String, String> e : headers.entrySet()) response.setHeader(e.getKey(), e.getValue()); } log.debug( "USER_REQUIRED " + req.getHeader("Authorization") + " " + req.getUserPrincipal()); } if (!(authResponse.statusCode == HttpStatus.SC_ACCEPTED) && !(authResponse.statusCode == HttpStatus.SC_OK)) { log.info( "USER_REQUIRED auth header {} context : {} ", req.getHeader("Authorization"), context); sendError( authResponse.statusCode, "Unauthorized request, Response code: " + authResponse.statusCode); return RETURN; } } HttpServletResponse resp = response; switch (action) { case ADMIN: handleAdminRequest(); return RETURN; case REMOTEQUERY: remoteQuery(coreUrl + path, resp); return RETURN; case PROCESS: final Method reqMethod = Method.getMethod(req.getMethod()); HttpCacheHeaderUtil.setCacheControlHeader(config, resp, reqMethod); // unless we have been explicitly told not to, do cache validation // if we fail cache validation, execute the query if (config.getHttpCachingConfig().isNever304() || !HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req, reqMethod, resp)) { SolrQueryResponse solrRsp = new SolrQueryResponse(); /* even for HEAD requests, we need to execute the handler to * ensure we don't get an error (and to make sure the correct * QueryResponseWriter is selected and we get the correct * Content-Type) */ SolrRequestInfo.setRequestInfo(new SolrRequestInfo(solrReq, solrRsp)); execute(solrRsp); HttpCacheHeaderUtil.checkHttpCachingVeto(solrRsp, resp, reqMethod); Iterator<Map.Entry<String, String>> headers = solrRsp.httpHeaders(); while (headers.hasNext()) { Map.Entry<String, String> entry = headers.next(); resp.addHeader(entry.getKey(), entry.getValue()); } QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq); if (invalidStates != null) solrReq.getContext().put(CloudSolrClient.STATE_VERSION, invalidStates); writeResponse(solrRsp, responseWriter, reqMethod); } return RETURN; default: return action; } } catch (Throwable ex) { sendError(ex); // walk the the entire cause chain to search for an Error Throwable t = ex; while (t != null) { if (t instanceof Error) { if (t != ex) { log.error( "An Error was wrapped in another exception - please report complete stacktrace on SOLR-6161", ex); } throw (Error) t; } t = t.getCause(); } return RETURN; } finally { MDCLoggingContext.clear(); } }
public void handleRequest(RequestGetter requestGetter) { MDCLoggingContext.reset(); MDCLoggingContext.setNode(cores); String path = requestGetter.getPath(); solrParams = requestGetter.getSolrParams(); SolrRequestHandler handler = null; String corename = ""; String origCorename = null; try { // set a request timer which can be reused by requests if needed // req.setAttribute(SolrRequestParsers.REQUEST_TIMER_SERVLET_ATTRIBUTE, new RTimer()); // put the core container in request attribute // req.setAttribute("org.apache.solr.CoreContainer", cores); // 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; List<String> collectionsList = null; // Check for container handlers handler = cores.getRequestHandler(path); if (handler != null) { solrReq = parseSolrQueryRequest(SolrRequestParsers.DEFAULT, requestGetter); handleAdminRequest(handler, solrReq); 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); } } // add collection name if (core == null && StringUtils.isNotBlank(requestGetter.getCollection())) { corename = requestGetter.getCollection(); core = cores.getCore(corename); } 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(cores, corename); if (core != null) { // we found a core, update the path path = path.substring(idx); } // try the default core if (core == null) { core = cores.getCore(""); if (core != null) {} } } // With a valid core... if (core != null) { MDCLoggingContext.setCore(core); final SolrConfig 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) 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/")) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "unsupport /schema/**, use http solr"); } } // no handler yet but allowed to handle select; let's check if (handler == null && parser.isHandleSelect()) { if ("/select".equals(path) || "/select/".equals(path)) { solrReq = parseSolrQueryRequest(parser, requestGetter); invalidStates = checkStateIsValid(cores, 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); } } } } // With a valid handler and a valid core... if (handler != null) { // if not a /select, create the request if (solrReq == null) { solrReq = parseSolrQueryRequest(parser, requestGetter); } if (usingAliases) { processAliases(solrReq, aliases, collectionsList); } SolrQueryResponse solrRsp = new SolrQueryResponse(); SolrRequestInfo.setRequestInfo(new SolrRequestInfo(solrReq, solrRsp)); this.execute(handler, solrReq, solrRsp); QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq); if (invalidStates != null) solrReq.getContext().put(CloudSolrClient.STATE_VERSION, invalidStates); writeResponse(solrRsp, responseWriter, solrReq); return; // we are done with a valid handler } } logger.debug("no handler or core retrieved for {}, follow through...", path); throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "no handler or core retrieved for " + path); } catch (Throwable ex) { sendError(core, solrReq, ex); // walk the the entire cause chain to search for an Error Throwable t = ex; while (t != null) { if (t instanceof Error) { if (t != ex) { logger.error( "An Error was wrapped in another exception - please report complete stacktrace on SOLR-6161", ex); } throw (Error) t; } t = t.getCause(); } return; } finally { try { if (solrReq != null) { logger.debug("Closing out SolrRequest: {}", solrReq); solrReq.close(); } } finally { try { if (core != null) { core.close(); } } finally { SolrRequestInfo.clearRequestInfo(); } } MDCLoggingContext.clear(); } }