예제 #1
0
  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);
        }
      }
    }
  }
예제 #2
0
  @Override
  public FilterDirector handleRequest(
      HttpServletRequest httpRequest, ReadableHttpServletResponse httpResponse) {
    MutableHttpServletRequest request = MutableHttpServletRequest.wrap(httpRequest);
    MutableHttpServletResponse response =
        MutableHttpServletResponse.wrap(httpRequest, httpResponse);
    FilterDirector filterDirector = new FilterDirectorImpl();
    MediaType contentType = getContentType(request.getHeaderValue("content-type"));
    List<MediaType> acceptValues =
        getAcceptValues(request.getPreferredHeaders("Accept", DEFAULT_TYPE));
    List<XmlChainPool> pools =
        getHandlerChainPool(request.getMethod(), contentType, acceptValues, "", requestProcessors);

    if (pools.isEmpty()) {
      filterDirector.setFilterAction(FilterAction.PROCESS_RESPONSE);
      return filterDirector;
    }

    try {
      ServletInputStream in = request.getInputStream();
      TranslationResult result = null;
      for (XmlChainPool pool : pools) {
        final ByteBuffer internalBuffer = new CyclicByteBuffer(DEFAULT_BUFFER_SIZE, true);
        result =
            pool.executePool(
                new TranslationPreProcessor(in, contentType, true).getBodyStream(),
                new ByteBufferServletOutputStream(internalBuffer),
                getInputParameters(TranslationType.REQUEST, request, response, result));

        if (result.isSuccess()) {
          in = new ByteBufferInputStream(internalBuffer);
          request.setInputStream(in);
          result.applyResults(filterDirector);
          if (StringUtilities.isNotBlank(pool.getResultContentType())) {
            filterDirector
                .requestHeaderManager()
                .putHeader("content-type", pool.getResultContentType());
            contentType = getContentType(pool.getResultContentType());
          }
          filterDirector.setFilterAction(FilterAction.PROCESS_RESPONSE);
        } else {
          filterDirector.setResponseStatus(HttpStatusCode.BAD_REQUEST);
          filterDirector.setFilterAction(FilterAction.RETURN);
          break;
        }
      }
    } catch (IOException ex) {
      LOG.error("Error executing request transformer chain", ex);
      filterDirector.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR);
      filterDirector.setFilterAction(FilterAction.RETURN);
    }

    return filterDirector;
  }
예제 #3
0
 @Override
 public FilterDirector handleRequest(
     HttpServletRequest request, ReadableHttpServletResponse response) {
   FilterDirector filterDirector = new FilterDirectorImpl();
   filterDirector.setFilterAction(FilterAction.PROCESS_RESPONSE);
   return filterDirector;
 }
  @Override
  public FilterDirector handleRequest(
      HttpServletRequest request, ReadableHttpServletResponse response) {
    FilterDirector director = new FilterDirectorImpl();
    director.setFilterAction(FilterAction.PASS);

    if (CacheRequest.isCacheRequest(request)) {
      if (isAllowed(request)) {
        director = performCacheRequest(request);
      } else {
        director.setResponseStatus(HttpStatusCode.FORBIDDEN);
        director.setFilterAction(FilterAction.RETURN);
      }
    }

    return director;
  }
  @Override
  public FilterDirector handleRequest(
      HttpServletRequest request, ReadableHttpServletResponse response) {
    FilterDirector filterDirector = new FilterDirectorImpl();
    filterDirector.setResponseStatus(HttpStatusCode.UNAUTHORIZED);
    filterDirector.setFilterAction(FilterAction.RETURN);

    final String uri = request.getRequestURI();
    LOG.debug("Uri is " + uri);
    if (uriMatcher.isUriOnWhiteList(uri)) {
      filterDirector.setFilterAction(FilterAction.PASS);
      LOG.debug("Uri is on whitelist!  Letting request pass through.");
    } else {
      filterDirector = this.authenticate(request);
    }

    return filterDirector;
  }
  public void onCacheDelete(HttpServletRequest request, final FilterDirector director)
      throws DatastoreOperationException, MalformedCacheRequestException {
    final CacheRequest cacheDelete = CacheRequest.marshallCacheRequest(request);
    hashRingDatastore.remove(
        cacheDelete.getCacheKey(),
        encodingProvider.decode(cacheDelete.getCacheKey()),
        cacheDelete.getRequestedRemoteBehavior());

    director.setResponseStatus(HttpStatusCode.ACCEPTED);
    director.setFilterAction(FilterAction.RETURN);
  }
예제 #7
0
  @Override
  public FilterDirector handleRequest(
      HttpServletRequest request, ReadableHttpServletResponse response) {
    final FilterDirector director = new FilterDirectorImpl();
    MutableHttpServletRequest mutableRequest = MutableHttpServletRequest.wrap(request);
    MediaRangeProcessor processor =
        new MediaRangeProcessor(
            mutableRequest.getPreferredHeaders(CommonHttpHeader.ACCEPT.toString(), DEFAULT_TYPE));

    List<MediaType> mediaTypes = processor.process();

    if (requestHasExpectedHeaders(request)) {
      originalPreferredAccept = getPreferredMediaType(mediaTypes);
      MediaType preferredMediaType = originalPreferredAccept;

      final String requestUri = request.getRequestURI();

      // request now considered valid with user.
      director.setFilterAction(FilterAction.PASS);

      // Record limits
      final boolean pass = recordLimitedRequest(request, director);

      // Does the request match the configured getCurrentLimits API call endpoint?
      if (pass && describeLimitsUriPattern.matcher(requestUri).matches()) {
        describeLimitsForRequest(request, director, preferredMediaType);
      }
    } else {
      LOG.warn(
          "Expected header: "
              + PowerApiHeader.USER.toString()
              + " was not supplied in the request. Rate limiting requires this header to operate.");

      // Auto return a 401 if the request does not meet expectations
      director.setResponseStatus(HttpStatusCode.UNAUTHORIZED);
      director.setFilterAction(FilterAction.RETURN);
    }

    return director;
  }
예제 #8
0
  @Override
  public FilterDirector handleResponse(
      HttpServletRequest request, ReadableHttpServletResponse response) {
    FilterDirector filterDirector = new FilterDirectorImpl();
    filterDirector.setResponseStatusCode(response.getStatus());
    filterDirector.setFilterAction(FilterAction.PASS);

    for (HttpLoggerWrapper loggerWrapper : loggers) {
      loggerWrapper.handle(request, response);
    }

    return filterDirector;
  }
  private FilterDirector authenticate(HttpServletRequest request) {
    final FilterDirector filterDirector = new FilterDirectorImpl();
    filterDirector.setResponseStatus(HttpStatusCode.UNAUTHORIZED);
    filterDirector.setFilterAction(FilterAction.RETURN);

    final String authToken = request.getHeader(CommonHttpHeader.AUTH_TOKEN.toString());
    ExtractorResult<String> account = null;
    AuthToken token = null;

    if (tenanted) {
      account = extractAccountIdentification(request);
    }

    final boolean allow = allowAccount(account);

    if ((!StringUtilities.isBlank(authToken) && allow)) {
      token = checkToken(account, authToken);

      if (token == null) {
        try {
          token = validateToken(account, StringUriUtilities.encodeUri(authToken));
          cacheUserInfo(token);
        } catch (ClientHandlerException ex) {
          LOG.error("Failure communicating with the auth service: " + ex.getMessage(), ex);
          filterDirector.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR);
        } catch (AuthServiceException ex) {
          LOG.error("Failure in Auth-N: " + ex.getMessage());
          filterDirector.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR);
        } catch (IllegalArgumentException ex) {
          LOG.error("Failure in Auth-N: " + ex.getMessage());
          filterDirector.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR);
        } catch (Exception ex) {
          LOG.error("Failure in auth: " + ex.getMessage(), ex);
          filterDirector.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR);
        }
      }
    }

    List<AuthGroup> groups = getAuthGroups(token);

    setFilterDirectorValues(
        authToken,
        token,
        delegable,
        filterDirector,
        account == null ? "" : account.getResult(),
        groups);

    return filterDirector;
  }
예제 #10
0
  public void onCachePut(HttpServletRequest request, final FilterDirector director)
      throws MalformedCacheRequestException, DatastoreOperationException {
    final CacheRequest cachePut = CacheRequest.marshallCachePutRequest(request);
    hashRingDatastore.put(
        cachePut.getCacheKey(),
        encodingProvider.decode(cachePut.getCacheKey()),
        cachePut.getPayload(),
        cachePut.getTtlInSeconds(),
        TimeUnit.SECONDS,
        cachePut.getRequestedRemoteBehavior());

    director.setResponseStatus(HttpStatusCode.ACCEPTED);
    director.setFilterAction(FilterAction.RETURN);
  }
예제 #11
0
  /** @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;
  }
예제 #12
0
  public FilterDirector performCacheRequest(HttpServletRequest request) {
    final FilterDirector director = new FilterDirectorImpl();

    // Defaults to return not-implemented
    director.setResponseStatus(HttpStatusCode.NOT_IMPLEMENTED);
    director.setFilterAction(FilterAction.RETURN);

    try {
      final String requestMethod = request.getMethod();

      if ("GET".equalsIgnoreCase(requestMethod)) {
        onCacheGet(CacheRequest.marshallCacheRequest(request), director);
      } else if ("PUT".equalsIgnoreCase(requestMethod)) {
        onCachePut(request, director);
      } else if ("DELETE".equalsIgnoreCase(requestMethod)) {
        onCacheDelete(request, director);
      }
    } catch (MalformedCacheRequestException mcre) {
      LOG.error(
          "The request to interact with the cache is malformed: "
              + request.getMethod()
              + " Reason: "
              + mcre.getMessage(),
          mcre);
      director.getResponseWriter().write(mcre.getMessage() == null ? "" : mcre.getMessage());
      director.setResponseStatus(HttpStatusCode.BAD_REQUEST);
      director.setFilterAction(FilterAction.RETURN);
    } catch (Exception ex) {
      LOG.error(ex.getMessage(), ex);

      director.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR);
      director.setFilterAction(FilterAction.RETURN);
    }

    return director;
  }
예제 #13
0
  public void onCacheGet(CacheRequest cacheGet, FilterDirector director) {
    final StoredElement element =
        hashRingDatastore.get(
            cacheGet.getCacheKey(),
            encodingProvider.decode(cacheGet.getCacheKey()),
            cacheGet.getRequestedRemoteBehavior());

    if (!element.elementIsNull()) {
      try {
        director.getResponseOutputStream().write(element.elementBytes());

        director.setResponseStatus(HttpStatusCode.OK);
        director.setFilterAction(FilterAction.RETURN);
      } catch (IOException ioe) {
        LOG.error(ioe.getMessage(), ioe);

        director.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR);
        director.setFilterAction(FilterAction.RETURN);
      }
    } else {
      director.setResponseStatus(HttpStatusCode.NOT_FOUND);
      director.setFilterAction(FilterAction.RETURN);
    }
  }
  @Override
  public FilterDirector authenticate(HttpServletRequest request) {
    final FilterDirector filterDirector = new FilterDirectorImpl();
    filterDirector.setResponseStatus(HttpStatusCode.UNAUTHORIZED);
    filterDirector.setFilterAction(FilterAction.RETURN);

    final String authToken = request.getHeader(CommonHttpHeader.AUTH_TOKEN.toString());
    final ExtractorResult<Object> account = keyedRegexExtractor.extract(request.getRequestURI());
    CachableUserInfo user = null;

    if ((!StringUtilities.isBlank(authToken) && account != null)) {
      user = checkUserCache(account.getResult(), authToken);

      if (user == null) {
        try {
          user = authenticationService.validateToken(account.getResult(), authToken);
          cacheUserInfo(user);
        } catch (Exception ex) {
          LOG.error("Failure in auth: " + ex.getMessage(), ex);
          filterDirector.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR);
        }
      }
    }

    Groups groups = null;
    if (user != null) {
      groups = authenticationService.getGroups(user.getUserId());
    }

    final AuthenticationHeaderManager headerManager =
        new AuthenticationHeaderManager(
            authToken,
            user,
            delegatable,
            filterDirector,
            account == null ? "" : account.getResult(),
            groups,
            request);
    headerManager.setFilterDirectorValues();

    return filterDirector;
  }
예제 #15
0
  private void consumeException(Exception e, FilterDirector director) {
    LOG.error("Failure when querying limits. Reason: " + e.getMessage(), e);

    director.setFilterAction(FilterAction.RETURN);
    director.setResponseStatus(HttpStatusCode.INTERNAL_SERVER_ERROR);
  }
예제 #16
0
  @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;
  }