Пример #1
0
  /**
   * For example:
   *
   * <p>String json = solr.request( "/select?qt=dismax&wt=json&q=...", null ); String xml =
   * solr.request( "/update", "&lt;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();
      }
    }
  }
Пример #2
0
 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();
       }
     }
   }
 }
Пример #3
0
 /** 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);
 }
Пример #4
0
  /** 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();
    }
  }
Пример #5
0
  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();
    }
  }