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;
}