private void describeLimitsForRequest( HttpServletRequest request, FilterDirector director, MediaType preferredMediaType) { if (preferredMediaType.getMimeType() == MimeType.UNKNOWN) { director.setFilterAction(FilterAction.RETURN); director.setResponseStatus(HttpStatusCode.NOT_ACCEPTABLE); } else { // If include absolute limits let request pass thru but prepare the combined // (absolute and active) limits when processing the response if (includeAbsoluteLimits) { director.setFilterAction(FilterAction.PROCESS_RESPONSE); director .requestHeaderManager() .putHeader(CommonHttpHeader.ACCEPT.toString(), MimeType.APPLICATION_XML.toString()); } else { try { final MimeType mimeType = rateLimitingServiceHelper.queryActiveLimits( request, preferredMediaType, director.getResponseOutputStream()); director .responseHeaderManager() .putHeader(CommonHttpHeader.CONTENT_TYPE.toString(), mimeType.toString()); director.setFilterAction(FilterAction.RETURN); director.setResponseStatus(HttpStatusCode.OK); } catch (Exception e) { consumeException(e, director); } } } }
private FilterDirector updateHttpResponse(FilterDirector director, String wwwAuthenticateHeader) { // If in the case that the origin service supports delegated authentication // we should then communicate to the client how to authenticate with us if (!StringUtilities.isBlank(wwwAuthenticateHeader) && wwwAuthenticateHeader.contains("Delegated")) { final String replacementWwwAuthenticateHeader = getWWWAuthenticateHeaderContents(); director .responseHeaderManager() .putHeader( CommonHttpHeader.WWW_AUTHENTICATE.toString(), replacementWwwAuthenticateHeader); } else { // In the case where authentication has failed and we did not receive // a delegated WWW-Authenticate header, this means that our own authentication // with the origin service has failed and must then be communicated as // a 500 (internal server error) to the client director.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR); } return director; }
@Test public void shouldModifyDelegatedWwwAuthenticateHeaderOn403() { when(response.getHeader(CommonHttpHeader.WWW_AUTHENTICATE.toString())) .thenReturn("Delegated"); when(response.getStatus()).thenReturn(403); final FilterDirector responseDirector = handler.handleResponse(request, response); final String expected = "Keystone uri=" + osauthConfig.getIdentityService().getUri(); assertEquals( "Auth component must pass invalid requests but process their responses", expected, responseDirector .responseHeaderManager() .headersToAdd() .get(CommonHttpHeader.WWW_AUTHENTICATE.toString()) .iterator() .next()); }
@Override public FilterDirector handleResponse( HttpServletRequest request, ReadableHttpServletResponse response) { final FilterDirector director = new FilterDirectorImpl(); try { final MimeType mimeType = rateLimitingServiceHelper.queryCombinedLimits( request, originalPreferredAccept, response.getBufferedOutputAsInputStream(), director.getResponseOutputStream()); director .responseHeaderManager() .putHeader(CommonHttpHeader.CONTENT_TYPE.toString(), mimeType.toString()); } catch (Exception e) { consumeException(e, director); } return director; }
/** @return false if over-limit and response delegation is not enabled */ private boolean recordLimitedRequest(HttpServletRequest request, FilterDirector director) { boolean pass = true; try { rateLimitingServiceHelper.trackLimits(request); } catch (OverLimitException e) { new LimitLogger(e.getUser(), request) .log(e.getConfiguredLimit(), Integer.toString(e.getCurrentLimitAmount())); final HttpDate nextAvailableTime = new HttpDate(e.getNextAvailableTime()); // Tell the filter we want to return right away director.setFilterAction(FilterAction.RETURN); pass = false; // We use a 413 "Request Entity Too Large" to communicate that the user // in question has hit their rate limit for this requested URI if (overLimit429ResponseCode) { director.setResponseStatus(HttpStatusCode.TOO_MANY_REQUESTS); } else { director.setResponseStatus(HttpStatusCode.REQUEST_ENTITY_TOO_LARGE); } director .responseHeaderManager() .appendHeader(CommonHttpHeader.RETRY_AFTER.toString(), nextAvailableTime.toRFC1123()); } catch (CacheException e) { LOG.error("Failure when tracking limits. Reason: " + e.getMessage(), e); director.setFilterAction(FilterAction.RETURN); director.setResponseStatus(HttpStatusCode.BAD_GATEWAY); } return pass; }
@Override public FilterDirector handleResponse( HttpServletRequest httpRequest, ReadableHttpServletResponse httpResponse) { MutableHttpServletRequest request = MutableHttpServletRequest.wrap(httpRequest); MutableHttpServletResponse response = MutableHttpServletResponse.wrap(httpRequest, httpResponse); final FilterDirector filterDirector = new FilterDirectorImpl(); filterDirector.setFilterAction(FilterAction.PASS); MediaType contentType = getContentType(response.getHeaderValue("Content-Type")); List<MediaType> acceptValues = getAcceptValues(request.getPreferredHeaders("Accept", DEFAULT_TYPE)); List<XmlChainPool> pools = getHandlerChainPool( "", contentType, acceptValues, String.valueOf(response.getStatus()), responseProcessors); if (pools.isEmpty()) { filterDirector.setResponseStatusCode(response.getStatus()); return filterDirector; } try { filterDirector.setResponseStatusCode(response.getStatus()); if (response.hasBody()) { InputStream in = response.getBufferedOutputAsInputStream(); TranslationResult result = null; for (XmlChainPool pool : pools) { if (in.available() > 0) { result = pool.executePool( new TranslationPreProcessor(in, contentType, true).getBodyStream(), filterDirector.getResponseOutputStream(), getInputParameters(TranslationType.RESPONSE, request, response, result)); if (result.isSuccess()) { result.applyResults(filterDirector); if (StringUtilities.isNotBlank(pool.getResultContentType())) { filterDirector .requestHeaderManager() .putHeader("content-type", pool.getResultContentType()); contentType = getContentType(pool.getResultContentType()); } in = new ByteArrayInputStream(filterDirector.getResponseMessageBodyBytes()); } else { filterDirector.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR); response.setContentLength(0); filterDirector.responseHeaderManager().removeHeader("Content-Length"); break; } } } } } catch (IOException ex) { LOG.error("Error executing response transformer chain", ex); filterDirector.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR); response.setContentLength(0); } return filterDirector; }