All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ro.isdc.wro.http.handler.ResourceProxyRequestHandler Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
package ro.isdc.wro.http.handler;

import static org.apache.commons.lang3.Validate.notNull;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.AutoCloseInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ro.isdc.wro.config.ReadOnlyContext;
import ro.isdc.wro.http.WroFilter;
import ro.isdc.wro.http.support.ContentTypeResolver;
import ro.isdc.wro.http.support.HttpHeader;
import ro.isdc.wro.http.support.ResponseHeadersConfigurer;
import ro.isdc.wro.http.support.UnauthorizedRequestException;
import ro.isdc.wro.model.group.Inject;
import ro.isdc.wro.model.resource.locator.factory.UriLocatorFactory;
import ro.isdc.wro.model.resource.support.ResourceAuthorizationManager;


/**
 * Provides access to wro resources via a resource proxy. This request handler accepts the following uri:
 *
 * 
 * ?wroAPI=wroResources?id=/path/to/resourceId.js
 * 
* * Notice that this uri has the following mandatory parameters: *
    *
  • wroAPI - having the 'wroResources' value
  • *
  • id - the id of the proxy resource
  • *
* * @author Ivar Conradi Østhus * @created 19 May 2012 * @since 1.4.7 */ public class ResourceProxyRequestHandler extends RequestHandlerSupport { private static final Logger LOG = LoggerFactory.getLogger(ResourceProxyRequestHandler.class); public static final String PARAM_RESOURCE_ID = "id"; public static final String PATH_RESOURCES = "wroResources"; /** * The alias of this {@link RequestHandler} used for configuration. */ public static final String ALIAS = "resourceProxy"; @Inject private UriLocatorFactory locatorFactory; @Inject private ReadOnlyContext context; @Inject private ResourceAuthorizationManager authManager; private ResponseHeadersConfigurer headersConfigurer; @Override public void handle(final HttpServletRequest request, final HttpServletResponse response) throws IOException { verifyAccess(request, response); serveProxyResourceUri(request, response); } @Override public boolean accept(final HttpServletRequest request) { return isProxyRequest(request); } private void serveProxyResourceUri(final HttpServletRequest request, final HttpServletResponse response) throws IOException { final String resourceUri = getResourceUri(request); LOG.debug("[OK] serving proxy resource: {}", resourceUri); final OutputStream outputStream = response.getOutputStream(); response.setContentType(ContentTypeResolver.get(resourceUri, context.getConfig().getEncoding())); if (isResourceChanged(request)) { // set expiry headers getHeadersConfigurer().setHeaders(response); InputStream is = null; try { is = new AutoCloseInputStream(locatorFactory.locate(resourceUri)); final int length = IOUtils.copy(is, outputStream); // servlet engine may ignore this if content body is flushed to client response.setContentLength(length); response.setStatus(HttpServletResponse.SC_OK); } finally { IOUtils.closeQuietly(is); IOUtils.closeQuietly(outputStream); } } else { response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } /** * Used to identify whether the {@link HttpServletResponse#SC_NOT_MODIFIED} or {@link HttpServletResponse#SC_OK} * should be returned. Currently a single timestamp is used to detect the change for all resources. This might be no * accurate, but at least it allows sending NOT_MODIFIED header much often resulting in less load on the server. *

* Override this method if a different way detecting change is required. * * @return true if the requested resource is changed on the server and the latest version should be returned. */ protected boolean isResourceChanged(final HttpServletRequest request) { try { final long ifModifiedSince = request.getDateHeader(HttpHeader.IF_MODIFIED_SINCE.toString()); return ifModifiedSince < getHeadersConfigurer().getLastModifiedTimestamp(); } catch (final Exception e) { LOG.warn("Could not extract IF_MODIFIED_SINCE header for request: " + request.getRequestURI() + ". Assuming content is changed. ", e); return true; } } private void verifyAccess(final HttpServletRequest request, final HttpServletResponse response) { final String resourceUri = getResourceUri(request); if (!authManager.isAuthorized(resourceUri)) { LOG.debug("[FAIL] Unauthorized proxy resource: {}", resourceUri); response.setStatus(HttpServletResponse.SC_FORBIDDEN); throw new UnauthorizedRequestException("Unauthorized resource request detected: " + resourceUri); } } private String getResourceUri(final HttpServletRequest request) { return request.getParameter(PARAM_RESOURCE_ID); } private final ResponseHeadersConfigurer getHeadersConfigurer() { if (headersConfigurer == null) { headersConfigurer = newResponseHeadersConfigurer(); } return headersConfigurer; } /** * @return the {@link ResponseHeadersConfigurer}. */ protected ResponseHeadersConfigurer newResponseHeadersConfigurer() { return ResponseHeadersConfigurer.fromConfig(context.getConfig()); } /** * Builds the request path for this request handler using the assumption that {@link WroFilter} has a mapping ending * with a * character. * * @param requestUri * of wro request used to compute the path to this request handler. This request uri is required, because we * do not know how the wro filter is mapped. * @return the path for this handler. */ public static String createProxyPath(final String requestUri, final String resourceId) { notNull(requestUri); notNull(resourceId); return requestUri + getRequestHandlerPath(resourceId); } /** * Checks if the provided url is a resource proxy request. * @param url * to check. * @return true if the provided url is a proxy resource. */ public static boolean isProxyUri(final String url) { notNull(url); return url.contains(getRequestHandlerPath()); } private boolean isProxyRequest(final HttpServletRequest request) { final String apiHandlerValue = request.getParameter(PATH_API); final String resourceId = request.getParameter(PARAM_RESOURCE_ID); return PATH_RESOURCES.equals(apiHandlerValue) && resourceId != null; } private static String getRequestHandlerPath() { return String.format("?%s=%s", PATH_API, PATH_RESOURCES); } private static String getRequestHandlerPath(final String resourceId) { return String.format("%s&%s=%s", getRequestHandlerPath(), PARAM_RESOURCE_ID, resourceId); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy