Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2014 Red Hat, Inc., and individual contributors
   * as indicated by the @author tags.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
 
 package io.undertow.servlet.handlers;
 
 
 import java.io.File;
 import java.util.Date;
 import java.util.Set;

Default servlet responsible for serving up resources. This is both a handler and a servlet. If no filters match the current path then the resources will be served up asynchronously using the io.undertow.server.HttpHandler.handleRequest(io.undertow.server.HttpServerExchange) method, otherwise the request is handled as a normal servlet request.

By default we only allow a restricted set of extensions.

todo: this thing needs a lot more work. In particular: - caching for blocking requests - correct mime type - range/last-modified and other headers to be handled properly - head requests - and probably heaps of other things

Author(s):
Stuart Douglas
 
 public class DefaultServlet extends HttpServlet {
 
     public static final String DIRECTORY_LISTING = "directory-listing";
     public static final String DEFAULT_ALLOWED = "default-allowed";
     public static final String ALLOWED_EXTENSIONS = "allowed-extensions";
     public static final String DISALLOWED_EXTENSIONS = "disallowed-extensions";
     public static final String RESOLVE_AGAINST_CONTEXT_ROOT = "resolve-against-context-root";
 
     private static final Set<StringDEFAULT_ALLOWED_EXTENSIONS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("js""css""png""jpg""gif""html""htm""txt""pdf""jpeg""xml")));
 
 
     private Deployment deployment;
     private ResourceManager resourceManager;
     private boolean directoryListingEnabled = false;
 
     private boolean defaultAllowed = true;
     private Set<Stringdisallowed = Collections.emptySet();
     private boolean resolveAgainstContextRoot;
 
     @Override
     public void init(ServletConfig configthrows ServletException {
         super.init(config);
         ServletContextImpl sc = (ServletContextImplconfig.getServletContext();
         this. = sc.getDeployment();
         DefaultServletConfig defaultServletConfig = .getDeploymentInfo().getDefaultServletConfig();
         if (defaultServletConfig != null) {
              = defaultServletConfig.isDefaultAllowed();
              = new HashSet<>();
             if (defaultServletConfig.getAllowed() != null) {
                .addAll(defaultServletConfig.getAllowed());
            }
             = new HashSet<>();
            if (defaultServletConfig.getDisallowed() != null) {
                .addAll(defaultServletConfig.getDisallowed());
            }
        }
        if (config.getInitParameter() != null) {
             = Boolean.parseBoolean(config.getInitParameter());
        }
        if (config.getInitParameter() != null) {
            String extensions = config.getInitParameter();
             = new HashSet<>(Arrays.asList(extensions.split(",")));
        }
        if (config.getInitParameter() != null) {
            String extensions = config.getInitParameter();
             = new HashSet<>(Arrays.asList(extensions.split(",")));
        }
        if (config.getInitParameter() != null) {
        }
        String listings = config.getInitParameter();
        if (Boolean.valueOf(listings)) {
            this. = true;
        }
    }
    @Override
    protected void doGet(final HttpServletRequest reqfinal HttpServletResponse respthrows ServletExceptionIOException {
        String path = getPath(req);
        if (!isAllowed(pathreq.getDispatcherType())) {
            resp.sendError(404);
            return;
        }
        if(. != '/') {
            //if the separator char is not / we want to replace it with a / and canonicalise
            path = CanonicalPathUtils.canonicalize(path.replace(.'/'));
        }
        final Resource resource;
        //we want to disallow windows characters in the path
        if(. == '/' || !path.contains(.)) {
            resource = .getResource(path);
        } else {
            resource = null;
        }
        if (resource == null) {
            if (req.getDispatcherType() == .) {
                //servlet 9.3
                throw new FileNotFoundException(path);
            } else {
                resp.sendError(404);
            }
            return;
        } else if (resource.isDirectory()) {
            if ("css".equals(req.getQueryString())) {
                resp.setContentType("text/css");
                resp.getWriter().write(..);
                return;
            } else if ("js".equals(req.getQueryString())) {
                resp.setContentType("application/javascript");
                resp.getWriter().write(..);
                return;
            }
            if () {
                StringBuilder output = DirectoryUtils.renderDirectoryListing(req.getRequestURI(), resource);
                resp.getWriter().write(output.toString());
            } else {
                resp.sendError(403);
            }
        } else {
            serveFileBlocking(reqrespresource);
        }
    }
    @Override
    protected void doPost(HttpServletRequest reqHttpServletResponse respthrows ServletExceptionIOException {
        /*
         * Where a servlet has received a POST request we still require the capability to include static content.
         */
        switch (req.getDispatcherType()) {
            case :
            case :
            case :
                doGet(reqresp);
                break;
            default:
                super.doPost(reqresp);
        }
    }
    @Override
    protected void doPut(HttpServletRequest reqHttpServletResponse respthrows ServletExceptionIOException {
        switch (req.getDispatcherType()) {
            case :
            case :
            case :
                doGet(reqresp);
                break;
            default:
                super.doPut(reqresp);
        }
    }
    @Override
    protected void doDelete(HttpServletRequest reqHttpServletResponse respthrows ServletExceptionIOException {
        switch (req.getDispatcherType()) {
            case :
            case :
            case :
                doGet(reqresp);
                break;
            default:
                super.doDelete(reqresp);
        }
    }
    @Override
    protected void doOptions(HttpServletRequest reqHttpServletResponse respthrows ServletExceptionIOException {
        switch (req.getDispatcherType()) {
            case :
            case :
            case :
                doGet(reqresp);
                break;
            default:
                super.doOptions(reqresp);
        }
    }
    @Override
    protected void doTrace(HttpServletRequest reqHttpServletResponse respthrows ServletExceptionIOException {
        switch (req.getDispatcherType()) {
            case :
            case :
            case :
                doGet(reqresp);
                break;
            default:
                super.doTrace(reqresp);
        }
    }
    private void serveFileBlocking(final HttpServletRequest reqfinal HttpServletResponse respfinal Resource resourcethrows IOException {
        final ETag etag = resource.getETag();
        final Date lastModified = resource.getLastModified();
        if (!ETagUtils.handleIfMatch(req.getHeader(.), etagfalse) ||
                !DateUtils.handleIfUnmodifiedSince(req.getHeader(.), lastModified)) {
            resp.setStatus(412);
            return;
        }
        if (!ETagUtils.handleIfNoneMatch(req.getHeader(.), etagtrue) ||
                !DateUtils.handleIfModifiedSince(req.getHeader(.), lastModified)) {
            resp.setStatus(304);
            return;
        }
        //todo: handle range requests
        //we are going to proceed. Set the appropriate headers
        if(resp.getContentType() == null) {
            final String contentType = .getServletContext().getMimeType(resource.getName());
            if (contentType != null) {
                resp.setContentType(contentType);
            } else {
                resp.setContentType("application/octet-stream");
            }
        }
        if (lastModified != null) {
            resp.setHeader(.resource.getLastModifiedString());
        }
        if (etag != null) {
            resp.setHeader(.etag.toString());
        }
        try {
            //only set the content length if we are using a stream
            //if we are using a writer who knows what the length will end up being
            //todo: if someone installs a filter this can cause problems
            //not sure how best to deal with this
            Long contentLength = resource.getContentLength();
            if (contentLength != null) {
                resp.getOutputStream();
                resp.setContentLengthLong(contentLength);
            }
        } catch (IllegalStateException e) {
        }
        final boolean include = req.getDispatcherType() == .;
        if (!req.getMethod().equals(.)) {
            HttpServerExchange exchange = SecurityActions.requireCurrentServletRequestContext().getOriginalRequest().getExchange();
            resource.serve(exchange.getResponseSender(), exchangenew IoCallback() {
                @Override
                public void onComplete(final HttpServerExchange exchangefinal Sender sender) {
                    if (!include) {
                        sender.close();
                    }
                }
                @Override
                public void onException(final HttpServerExchange exchangefinal Sender senderfinal IOException exception) {
                    //not much we can do here, the connection is broken
                    sender.close();
                }
            });
        }
    }
    private String getPath(final HttpServletRequest request) {
        String servletPath;
        String pathInfo;
        if (request.getDispatcherType() == . && request.getAttribute(.) != null) {
            pathInfo = (Stringrequest.getAttribute(.);
            servletPath = (Stringrequest.getAttribute(.);
        } else {
            pathInfo = request.getPathInfo();
            servletPath = request.getServletPath();
        }
        String result = pathInfo;
        if (result == null) {
            result = servletPath;
        } else if() {
            result = servletPath + CanonicalPathUtils.canonicalize(pathInfo);
        } else {
            result = CanonicalPathUtils.canonicalize(result);
        }
        if ((result == null) || (result.equals(""))) {
            result = "/";
        }
        return result;
    }
    private boolean isAllowed(String pathDispatcherType dispatcherType) {
        if (!path.isEmpty()) {
            if(dispatcherType == .) {
                //WFLY-3543 allow the dispatcher to access stuff in web-inf and meta inf
                if (path.startsWith("/META-INF") ||
                        path.startsWith("META-INF") ||
                        path.startsWith("/WEB-INF") ||
                        path.startsWith("WEB-INF")) {
                    return false;
                }
            }
        }
        int pos = path.lastIndexOf('/');
        final String lastSegment;
        if (pos == -1) {
            lastSegment = path;
        } else {
            lastSegment = path.substring(pos + 1);
        }
        if (lastSegment.isEmpty()) {
            return true;
        }
        int ext = lastSegment.lastIndexOf('.');
        if (ext == -1) {
            //no extension
            return true;
        }
        final String extension = lastSegment.substring(ext + 1, lastSegment.length());
        if () {
            return !.contains(extension);
        } else {
            return .contains(extension);
        }
    }
New to GrepCode? Check out our FAQ X