Search in sources :

Example 1 with RangeAwareResource

use of io.undertow.server.handlers.resource.RangeAwareResource in project undertow by undertow-io.

the class DefaultServlet method serveFileBlocking.

private void serveFileBlocking(final HttpServletRequest req, final HttpServletResponse resp, final Resource resource) throws IOException {
    final ETag etag = resource.getETag();
    final Date lastModified = resource.getLastModified();
    if (req.getDispatcherType() != DispatcherType.INCLUDE) {
        if (!ETagUtils.handleIfMatch(req.getHeader(Headers.IF_MATCH_STRING), etag, false) || !DateUtils.handleIfUnmodifiedSince(req.getHeader(Headers.IF_UNMODIFIED_SINCE_STRING), lastModified)) {
            resp.setStatus(StatusCodes.PRECONDITION_FAILED);
            return;
        }
        if (!ETagUtils.handleIfNoneMatch(req.getHeader(Headers.IF_NONE_MATCH_STRING), etag, true) || !DateUtils.handleIfModifiedSince(req.getHeader(Headers.IF_MODIFIED_SINCE_STRING), lastModified)) {
            resp.setStatus(StatusCodes.NOT_MODIFIED);
            return;
        }
    }
    //we are going to proceed. Set the appropriate headers
    if (resp.getContentType() == null) {
        if (!resource.isDirectory()) {
            final String contentType = deployment.getServletContext().getMimeType(resource.getName());
            if (contentType != null) {
                resp.setContentType(contentType);
            } else {
                resp.setContentType("application/octet-stream");
            }
        }
    }
    if (lastModified != null) {
        resp.setHeader(Headers.LAST_MODIFIED_STRING, resource.getLastModifiedString());
    }
    if (etag != null) {
        resp.setHeader(Headers.ETAG_STRING, etag.toString());
    }
    ByteRange.RangeResponseResult rangeResponse = null;
    long start = -1, end = -1;
    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
        //we also can't deal with range requests if a writer is in use
        Long contentLength = resource.getContentLength();
        if (contentLength != null) {
            resp.getOutputStream();
            if (contentLength > Integer.MAX_VALUE) {
                resp.setContentLengthLong(contentLength);
            } else {
                resp.setContentLength(contentLength.intValue());
            }
            if (resource instanceof RangeAwareResource && ((RangeAwareResource) resource).isRangeSupported() && resource.getContentLength() != null) {
                resp.setHeader(Headers.ACCEPT_RANGES_STRING, "bytes");
                //TODO: figure out what to do with the content encoded resource manager
                final ByteRange range = ByteRange.parse(req.getHeader(Headers.RANGE_STRING));
                if (range != null) {
                    rangeResponse = range.getResponseResult(resource.getContentLength(), req.getHeader(Headers.IF_RANGE_STRING), resource.getLastModified(), resource.getETag() == null ? null : resource.getETag().getTag());
                    if (rangeResponse != null) {
                        start = rangeResponse.getStart();
                        end = rangeResponse.getEnd();
                        resp.setStatus(rangeResponse.getStatusCode());
                        resp.setHeader(Headers.CONTENT_RANGE_STRING, rangeResponse.getContentRange());
                        long length = rangeResponse.getContentLength();
                        if (length > Integer.MAX_VALUE) {
                            resp.setContentLengthLong(length);
                        } else {
                            resp.setContentLength((int) length);
                        }
                        if (rangeResponse.getStatusCode() == StatusCodes.REQUEST_RANGE_NOT_SATISFIABLE) {
                            return;
                        }
                    }
                }
            }
        }
    } catch (IllegalStateException e) {
    }
    final boolean include = req.getDispatcherType() == DispatcherType.INCLUDE;
    if (!req.getMethod().equals(Methods.HEAD_STRING)) {
        HttpServerExchange exchange = SecurityActions.requireCurrentServletRequestContext().getOriginalRequest().getExchange();
        if (rangeResponse == null) {
            resource.serve(exchange.getResponseSender(), exchange, completionCallback(include));
        } else {
            ((RangeAwareResource) resource).serveRange(exchange.getResponseSender(), exchange, start, end, completionCallback(include));
        }
    }
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) ETag(io.undertow.util.ETag) ByteRange(io.undertow.util.ByteRange) RangeAwareResource(io.undertow.server.handlers.resource.RangeAwareResource) Date(java.util.Date)

Aggregations

HttpServerExchange (io.undertow.server.HttpServerExchange)1 RangeAwareResource (io.undertow.server.handlers.resource.RangeAwareResource)1 ByteRange (io.undertow.util.ByteRange)1 ETag (io.undertow.util.ETag)1 Date (java.util.Date)1