Package com.elibom.jogger.middleware.statik

Source Code of com.elibom.jogger.middleware.statik.StaticMiddleware

package com.elibom.jogger.middleware.statik;

import java.net.URLDecoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.elibom.jogger.Middleware;
import com.elibom.jogger.MiddlewareChain;
import com.elibom.jogger.asset.Asset;
import com.elibom.jogger.asset.AssetLoader;
import com.elibom.jogger.asset.FileAssetLoader;
import com.elibom.jogger.http.Request;
import com.elibom.jogger.http.Response;
import com.elibom.jogger.util.Preconditions;

/**
* This middleware serve static files, usually from (but not limited to) the file system. Keep in mind the following when
* using this middleware:
*
* <ol>
*   <li>It will only handle requests where its path matches the prefix configured in the middleware (e.g. the request with
* path "/assets/my_asset.gif" will be handled if the path prefix of the middleware is "assets").</li>
<li>If the path matches but the method is not GET, a <strong>404 Not Found</strong> will be returned (i.e. it won't
*  recognized other HTTP method different to GET).</li>
<li>If the asset is not found, a <strong>404 Not Found</strong> will be returned.</li>
<li>If the asset hasn't been modified (i.e. using the If-Modified-Since header), a <strong>304 Not Modified</strong> will
*  be returned.</li>
* </ol>
*
* @author German Escobar
*/
public class StaticMiddleware implements Middleware {
 
  /**
   * Used to load the assets.
   */
  private AssetLoader assetLoader;
 
  /**
   * The path prefix this middleware uses to decide to match a request.
   */
  private String prefix;

  /**
   * Constructor. Creates a new instance with the provided path and with a {@link FileAssetLoader} as the
   * {@link AssetLoader} implementation.
   *
   * @param path the prefix used to match the request path; also the path where the static files are located in the file system.
   */
  public StaticMiddleware(String path) {
    Preconditions.notNull(path, "no path provided.");
    this.prefix = fixPrefix(path);
    this.assetLoader = new FileAssetLoader(path);
  }
 
  /**
   * Helper method. Adds a leading and trailing slash if they are not present (i.e. "assets" becomes "/assets/")
   *
   * @param prefix the path to be fixed, can't be null.
   *
   * @return the prefix with leading and trailing slashes.
   */
  private String fixPrefix(String prefix) {
    String fixedPrefix = prefix.startsWith("/") ? prefix : "/" + prefix;
    return fixedPrefix.endsWith("/") ? fixedPrefix : fixedPrefix + "/";
  }
 
  /**
   * Constructor. Creates a new instance with a {@link FileAssetLoader} with the provided path, and the prefix.
   *
   * @param path the path where the static files are located in the file system.
   * @param prefix the prefix used to match the request path
   */
  public StaticMiddleware(String path, String prefix) {
    Preconditions.notNull(path, "no path provided.");
    Preconditions.notNull(prefix, "no prefix provided.");
   
    this.prefix = fixPrefix(prefix);
    this.assetLoader = new FileAssetLoader(path);
  }
 
  /**
   * Constructor. Creates a new instance with the provided asset loader and prefix.
   *
   * @param assetLoader the object used to load the assets.
   * @param prefix the prefix used to match the request path.
   */
  public StaticMiddleware(AssetLoader assetLoader, String prefix) {
    Preconditions.notNull(assetLoader, "no assetLoader provided.");
    Preconditions.notNull(prefix, "no prefix provided.");
   
    this.prefix = fixPrefix(prefix);
    this.assetLoader = assetLoader;
  }

  @Override
  public void handle(Request request, Response response, MiddlewareChain chain) throws Exception {
    // check if we have to handle the request or not
    String requestPath = fixRequestPath(request.getPath());
    if (!requestPath.startsWith(prefix)) {
      chain.next();
      return;
    }
   
    // only handle GET requests
    if (!request.getMethod().equalsIgnoreCase("get")) {
      chain.next();
      return;
    }
   
    // load the asset
    requestPath = requestPath.replaceFirst(prefix, "");
    Asset asset = assetLoader.load(URLDecoder.decode(requestPath, "UTF-8"));
    if (asset == null) {
      chain.next();
      return;
    }
   
    // check if asset has been modified
    if (!assetHasBeenModified(request, asset)) {
      response.status(Response.NOT_MODIFIED);
      return;
    }

    response.status(Response.OK);
    response.write(asset);
  }
 
  /**
   * Helper method. The request path shouldn't have a trailing slash.
   *
   * @param path the path to fix.
   * @return the path with its trailing slash
   */
  private String fixRequestPath(String path) {
    return path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
  }

  private boolean assetHasBeenModified(Request request, Asset asset) throws ParseException {
    String ifModifiedSince = request.getHeader("If-Modified-Since");
    if (ifModifiedSince != null) {
      SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
      Date dt = sdf.parse(ifModifiedSince);
      if (dt.getTime() == asset.getLastModified()) {
        return false;
      }
    }
   
    return true;
  }

}
TOP

Related Classes of com.elibom.jogger.middleware.statik.StaticMiddleware

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.