diff options
Diffstat (limited to 'jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java')
-rw-r--r-- | jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java | 751 |
1 files changed, 317 insertions, 434 deletions
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java index b937c2fbf9..adeb05def1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java @@ -19,43 +19,35 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.nio.ByteBuffer; -import java.nio.channels.ReadableByteChannel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; -import javax.servlet.AsyncContext; -import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.MimeTypes; -import org.eclipse.jetty.io.WriterOutputStream; -import org.eclipse.jetty.server.HttpOutput; +import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.server.ResourceContentFactory; +import org.eclipse.jetty.server.ResourceService; import org.eclipse.jetty.server.handler.ContextHandler.Context; -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.resource.PathResource; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.ResourceFactory; - /* ------------------------------------------------------------ */ -/** Resource Handler. +/** + * Resource Handler. * - * This handle will serve static content and handle If-Modified-Since headers. - * No caching is done. - * Requests for resources that do not exist are let pass (Eg no 404's). + * This handle will serve static content and handle If-Modified-Since headers. No caching is done. Requests for resources that do not exist are let pass (Eg no + * 404's). * * */ @@ -63,577 +55,468 @@ public class ResourceHandler extends HandlerWrapper implements ResourceFactory { private static final Logger LOG = Log.getLogger(ResourceHandler.class); - ContextHandler _context; Resource _baseResource; + ContextHandler _context; Resource _defaultStylesheet; - Resource _stylesheet; - String[] _welcomeFiles={"index.html"}; MimeTypes _mimeTypes; - String _cacheControl; - boolean _directory; - boolean _gzip; - boolean _etags; - int _minMemoryMappedContentLength=0; - int _minAsyncContentLength=16*1024; + private final ResourceService _resourceService; + Resource _stylesheet; + String[] _welcomes = + { "index.html" }; /* ------------------------------------------------------------ */ public ResourceHandler() { + _resourceService = new ResourceService() + { + @Override + protected String getWelcomeFile(String pathInContext) + { + if (_welcomes == null) + return null; + + String welcome_servlet = null; + for (int i = 0; i < _welcomes.length; i++) + { + String welcome_in_context = URIUtil.addPaths(pathInContext,_welcomes[i]); + Resource welcome = getResource(welcome_in_context); + if (welcome != null && welcome.exists()) + return _welcomes[i]; + } + return welcome_servlet; + } + @Override + protected void notFound(HttpServletRequest request, HttpServletResponse response) throws IOException + { + } + }; + _resourceService.setGzipEquivalentFileExtensions(new ArrayList<>(Arrays.asList(new String[] + { ".svgz" }))); } /* ------------------------------------------------------------ */ - public MimeTypes getMimeTypes() + @Override + public void doStart() throws Exception { - return _mimeTypes; + Context scontext = ContextHandler.getCurrentContext(); + _context = (scontext == null?null:scontext.getContextHandler()); + _mimeTypes = _context == null?new MimeTypes():_context.getMimeTypes(); + + _resourceService.setContentFactory(new ResourceContentFactory(this,_mimeTypes,_resourceService.isGzip())); + + super.doStart(); } /* ------------------------------------------------------------ */ - public void setMimeTypes(MimeTypes mimeTypes) + /** + * @return Returns the resourceBase. + */ + public Resource getBaseResource() { - _mimeTypes = mimeTypes; + if (_baseResource == null) + return null; + return _baseResource; } /* ------------------------------------------------------------ */ - /** Get the directory option. - * @return true if directories are listed. + /** + * @return the cacheControl header to set on all static content. */ - public boolean isDirectoriesListed() + public String getCacheControl() { - return _directory; + return _resourceService.getCacheControl().getValue(); } /* ------------------------------------------------------------ */ - /** Set the directory. - * @param directory true if directories are listed. + /** + * @return file extensions that signify that a file is gzip compressed. Eg ".svgz" */ - public void setDirectoriesListed(boolean directory) + public List<String> getGzipEquivalentFileExtensions() { - _directory = directory; + return _resourceService.getGzipEquivalentFileExtensions(); } /* ------------------------------------------------------------ */ - /** Get minimum memory mapped file content length. - * @return the minimum size in bytes of a file resource that will - * be served using a memory mapped buffer, or -1 (default) for no memory mapped - * buffers. - */ - public int getMinMemoryMappedContentLength() + public MimeTypes getMimeTypes() { - return _minMemoryMappedContentLength; + return _mimeTypes; } /* ------------------------------------------------------------ */ - /** Set minimum memory mapped file content length. - * @param minMemoryMappedFileSize the minimum size in bytes of a file resource that will - * be served using a memory mapped buffer, or -1 for no memory mapped - * buffers. + /** + * Get the minimum content length for async handling. + * + * @return The minimum size in bytes of the content before asynchronous handling is used, or -1 for no async handling or 0 (default) for using + * {@link HttpServletResponse#getBufferSize()} as the minimum length. */ - public void setMinMemoryMappedContentLength(int minMemoryMappedFileSize) + @Deprecated + public int getMinAsyncContentLength() { - _minMemoryMappedContentLength = minMemoryMappedFileSize; + return -1; } /* ------------------------------------------------------------ */ - /** Get the minimum content length for async handling. - * @return The minimum size in bytes of the content before asynchronous - * handling is used, or -1 for no async handling or 0 (default) for using - * {@link HttpServletResponse#getBufferSize()} as the minimum length. + /** + * Get minimum memory mapped file content length. + * + * @return the minimum size in bytes of a file resource that will be served using a memory mapped buffer, or -1 (default) for no memory mapped buffers. */ - public int getMinAsyncContentLength() + @Deprecated + public int getMinMemoryMappedContentLength() { - return _minAsyncContentLength; + return -1; } /* ------------------------------------------------------------ */ - /** Set the minimum content length for async handling. - * @param minAsyncContentLength The minimum size in bytes of the content before asynchronous - * handling is used, or -1 for no async handling or 0 for using - * {@link HttpServletResponse#getBufferSize()} as the minimum length. + /* */ - public void setMinAsyncContentLength(int minAsyncContentLength) + @Override + public Resource getResource(String path) { - _minAsyncContentLength = minAsyncContentLength; + if (LOG.isDebugEnabled()) + LOG.debug("{} getResource({})",_context == null?_baseResource:_context,_baseResource,path); + + if (path == null || !path.startsWith("/")) + return null; + + try + { + Resource r = null; + + if (_baseResource != null) + { + path = URIUtil.canonicalPath(path); + r = _baseResource.addPath(path); + + if (r != null && r.isAlias() && (_context == null || !_context.checkAlias(path,r))) + { + if (LOG.isDebugEnabled()) + LOG.debug("resource={} alias={}",r,r.getAlias()); + return null; + } + } + else if (_context != null) + r = _context.getResource(path); + + if ((r == null || !r.exists()) && path.endsWith("/jetty-dir.css")) + r = getStylesheet(); + + return r; + } + catch (Exception e) + { + LOG.debug(e); + } + + return null; } /* ------------------------------------------------------------ */ /** - * @return True if ETag processing is done + * @return Returns the base resource as a string. */ - public boolean isEtags() + public String getResourceBase() { - return _etags; + if (_baseResource == null) + return null; + return _baseResource.toString(); } /* ------------------------------------------------------------ */ /** - * @param etags True if ETag processing is done + * @return Returns the stylesheet as a Resource. */ - public void setEtags(boolean etags) + public Resource getStylesheet() { - _etags = etags; + if (_stylesheet != null) + { + return _stylesheet; + } + else + { + if (_defaultStylesheet == null) + { + _defaultStylesheet = Resource.newResource(this.getClass().getResource("/jetty-dir.css")); + } + return _defaultStylesheet; + } } /* ------------------------------------------------------------ */ - @Override - public void doStart() - throws Exception + public String[] getWelcomeFiles() { - Context scontext = ContextHandler.getCurrentContext(); - _context = (scontext==null?null:scontext.getContextHandler()); - _mimeTypes = _context==null?new MimeTypes():_context.getMimeTypes(); - - super.doStart(); + return _welcomes; } /* ------------------------------------------------------------ */ - /** - * @return Returns the resourceBase. + /* + * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int) */ - public Resource getBaseResource() + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - if (_baseResource==null) - return null; - return _baseResource; + if (baseRequest.isHandled()) + return; + + if (!HttpMethod.GET.is(request.getMethod())) + { + if (!HttpMethod.HEAD.is(request.getMethod())) + { + // try another handler + super.handle(target,baseRequest,request,response); + return; + } + } + + _resourceService.doGet(request,response); + + if (response.isCommitted()) + baseRequest.setHandled(true); + else + // no resource - try other handlers + super.handle(target,baseRequest,request,response); } /* ------------------------------------------------------------ */ /** - * @return Returns the base resource as a string. + * @return If true, range requests and responses are supported */ - public String getResourceBase() + public boolean isAcceptRanges() { - if (_baseResource==null) - return null; - return _baseResource.toString(); + return _resourceService.isAcceptRanges(); } + /** + * @return If true, directory listings are returned if no welcome file is found. Else 403 Forbidden. + */ + public boolean isDirAllowed() + { + return _resourceService.isDirAllowed(); + } /* ------------------------------------------------------------ */ /** - * @param base The resourceBase to set. + * Get the directory option. + * + * @return true if directories are listed. */ - public void setBaseResource(Resource base) + public boolean isDirectoriesListed() { - _baseResource=base; + return _resourceService.isDirAllowed(); } /* ------------------------------------------------------------ */ /** - * @param resourceBase The base resource as a string. + * @return True if ETag processing is done */ - public void setResourceBase(String resourceBase) + public boolean isEtags() { - try - { - setBaseResource(Resource.newResource(resourceBase)); - } - catch (Exception e) - { - LOG.warn(e.toString()); - LOG.debug(e); - throw new IllegalArgumentException(resourceBase); - } + return _resourceService.isEtags(); } - + /* ------------------------------------------------------------ */ /** - * @return Returns the stylesheet as a Resource. + * @return If set to true, then static content will be served as gzip content encoded if a matching resource is found ending with ".gz" */ - public Resource getStylesheet() + public boolean isGzip() { - if(_stylesheet != null) - { - return _stylesheet; - } - else - { - if(_defaultStylesheet == null) - { - _defaultStylesheet = Resource.newResource(this.getClass().getResource("/jetty-dir.css")); - } - return _defaultStylesheet; - } + return _resourceService.isGzip(); } /* ------------------------------------------------------------ */ /** - * @param stylesheet The location of the stylesheet to be used as a String. + * @return true, only the path info will be applied to the resourceBase */ - public void setStylesheet(String stylesheet) + public boolean isPathInfoOnly() { - try - { - _stylesheet = Resource.newResource(stylesheet); - if(!_stylesheet.exists()) - { - LOG.warn("unable to find custom stylesheet: " + stylesheet); - _stylesheet = null; - } - } - catch(Exception e) - { - LOG.warn(e.toString()); - LOG.debug(e); - throw new IllegalArgumentException(stylesheet); - } + return _resourceService.isPathInfoOnly(); } /* ------------------------------------------------------------ */ /** - * @return the cacheControl header to set on all static content. + * @return If true, welcome files are redirected rather than forwarded to. */ - public String getCacheControl() + public boolean isRedirectWelcome() { - return _cacheControl; + return _resourceService.isRedirectWelcome(); } /* ------------------------------------------------------------ */ /** - * @param cacheControl the cacheControl header to set on all static content. + * @param acceptRanges If true, range requests and responses are supported */ - public void setCacheControl(String cacheControl) + public void setAcceptRanges(boolean acceptRanges) { - _cacheControl=cacheControl; + _resourceService.setAcceptRanges(acceptRanges); } /* ------------------------------------------------------------ */ - /* + /** + * @param base The resourceBase to server content from. If null the + * context resource base is used. */ - @Override - public Resource getResource(String path) + public void setBaseResource(Resource base) { - if (LOG.isDebugEnabled()) - LOG.debug("{} getResource({})",_context==null?_baseResource:_context,_baseResource,path); - - if (path==null || !path.startsWith("/")) - return null; - - try - { - Resource base = _baseResource; - if (base==null) - { - if (_context==null) - return null; - return _context.getResource(path); - } - - path=URIUtil.canonicalPath(path); - Resource r = base.addPath(path); - if (r!=null && r.isAlias() && (_context==null || !_context.checkAlias(path, r))) - { - if (LOG.isDebugEnabled()) - LOG.debug("resource={} alias={}",r,r.getAlias()); - return null; - } - return r; - } - catch(Exception e) - { - LOG.debug(e); - } - - return null; + _baseResource = base; } /* ------------------------------------------------------------ */ - protected Resource getResource(HttpServletRequest request) throws MalformedURLException + /** + * @param cacheControl + * the cacheControl header to set on all static content. + */ + public void setCacheControl(String cacheControl) { - String servletPath; - String pathInfo; - Boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; - if (included != null && included.booleanValue()) - { - servletPath = (String)request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); - pathInfo = (String)request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO); + _resourceService.setCacheControl(new PreEncodedHttpField(HttpHeader.CACHE_CONTROL,cacheControl)); + } - if (servletPath == null && pathInfo == null) - { - servletPath = request.getServletPath(); - pathInfo = request.getPathInfo(); - } - } - else - { - servletPath = request.getServletPath(); - pathInfo = request.getPathInfo(); - } + /** + * @param dirAllowed + * If true, directory listings are returned if no welcome file is found. Else 403 Forbidden. + */ + public void setDirAllowed(boolean dirAllowed) + { + _resourceService.setDirAllowed(dirAllowed); + } - String pathInContext=URIUtil.addPaths(servletPath,pathInfo); - return getResource(pathInContext); + /* ------------------------------------------------------------ */ + /** + * Set the directory. + * + * @param directory + * true if directories are listed. + */ + public void setDirectoriesListed(boolean directory) + { + _resourceService.setDirAllowed(directory); } + /* ------------------------------------------------------------ */ + /** + * @param etags + * True if ETag processing is done + */ + public void setEtags(boolean etags) + { + _resourceService.setEtags(etags); + } /* ------------------------------------------------------------ */ - public String[] getWelcomeFiles() + /** + * @param gzip + * If set to true, then static content will be served as gzip content encoded if a matching resource is found ending with ".gz" + */ + public void setGzip(boolean gzip) { - return _welcomeFiles; + _resourceService.setGzip(gzip); } /* ------------------------------------------------------------ */ - public void setWelcomeFiles(String[] welcomeFiles) + /** + * @param gzipEquivalentFileExtensions file extensions that signify that a file is gzip compressed. Eg ".svgz" + */ + public void setGzipEquivalentFileExtensions(List<String> gzipEquivalentFileExtensions) { - _welcomeFiles=welcomeFiles; + _resourceService.setGzipEquivalentFileExtensions(gzipEquivalentFileExtensions); } /* ------------------------------------------------------------ */ - protected Resource getWelcome(Resource directory) throws MalformedURLException, IOException + public void setMimeTypes(MimeTypes mimeTypes) { - for (int i=0;i<_welcomeFiles.length;i++) - { - Resource welcome=directory.addPath(_welcomeFiles[i]); - if (welcome.exists() && !welcome.isDirectory()) - return welcome; - } + _mimeTypes = mimeTypes; + } - return null; + /* ------------------------------------------------------------ */ + /** + * Set the minimum content length for async handling. + * + * @param minAsyncContentLength + * The minimum size in bytes of the content before asynchronous handling is used, or -1 for no async handling or 0 for using + * {@link HttpServletResponse#getBufferSize()} as the minimum length. + */ + @Deprecated + public void setMinAsyncContentLength(int minAsyncContentLength) + { } /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int) + /** + * Set minimum memory mapped file content length. + * + * @param minMemoryMappedFileSize + * the minimum size in bytes of a file resource that will be served using a memory mapped buffer, or -1 for no memory mapped buffers. */ - @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + @Deprecated + public void setMinMemoryMappedContentLength(int minMemoryMappedFileSize) { - if (baseRequest.isHandled()) - return; + } - boolean skipContentBody = false; + /** + * @param pathInfoOnly + * true, only the path info will be applied to the resourceBase + */ + public void setPathInfoOnly(boolean pathInfoOnly) + { + _resourceService.setPathInfoOnly(pathInfoOnly); + } - if(!HttpMethod.GET.is(request.getMethod())) - { - if(!HttpMethod.HEAD.is(request.getMethod())) - { - //try another handler - super.handle(target, baseRequest, request, response); - return; - } - skipContentBody = true; - } + /** + * @param redirectWelcome + * If true, welcome files are redirected rather than forwarded to. + */ + public void setRedirectWelcome(boolean redirectWelcome) + { + _resourceService.setRedirectWelcome(redirectWelcome); + } - Resource resource = getResource(request); - - if (LOG.isDebugEnabled()) - { - if (resource==null) - LOG.debug("resource=null"); - else - LOG.debug("resource={} alias={} exists={}",resource,resource.getAlias(),resource.exists()); - } - - - // If resource is not found - if (resource==null || !resource.exists()) + /* ------------------------------------------------------------ */ + /** + * @param resourceBase + * The base resource as a string. + */ + public void setResourceBase(String resourceBase) + { + try { - // inject the jetty-dir.css file if it matches - if (target.endsWith("/jetty-dir.css")) - { - resource = getStylesheet(); - if (resource==null) - return; - response.setContentType("text/css"); - } - else - { - //no resource - try other handlers - super.handle(target, baseRequest, request, response); - return; - } + setBaseResource(Resource.newResource(resourceBase)); } - - // We are going to serve something - baseRequest.setHandled(true); - - // handle directories - if (resource.isDirectory()) + catch (Exception e) { - String pathInfo = request.getPathInfo(); - boolean endsWithSlash=(pathInfo==null?request.getServletPath():pathInfo).endsWith(URIUtil.SLASH); - if (!endsWithSlash) - { - response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getRequestURI(),URIUtil.SLASH))); - return; - } - - Resource welcome=getWelcome(resource); - if (welcome!=null && welcome.exists()) - resource=welcome; - else - { - doDirectory(request,response,resource); - baseRequest.setHandled(true); - return; - } + LOG.warn(e.toString()); + LOG.debug(e); + throw new IllegalArgumentException(resourceBase); } + } - // Handle ETAGS - long last_modified=resource.lastModified(); - String etag=null; - if (_etags) - { - // simple handling of only a single etag - String ifnm = request.getHeader(HttpHeader.IF_NONE_MATCH.asString()); - etag=resource.getWeakETag(); - if (ifnm!=null && resource!=null && ifnm.equals(etag)) - { - response.setStatus(HttpStatus.NOT_MODIFIED_304); - baseRequest.getResponse().getHttpFields().put(HttpHeader.ETAG,etag); - return; - } - } - - // Handle if modified since - if (last_modified>0) + /* ------------------------------------------------------------ */ + /** + * @param stylesheet + * The location of the stylesheet to be used as a String. + */ + public void setStylesheet(String stylesheet) + { + try { - long if_modified=request.getDateHeader(HttpHeader.IF_MODIFIED_SINCE.asString()); - if (if_modified>0 && last_modified/1000<=if_modified/1000) + _stylesheet = Resource.newResource(stylesheet); + if (!_stylesheet.exists()) { - response.setStatus(HttpStatus.NOT_MODIFIED_304); - return; + LOG.warn("unable to find custom stylesheet: " + stylesheet); + _stylesheet = null; } } - - // set the headers - String mime=_mimeTypes.getMimeByExtension(resource.toString()); - if (mime==null) - mime=_mimeTypes.getMimeByExtension(request.getPathInfo()); - doResponseHeaders(response,resource,mime); - if (_etags) - baseRequest.getResponse().getHttpFields().put(HttpHeader.ETAG,etag); - if (last_modified>0) - response.setDateHeader(HttpHeader.LAST_MODIFIED.asString(),last_modified); - - if(skipContentBody) - return; - - // Send the content - OutputStream out =null; - try {out = response.getOutputStream();} - catch(IllegalStateException e) {out = new WriterOutputStream(response.getWriter());} - - // Has the output been wrapped - if (!(out instanceof HttpOutput)) - // Write content via wrapped output - resource.writeTo(out,0,resource.length()); - else + catch (Exception e) { - // select async by size - int min_async_size=_minAsyncContentLength==0?response.getBufferSize():_minAsyncContentLength; - - if (request.isAsyncSupported() && - min_async_size>0 && - resource.length()>=min_async_size) - { - final AsyncContext async = request.startAsync(); - async.setTimeout(0); - Callback callback = new Callback() - { - @Override - public void succeeded() - { - async.complete(); - } - - @Override - public void failed(Throwable x) - { - LOG.warn(x.toString()); - LOG.debug(x); - async.complete(); - } - }; - - // Can we use a memory mapped file? - if (_minMemoryMappedContentLength>0 && - resource.length()>_minMemoryMappedContentLength && - resource.length()<Integer.MAX_VALUE && - resource instanceof PathResource) - { - ByteBuffer buffer = BufferUtil.toMappedBuffer(resource.getFile()); - ((HttpOutput)out).sendContent(buffer,callback); - } - else // Do a blocking write of a channel (if available) or input stream - { - // Close of the channel/inputstream is done by the async sendContent - ReadableByteChannel channel= resource.getReadableByteChannel(); - if (channel!=null) - ((HttpOutput)out).sendContent(channel,callback); - else - ((HttpOutput)out).sendContent(resource.getInputStream(),callback); - } - } - else - { - // Can we use a memory mapped file? - if (_minMemoryMappedContentLength>0 && - resource.length()>_minMemoryMappedContentLength && - resource instanceof PathResource) - { - ByteBuffer buffer = BufferUtil.toMappedBuffer(resource.getFile()); - ((HttpOutput)out).sendContent(buffer); - } - else // Do a blocking write of a channel (if available) or input stream - { - ReadableByteChannel channel= resource.getReadableByteChannel(); - if (channel!=null) - ((HttpOutput)out).sendContent(channel); - else - ((HttpOutput)out).sendContent(resource.getInputStream()); - } - } + LOG.warn(e.toString()); + LOG.debug(e); + throw new IllegalArgumentException(stylesheet); } } /* ------------------------------------------------------------ */ - protected void doDirectory(HttpServletRequest request,HttpServletResponse response, Resource resource) - throws IOException + public void setWelcomeFiles(String[] welcomeFiles) { - if (_directory) - { - String listing = resource.getListHTML(request.getRequestURI(),request.getPathInfo().lastIndexOf("/") > 0); - response.setContentType("text/html;charset=utf-8"); - response.getWriter().println(listing); - } - else - response.sendError(HttpStatus.FORBIDDEN_403); + _welcomes = welcomeFiles; } - /* ------------------------------------------------------------ */ - /** Set the response headers. - * This method is called to set the response headers such as content type and content length. - * May be extended to add additional headers. - * @param response the http response - * @param resource the resource - * @param mimeType the mime type - */ - protected void doResponseHeaders(HttpServletResponse response, Resource resource, String mimeType) - { - if (mimeType!=null) - response.setContentType(mimeType); - - long length=resource.length(); - - if (response instanceof Response) - { - HttpFields fields = ((Response)response).getHttpFields(); - - if (length>0) - ((Response)response).setLongContentLength(length); - - if (_cacheControl!=null) - fields.put(HttpHeader.CACHE_CONTROL,_cacheControl); - } - else - { - if (length>Integer.MAX_VALUE) - response.setHeader(HttpHeader.CONTENT_LENGTH.asString(),Long.toString(length)); - else if (length>0) - response.setContentLength((int)length); - - if (_cacheControl!=null) - response.setHeader(HttpHeader.CACHE_CONTROL.asString(),_cacheControl); - } - } } |