protected ModelAndView doHandle()

in rest-api/src/jetbrains/buildServer/server/rest/APIController.java [175:281]


  protected ModelAndView doHandle(@NotNull final HttpServletRequest request, @NotNull final HttpServletResponse response) throws Exception {
    if (TeamCityProperties.getBoolean("rest.disable")) {
      final String message = TeamCityProperties.getProperty("rest.disable.message", "REST API is disabled on this TeamCity server with 'rest.disable' internal property.");
      reportRestErrorResponse(response, HttpServletResponse.SC_NOT_IMPLEMENTED, null, message, Level.INFO, request);
      return null;
    }

    if (matches(WebUtil.getRequestUrl(request),
                myDisabledRequests.getParsedValues(TeamCityProperties.getProperty("rest.disable.requests"), TeamCityProperties.getProperty("rest.disable.requests.delimiter")))) {
      final String defaultMessage = "Requests for URL \"" + WebUtil.getRequestUrl(request) +
                                    "\" are disabled in REST API on this server with 'rest.disable.requests' internal property.";
      final String message = TeamCityProperties.getProperty("rest.disable.message", defaultMessage);
      reportRestErrorResponse(response, HttpServletResponse.SC_NOT_IMPLEMENTED, null, message, Level.INFO, request);
      return null;
    }

    final Stopwatch requestStart = Stopwatch.createStarted();
    boolean shouldLogToDebug = shouldLogToDebug(request);

    String requestType = getRequestType(request);

    if (shouldLogToDebug && TeamCityProperties.getBoolean("rest.log.debug.requestStart") && LOG.isDebugEnabled()) {
      LOG.debug(() -> "REST API " + requestType + " request received: " + WebUtil.getRequestDump(request));
    }

    try {
      myWebComponentInitializer.initJerseyWebComponent(() -> "during request " + WebUtil.getRequestDump(request));
    } catch (Throwable throwable) {
      reportRestErrorResponse(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, throwable, "Error initializing REST API", Level.ERROR, request);
      return null;
    }

    boolean runAsSystem = false;
    if (TeamCityProperties.getBoolean("rest.use.authToken")) {
      String authToken = request.getParameter("authToken");
      if (StringUtil.isNotEmpty(authToken) && StringUtil.isNotEmpty(getAuthToken())) {
        if (authToken.equals(getAuthToken())) {
          runAsSystem = true;
        } else {
          synchronized (this) {
            Thread.sleep(10000); //to prevent brute-forcing
          }
          reportRestErrorResponse(response, HttpServletResponse.SC_UNAUTHORIZED, null, "Wrong authToken specified",
                                  Level.INFO, request);
          return null;
        }
      }
    }

    final AtomicBoolean errorEncountered = new AtomicBoolean(false);
    final boolean runAsSystemActual = runAsSystem;
    try {

      final boolean corsRequest = myAllowedOrigins.processCorsOriginHeaders(request, response, LOG);
      if (corsRequest && request.getMethod().equalsIgnoreCase("OPTIONS")) {
        //handling browser pre-flight requests
        LOG.debug("Pre-flight OPTIONS request detected, replying with status 204");
        response.setStatus(HttpServletResponse.SC_NO_CONTENT);
        return null;
      }
      if (myInternalAuthProcessing && SessionUser.getUser(request) == null && !requestForMyPathNotRequiringAuth(request)) {
        if (processRequestAuthentication(request, response, myAuthManager)) {
          return null;
        }
        //TeamCity API issue: SecurityContext.getAuthorityHolder is "SYSTEM" if request is not authorized
        final boolean notAuthorizedRequest = mySecurityContext.isSystemAccess();
        if (notAuthorizedRequest) {
          response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
          response.getWriter().write("TeamCity core was unable to handle authentication (no current user).");
          LOG.warn("TeamCity core was unable to handle authentication (no current user), replying with 401 status. Request details: " + WebUtil.getRequestDump(request));
          return null;
        }
      }

      patchThread(() -> WebUtil.getRequestDump(request), requestType, () -> {
        // workaround for http://jetbrains.net/tracker/issue2/TW-7656
        doUnderContextClassLoader(myClassloader, (FuncThrow<Void, Throwable>)() ->
          new RestContext(name -> request.getAttribute(CONTEXT_REQUEST_ARGUMENTS_PREFIX + name))
              .run(() -> {
                // patching request
                final HttpServletRequest actualRequest =
                  new RequestWrapper(patchRequestWithAcceptHeader(request), myRequestPathTransformInfo);

                if (runAsSystemActual) {
                  if (shouldLogToDebug && LOG.isDebugEnabled()) LOG.debug("Executing request with system security level");
                  mySecurityContext.runAsSystem(() -> {
                    myWebComponent.doFilter(actualRequest, response, null);
                  });
                } else {
                  myWebComponent.doFilter(actualRequest, response, null);
                }
                return null;
              }));
        return null;
      });
    } catch (Throwable throwable) {
      errorEncountered.set(true);
      processException(request, response, throwable);
    } finally {
      if (shouldLogToDebug && LOG.isDebugEnabled()) {
        LOG.debug(() -> "REST API " + requestType + " request processing finished in " +
                        TimePrinter.createMillisecondsFormatter().formatTime(requestStart.elapsed(TimeUnit.MILLISECONDS)) +
                        (errorEncountered.get() ? " with errors, original " : ", ") + "status code: " + getStatus(response) + ", request: " + WebUtil.getRequestDump(request));
      }
    }
    return null;
  }