Search in sources :

Example 1 with ResponseCache

use of io.undertow.server.handlers.cache.ResponseCache in project undertow by undertow-io.

the class CacheHandlerTestCase method testBasicPathBasedCaching.

@Test
public void testBasicPathBasedCaching() throws IOException {
    final AtomicInteger responseCount = new AtomicInteger();
    final HttpHandler messageHandler = new HttpHandler() {

        @Override
        public void handleRequest(final HttpServerExchange exchange) throws Exception {
            final ResponseCache cache = exchange.getAttachment(ResponseCache.ATTACHMENT_KEY);
            if (!cache.tryServeResponse()) {
                final String data = "Response " + responseCount.incrementAndGet();
                exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, data.length() + "");
                exchange.getResponseSender().send(data);
            }
        }
    };
    final CacheHandler cacheHandler = new CacheHandler(new DirectBufferCache(100, 10, 1000), messageHandler);
    DefaultServer.setRootHandler(cacheHandler);
    TestHttpClient client = new TestHttpClient();
    try {
        HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/path");
        // it takes 5 hits to make an entry actually get cached
        for (int i = 1; i <= 5; ++i) {
            HttpResponse result = client.execute(get);
            Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
            Assert.assertEquals("Response " + i, HttpClientUtils.readResponse(result));
        }
        HttpResponse result = client.execute(get);
        Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
        Assert.assertEquals("Response 5", HttpClientUtils.readResponse(result));
        result = client.execute(get);
        Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
        Assert.assertEquals("Response 5", HttpClientUtils.readResponse(result));
        result = client.execute(get);
        Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
        Assert.assertEquals("Response 5", HttpClientUtils.readResponse(result));
        get = new HttpGet(DefaultServer.getDefaultServerURL() + "/path2");
        result = client.execute(get);
        Assert.assertEquals(StatusCodes.OK, result.getStatusLine().getStatusCode());
        Assert.assertEquals("Response 6", HttpClientUtils.readResponse(result));
    } finally {
        client.getConnectionManager().shutdown();
    }
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) HttpHandler(io.undertow.server.HttpHandler) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) HttpGet(org.apache.http.client.methods.HttpGet) DirectBufferCache(io.undertow.server.handlers.cache.DirectBufferCache) HttpResponse(org.apache.http.HttpResponse) ResponseCache(io.undertow.server.handlers.cache.ResponseCache) CacheHandler(io.undertow.server.handlers.cache.CacheHandler) TestHttpClient(io.undertow.testutils.TestHttpClient) Test(org.junit.Test)

Example 2 with ResponseCache

use of io.undertow.server.handlers.cache.ResponseCache in project undertow by undertow-io.

the class ResourceHandler method serveResource.

private void serveResource(final HttpServerExchange exchange, final boolean sendContent) throws Exception {
    if (DirectoryUtils.sendRequestedBlobs(exchange)) {
        return;
    }
    if (!allowed.resolve(exchange)) {
        exchange.setStatusCode(StatusCodes.FORBIDDEN);
        exchange.endExchange();
        return;
    }
    ResponseCache cache = exchange.getAttachment(ResponseCache.ATTACHMENT_KEY);
    final boolean cachable = this.cachable.resolve(exchange);
    // we set caching headers before we try and serve from the cache
    if (cachable && cacheTime != null) {
        exchange.getResponseHeaders().put(Headers.CACHE_CONTROL, "public, max-age=" + cacheTime);
        long date = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(cacheTime);
        String dateHeader = DateUtils.toDateString(new Date(date));
        exchange.getResponseHeaders().put(Headers.EXPIRES, dateHeader);
    }
    if (cache != null && cachable) {
        if (cache.tryServeResponse()) {
            return;
        }
    }
    // we now dispatch to a worker thread
    // as resource manager methods are potentially blocking
    HttpHandler dispatchTask = new HttpHandler() {

        @Override
        public void handleRequest(HttpServerExchange exchange) throws Exception {
            Resource resource = null;
            try {
                if (File.separatorChar == '/' || !exchange.getRelativePath().contains(File.separator)) {
                    // we don't process resources that contain the sperator character if this is not /
                    // this prevents attacks where people use windows path seperators in file URLS's
                    resource = resourceSupplier.getResource(exchange, canonicalize(exchange.getRelativePath()));
                }
            } catch (IOException e) {
                clearCacheHeaders(exchange);
                UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
                exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                exchange.endExchange();
                return;
            }
            if (resource == null) {
                clearCacheHeaders(exchange);
                // usually a 404 handler
                next.handleRequest(exchange);
                return;
            }
            if (resource.isDirectory()) {
                Resource indexResource;
                try {
                    indexResource = getIndexFiles(exchange, resourceSupplier, resource.getPath(), welcomeFiles);
                } catch (IOException e) {
                    UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
                    exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                    exchange.endExchange();
                    return;
                }
                if (indexResource == null) {
                    if (directoryListingEnabled) {
                        DirectoryUtils.renderDirectoryListing(exchange, resource);
                        return;
                    } else {
                        exchange.setStatusCode(StatusCodes.FORBIDDEN);
                        exchange.endExchange();
                        return;
                    }
                } else if (!exchange.getRequestPath().endsWith("/")) {
                    exchange.setStatusCode(StatusCodes.FOUND);
                    exchange.getResponseHeaders().put(Headers.LOCATION, RedirectBuilder.redirect(exchange, exchange.getRelativePath() + "/", true));
                    exchange.endExchange();
                    return;
                }
                resource = indexResource;
            } else if (exchange.getRelativePath().endsWith("/")) {
                // UNDERTOW-432
                exchange.setStatusCode(StatusCodes.NOT_FOUND);
                exchange.endExchange();
                return;
            }
            final ETag etag = resource.getETag();
            final Date lastModified = resource.getLastModified();
            if (!ETagUtils.handleIfMatch(exchange, etag, false) || !DateUtils.handleIfUnmodifiedSince(exchange, lastModified)) {
                exchange.setStatusCode(StatusCodes.PRECONDITION_FAILED);
                exchange.endExchange();
                return;
            }
            if (!ETagUtils.handleIfNoneMatch(exchange, etag, true) || !DateUtils.handleIfModifiedSince(exchange, lastModified)) {
                exchange.setStatusCode(StatusCodes.NOT_MODIFIED);
                exchange.endExchange();
                return;
            }
            final ContentEncodedResourceManager contentEncodedResourceManager = ResourceHandler.this.contentEncodedResourceManager;
            Long contentLength = resource.getContentLength();
            if (contentLength != null && !exchange.getResponseHeaders().contains(Headers.TRANSFER_ENCODING)) {
                exchange.setResponseContentLength(contentLength);
            }
            ByteRange.RangeResponseResult rangeResponse = null;
            long start = -1, end = -1;
            if (resource instanceof RangeAwareResource && ((RangeAwareResource) resource).isRangeSupported() && contentLength != null && contentEncodedResourceManager == null) {
                exchange.getResponseHeaders().put(Headers.ACCEPT_RANGES, "bytes");
                // TODO: figure out what to do with the content encoded resource manager
                ByteRange range = ByteRange.parse(exchange.getRequestHeaders().getFirst(Headers.RANGE));
                if (range != null && range.getRanges() == 1 && resource.getContentLength() != null) {
                    rangeResponse = range.getResponseResult(resource.getContentLength(), exchange.getRequestHeaders().getFirst(Headers.IF_RANGE), resource.getLastModified(), resource.getETag() == null ? null : resource.getETag().getTag());
                    if (rangeResponse != null) {
                        start = rangeResponse.getStart();
                        end = rangeResponse.getEnd();
                        exchange.setStatusCode(rangeResponse.getStatusCode());
                        exchange.getResponseHeaders().put(Headers.CONTENT_RANGE, rangeResponse.getContentRange());
                        long length = rangeResponse.getContentLength();
                        exchange.setResponseContentLength(length);
                        if (rangeResponse.getStatusCode() == StatusCodes.REQUEST_RANGE_NOT_SATISFIABLE) {
                            return;
                        }
                    }
                }
            }
            if (!exchange.getResponseHeaders().contains(Headers.CONTENT_TYPE)) {
                final String contentType = resource.getContentType(mimeMappings);
                if (contentType != null) {
                    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, contentType);
                } else {
                    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/octet-stream");
                }
            }
            if (lastModified != null) {
                exchange.getResponseHeaders().put(Headers.LAST_MODIFIED, resource.getLastModifiedString());
            }
            if (etag != null) {
                exchange.getResponseHeaders().put(Headers.ETAG, etag.toString());
            }
            if (contentEncodedResourceManager != null) {
                try {
                    ContentEncodedResource encoded = contentEncodedResourceManager.getResource(resource, exchange);
                    if (encoded != null) {
                        exchange.getResponseHeaders().put(Headers.CONTENT_ENCODING, encoded.getContentEncoding());
                        exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, encoded.getResource().getContentLength());
                        encoded.getResource().serve(exchange.getResponseSender(), exchange, IoCallback.END_EXCHANGE);
                        return;
                    }
                } catch (IOException e) {
                    // TODO: should this be fatal
                    UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
                    exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                    exchange.endExchange();
                    return;
                }
            }
            if (!sendContent) {
                exchange.endExchange();
            } else if (rangeResponse != null) {
                ((RangeAwareResource) resource).serveRange(exchange.getResponseSender(), exchange, start, end, IoCallback.END_EXCHANGE);
            } else {
                resource.serve(exchange.getResponseSender(), exchange, IoCallback.END_EXCHANGE);
            }
        }
    };
    if (exchange.isInIoThread()) {
        exchange.dispatch(dispatchTask);
    } else {
        dispatchTask.handleRequest(exchange);
    }
}
Also used : HttpHandler(io.undertow.server.HttpHandler) ByteRange(io.undertow.util.ByteRange) ContentEncodedResource(io.undertow.server.handlers.encoding.ContentEncodedResource) HttpString(io.undertow.util.HttpString) IOException(java.io.IOException) ContentEncodedResource(io.undertow.server.handlers.encoding.ContentEncodedResource) Date(java.util.Date) HttpServerExchange(io.undertow.server.HttpServerExchange) ContentEncodedResourceManager(io.undertow.server.handlers.encoding.ContentEncodedResourceManager) ETag(io.undertow.util.ETag) ResponseCache(io.undertow.server.handlers.cache.ResponseCache)

Aggregations

HttpHandler (io.undertow.server.HttpHandler)2 HttpServerExchange (io.undertow.server.HttpServerExchange)2 ResponseCache (io.undertow.server.handlers.cache.ResponseCache)2 CacheHandler (io.undertow.server.handlers.cache.CacheHandler)1 DirectBufferCache (io.undertow.server.handlers.cache.DirectBufferCache)1 ContentEncodedResource (io.undertow.server.handlers.encoding.ContentEncodedResource)1 ContentEncodedResourceManager (io.undertow.server.handlers.encoding.ContentEncodedResourceManager)1 TestHttpClient (io.undertow.testutils.TestHttpClient)1 ByteRange (io.undertow.util.ByteRange)1 ETag (io.undertow.util.ETag)1 HttpString (io.undertow.util.HttpString)1 IOException (java.io.IOException)1 Date (java.util.Date)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 HttpResponse (org.apache.http.HttpResponse)1 HttpGet (org.apache.http.client.methods.HttpGet)1 Test (org.junit.Test)1