#9078 make HttpContent.getByteBuffer() implementations return new ByteBuffer instances and document that contract
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
parent
8d6734cf78
commit
177bafbace
|
@ -381,7 +381,7 @@ public class CachingHttpContentFactory implements HttpContent.Factory
|
|||
@Override
|
||||
public ByteBuffer getByteBuffer()
|
||||
{
|
||||
return _buffer;
|
||||
return _buffer == null ? null : _buffer.asReadOnlyBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -86,13 +86,13 @@ public class FileMappingHttpContentFactory implements HttpContent.Factory
|
|||
{
|
||||
ByteBuffer buffer = _buffer;
|
||||
if (buffer != null)
|
||||
return (buffer == SENTINEL_BUFFER) ? super.getByteBuffer() : buffer;
|
||||
return (buffer == SENTINEL_BUFFER) ? super.getByteBuffer() : buffer.asReadOnlyBuffer();
|
||||
|
||||
try (AutoLock lock = _lock.lock())
|
||||
{
|
||||
if (_buffer == null)
|
||||
_buffer = getMappedByteBuffer();
|
||||
return (_buffer == SENTINEL_BUFFER) ? super.getByteBuffer() : _buffer;
|
||||
return (_buffer == SENTINEL_BUFFER) ? super.getByteBuffer() : _buffer.asReadOnlyBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,12 @@ public interface HttpContent
|
|||
|
||||
Resource getResource();
|
||||
|
||||
/**
|
||||
* <p>Get this HTTP content as a {@link ByteBuffer} if possible.</p>
|
||||
* <p>Each invocation returns a new {@link ByteBuffer} instance that is
|
||||
* read-only and contains valid data between the pos and the limit.</p>
|
||||
* @return a {@link ByteBuffer} instance or null.
|
||||
*/
|
||||
ByteBuffer getByteBuffer();
|
||||
|
||||
default long getBytesOccupied()
|
||||
|
|
|
@ -641,7 +641,7 @@ public class ResourceService
|
|||
{
|
||||
try
|
||||
{
|
||||
ByteBuffer buffer = content.getByteBuffer();
|
||||
ByteBuffer buffer = content.getByteBuffer(); // this buffer is going to be consumed by response.write()
|
||||
if (buffer != null)
|
||||
response.write(true, buffer, callback);
|
||||
else
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.ee10.webapp;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class WebAppDefaultServletCacheTest
|
||||
{
|
||||
private LocalConnector connector;
|
||||
private Server server;
|
||||
private Path resourcePath;
|
||||
|
||||
@BeforeEach
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
connector = new LocalConnector(server);
|
||||
server.addConnector(connector);
|
||||
|
||||
URI uri = getClass().getResource("/org/acme").toURI();
|
||||
resourcePath = Paths.get(uri);
|
||||
server.addHandler(new WebAppContext(uri.toString(), "/"));
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheRefreshing() throws Exception
|
||||
{
|
||||
String fileName = "jetty-pic.png";
|
||||
long fileSize = Files.size(resourcePath.resolve(fileName));
|
||||
|
||||
HttpTester.Response response1 = sendRequest(fileName);
|
||||
assertEquals(response1.getLongField("Content-Length"), fileSize);
|
||||
assertEquals(200, response1.getStatus());
|
||||
|
||||
HttpTester.Response response2 = sendRequest(fileName, "If-Modified-Since: " + response1.get("Last-Modified"));
|
||||
assertEquals(response2.getLongField("Content-Length"), 0L);
|
||||
assertEquals(304, response2.getStatus());
|
||||
|
||||
HttpTester.Response response3 = sendRequest(fileName, "Cache-Control: no-cache", "Pragma: no-cache");
|
||||
assertEquals(response3.getLongField("Content-Length"), fileSize);
|
||||
assertEquals(200, response3.getStatus());
|
||||
}
|
||||
|
||||
private HttpTester.Response sendRequest(String file, String... extraHeaders) throws Exception
|
||||
{
|
||||
StringBuilder rawRequest = new StringBuilder();
|
||||
rawRequest.append("GET /").append(file).append(" HTTP/1.1\r\n");
|
||||
rawRequest.append("Host: local\r\n");
|
||||
for (String extraHeader : extraHeaders)
|
||||
{
|
||||
rawRequest.append(extraHeader).append("\r\n");
|
||||
}
|
||||
rawRequest.append("\r\n");
|
||||
String rawResponse = connector.getResponse(rawRequest.toString());
|
||||
return HttpTester.parseResponse(rawResponse);
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 482 KiB |
Loading…
Reference in New Issue