/*
* Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.grizzly.http.server;
import java.io.File;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.glassfish.grizzly.Grizzly;
import org.glassfish.grizzly.http.Method;
import org.glassfish.grizzly.http.util.Header;
import org.glassfish.grizzly.http.util.HttpStatus;
import org.glassfish.grizzly.utils.ArraySet;
HttpHandler
, which processes requests to a static resources. Author: Jeanfrancois Arcand, Alexey Stashok
/**
* {@link HttpHandler}, which processes requests to a static resources.
*
* @author Jeanfrancois Arcand
* @author Alexey Stashok
*/
public class StaticHttpHandler extends StaticHttpHandlerBase {
private static final Logger LOGGER = Grizzly.logger(StaticHttpHandler.class);
protected final ArraySet<File> docRoots = new ArraySet<>(File.class);
private boolean directorySlashOff;
Create HttpHandler, which, by default, will handle requests to the static resources located in the current
directory.
/**
* Create <tt>HttpHandler</tt>, which, by default, will handle requests to the static resources located in the current
* directory.
*/
public StaticHttpHandler() {
addDocRoot(".");
}
Create a new instance which will look for static pages located under the docRoot. If the docRoot is
null - static pages won't be served by this HttpHandler
Params: - docRoots – the folder(s) where the static resource are located. If the docRoot is null -
static pages won't be served by this HttpHandler
/**
* Create a new instance which will look for static pages located under the <tt>docRoot</tt>. If the <tt>docRoot</tt> is
* <tt>null</tt> - static pages won't be served by this <tt>HttpHandler</tt>
*
* @param docRoots the folder(s) where the static resource are located. If the <tt>docRoot</tt> is <tt>null</tt> -
* static pages won't be served by this <tt>HttpHandler</tt>
*/
public StaticHttpHandler(String... docRoots) {
if (docRoots != null) {
for (String docRoot : docRoots) {
addDocRoot(docRoot);
}
}
}
Create a new instance which will look for static pages located under the docRoot. If the docRoot is
null - static pages won't be served by this HttpHandler
Params: - docRoots – the folders where the static resource are located. If the docRoot is empty - static pages
won't be served by this HttpHandler
/**
* Create a new instance which will look for static pages located under the <tt>docRoot</tt>. If the <tt>docRoot</tt> is
* <tt>null</tt> - static pages won't be served by this <tt>HttpHandler</tt>
*
* @param docRoots the folders where the static resource are located. If the <tt>docRoot</tt> is empty - static pages
* won't be served by this <tt>HttpHandler</tt>
*/
@SuppressWarnings("UnusedDeclaration")
public StaticHttpHandler(Set<String> docRoots) {
if (docRoots != null) {
for (String docRoot : docRoots) {
addDocRoot(docRoot);
}
}
}
Return the default directory from where files will be serviced.
Returns: the default directory from where file will be serviced.
/**
* Return the default directory from where files will be serviced.
*
* @return the default directory from where file will be serviced.
*/
@SuppressWarnings("UnusedDeclaration")
public File getDefaultDocRoot() {
final File[] array = docRoots.getArray();
return array != null && array.length > 0 ? array[0] : null;
}
Return the list of directories where files will be serviced from.
Returns: the list of directories where files will be serviced from.
/**
* Return the list of directories where files will be serviced from.
*
* @return the list of directories where files will be serviced from.
*/
public ArraySet<File> getDocRoots() {
return docRoots;
}
Add the directory to the list of directories where files will be serviced from.
Params: - docRoot – the directory to be added to the list of directories where files will be serviced from.
Returns: return the File
representation of the passed docRoot
.
/**
* Add the directory to the list of directories where files will be serviced from.
*
* @param docRoot the directory to be added to the list of directories where files will be serviced from.
*
* @return return the {@link File} representation of the passed <code>docRoot</code>.
*/
public final File addDocRoot(String docRoot) {
if (docRoot == null) {
throw new NullPointerException("docRoot can't be null");
}
final File file = new File(docRoot);
addDocRoot(file);
return file;
}
Add the directory to the list of directories where files will be serviced from.
Params: - docRoot – the directory to be added to the list of directories where files will be serviced from.
/**
* Add the directory to the list of directories where files will be serviced from.
*
* @param docRoot the directory to be added to the list of directories where files will be serviced from.
*/
public final void addDocRoot(File docRoot) {
docRoots.add(docRoot);
}
Removes the directory from the list of directories where static files will be serviced from.
Params: - docRoot – the directory to remove.
/**
* Removes the directory from the list of directories where static files will be serviced from.
*
* @param docRoot the directory to remove.
*/
@SuppressWarnings("UnusedDeclaration")
public void removeDocRoot(File docRoot) {
docRoots.remove(docRoot);
}
Returns: true if HTTP 301 redirect shouldn't be sent when requested static resource is a directory, or
false otherwise
/**
* @return <tt>true</tt> if HTTP 301 redirect shouldn't be sent when requested static resource is a directory, or
* <tt>false</tt> otherwise
*/
public boolean isDirectorySlashOff() {
return directorySlashOff;
}
If the directorySlashOff is true HTTP 301 redirect will not be sent when requested static resource is a
directory.
Params: - directorySlashOff –
/**
* If the directorySlashOff is <tt>true</tt> HTTP 301 redirect will not be sent when requested static resource is a
* directory.
*
* @param directorySlashOff
*/
public void setDirectorySlashOff(boolean directorySlashOff) {
this.directorySlashOff = directorySlashOff;
}
// ------------------------------------------------------- Protected Methods
{@inheritDoc}
/**
* {@inheritDoc}
*/
@Override
protected boolean handle(final String uri, final Request request, final Response response) throws Exception {
boolean found = false;
final File[] fileFolders = docRoots.getArray();
if (fileFolders == null) {
return false;
}
File resource = null;
for (int i = 0; i < fileFolders.length; i++) {
final File webDir = fileFolders[i];
// local file
resource = new File(webDir, uri);
final boolean exists = resource.exists();
final boolean isDirectory = resource.isDirectory();
if (exists && isDirectory) {
if (!directorySlashOff && !uri.endsWith("/")) { // redirect to the same url, but with trailing slash
response.setStatus(HttpStatus.MOVED_PERMANENTLY_301);
response.setHeader(Header.Location, response.encodeRedirectURL(uri + "/"));
return true;
}
final File f = new File(resource, "/index.html");
if (f.exists()) {
resource = f;
found = true;
break;
}
}
if (isDirectory || !exists) {
found = false;
} else {
found = true;
break;
}
}
if (!found) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "File not found {0}", resource);
}
return false;
}
assert resource != null;
// If it's not HTTP GET - return method is not supported status
if (!Method.GET.equals(request.getMethod())) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "File found {0}, but HTTP method {1} is not allowed", new Object[] { resource, request.getMethod() });
}
response.setStatus(HttpStatus.METHOD_NOT_ALLOWED_405);
response.setHeader(Header.Allow, "GET");
return true;
}
pickupContentType(response, resource.getPath());
addToFileCache(request, response, resource);
sendFile(response, resource);
return true;
}
}