kopia lustrzana https://github.com/gaul/s3proxy
Add NoCacheBlobStore
rodzic
664a94dbd5
commit
b0ffdd47f3
|
@ -115,6 +115,7 @@ S3Proxy can modify its behavior based on middlewares:
|
||||||
* [sharded backend containers](https://github.com/gaul/s3proxy/wiki/Middleware-sharded-backend)
|
* [sharded backend containers](https://github.com/gaul/s3proxy/wiki/Middleware-sharded-backend)
|
||||||
* [storage class override](https://github.com/gaul/s3proxy/wiki/Middleware-storage-class-override)
|
* [storage class override](https://github.com/gaul/s3proxy/wiki/Middleware-storage-class-override)
|
||||||
* [user metadata replacer](https://github.com/gaul/s3proxy/wiki/Middleware-user-metadata-replacer)
|
* [user metadata replacer](https://github.com/gaul/s3proxy/wiki/Middleware-user-metadata-replacer)
|
||||||
|
* [no cache override](https://github.com/gaul/s3proxy/wiki/Middleware-no-cache)
|
||||||
|
|
||||||
## SSL Support
|
## SSL Support
|
||||||
|
|
||||||
|
|
|
@ -314,6 +314,14 @@ public final class Main {
|
||||||
blobStore = LatencyBlobStore.newLatencyBlobStore(blobStore, latencies, speeds);
|
blobStore = LatencyBlobStore.newLatencyBlobStore(blobStore, latencies, speeds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String noCacheBlobStore = properties.getProperty(
|
||||||
|
S3ProxyConstants.PROPERTY_NO_CACHE_BLOBSTORE);
|
||||||
|
if ("true".equalsIgnoreCase(noCacheBlobStore)) {
|
||||||
|
System.err.println("Using no-cache storage backend middleware");
|
||||||
|
blobStore = NoCacheBlobStore
|
||||||
|
.newNoCacheBlobStore(blobStore);
|
||||||
|
}
|
||||||
|
|
||||||
return blobStore;
|
return blobStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014-2025 Andrew Gaul <andrew@gaul.org>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* https://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 org.gaul.s3proxy;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.BlobStore;
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.options.GetOptions;
|
||||||
|
import org.jclouds.blobstore.util.ForwardingBlobStore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BlobStore which drops eTag or date based cache options from object requests.
|
||||||
|
* This is useful as the JClouds library does not fully support the proxying of HTTP 304 responses.
|
||||||
|
*/
|
||||||
|
final class NoCacheBlobStore extends ForwardingBlobStore {
|
||||||
|
|
||||||
|
private NoCacheBlobStore(BlobStore blobStore) {
|
||||||
|
super(blobStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlobStore newNoCacheBlobStore(BlobStore blobStore) {
|
||||||
|
return new NoCacheBlobStore(blobStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Blob getBlob(String containerName, String name) {
|
||||||
|
return getBlob(containerName, name, new GetOptions());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Blob getBlob(String containerName, String name, GetOptions getOptions) {
|
||||||
|
return super.getBlob(containerName, name, resetCacheHeaders(getOptions));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GetOptions resetCacheHeaders(GetOptions options) {
|
||||||
|
if (options.getIfMatch() != null || options.getIfNoneMatch() != null ||
|
||||||
|
options.getIfModifiedSince() != null || options.getIfUnmodifiedSince() != null) {
|
||||||
|
// as there is no exposed method to reset just the cache headers, a copy is used
|
||||||
|
GetOptions optionsNoCache = new GetOptions();
|
||||||
|
for (String range : options.getRanges()) {
|
||||||
|
String[] ranges = range.split("-", 2);
|
||||||
|
if (ranges[0].isEmpty()) {
|
||||||
|
optionsNoCache.tail(Long.parseLong(ranges[1]));
|
||||||
|
} else if (ranges[1].isEmpty()) {
|
||||||
|
optionsNoCache.startAt(Long.parseLong(ranges[0]));
|
||||||
|
} else {
|
||||||
|
optionsNoCache.range(Long.parseLong(ranges[0]), Long.parseLong(ranges[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return optionsNoCache;
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -138,6 +138,9 @@ public final class S3ProxyConstants {
|
||||||
public static final String PROPERTY_LATENCY =
|
public static final String PROPERTY_LATENCY =
|
||||||
"s3proxy.latency-blobstore";
|
"s3proxy.latency-blobstore";
|
||||||
|
|
||||||
|
public static final String PROPERTY_NO_CACHE_BLOBSTORE =
|
||||||
|
"s3proxy.no-cache-blobstore";
|
||||||
|
|
||||||
static final String PROPERTY_ALT_JCLOUDS_PREFIX = "alt.";
|
static final String PROPERTY_ALT_JCLOUDS_PREFIX = "alt.";
|
||||||
|
|
||||||
private S3ProxyConstants() {
|
private S3ProxyConstants() {
|
||||||
|
|
|
@ -25,6 +25,7 @@ exec java \
|
||||||
-Ds3proxy.encrypted-blobstore-salt="${S3PROXY_ENCRYPTED_BLOBSTORE_SALT}" \
|
-Ds3proxy.encrypted-blobstore-salt="${S3PROXY_ENCRYPTED_BLOBSTORE_SALT}" \
|
||||||
-Ds3proxy.v4-max-non-chunked-request-size="${S3PROXY_V4_MAX_NON_CHUNKED_REQ_SIZE:-134217728}" \
|
-Ds3proxy.v4-max-non-chunked-request-size="${S3PROXY_V4_MAX_NON_CHUNKED_REQ_SIZE:-134217728}" \
|
||||||
-Ds3proxy.read-only-blobstore="${S3PROXY_READ_ONLY_BLOBSTORE:-false}" \
|
-Ds3proxy.read-only-blobstore="${S3PROXY_READ_ONLY_BLOBSTORE:-false}" \
|
||||||
|
-Ds3proxy.no-cache-blobstore="${S3PROXY_NO_CACHE_BLOBSTORE:-false}" \
|
||||||
-Ds3proxy.maximum-timeskew="${S3PROXY_MAXIMUM_TIMESKEW}" \
|
-Ds3proxy.maximum-timeskew="${S3PROXY_MAXIMUM_TIMESKEW}" \
|
||||||
-Ds3proxy.service-path="${S3PROXY_SERVICE_PATH}" \
|
-Ds3proxy.service-path="${S3PROXY_SERVICE_PATH}" \
|
||||||
-Djclouds.provider="${JCLOUDS_PROVIDER}" \
|
-Djclouds.provider="${JCLOUDS_PROVIDER}" \
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014-2025 Andrew Gaul <andrew@gaul.org>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* https://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 org.gaul.s3proxy;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.options.GetOptions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public final class NoCacheBlobStoreTest {
|
||||||
|
@Test
|
||||||
|
public void testResetCacheHeadersKeepRange() {
|
||||||
|
var options = GetOptions.Builder.range(1, 5);
|
||||||
|
var optionsResult = NoCacheBlobStore.resetCacheHeaders(options);
|
||||||
|
assertThat(optionsResult.getRanges()).isEqualTo(options.getRanges());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResetCacheHeadersKeepTail() {
|
||||||
|
var options = GetOptions.Builder.range(1, 5).tail(3).startAt(10);
|
||||||
|
var optionsResult = NoCacheBlobStore.resetCacheHeaders(options);
|
||||||
|
assertThat(optionsResult.getRanges()).isEqualTo(options.getRanges());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResetCacheHeadersRangeDropCache() {
|
||||||
|
var options = GetOptions.Builder
|
||||||
|
.range(1, 5)
|
||||||
|
.tail(3)
|
||||||
|
.startAt(10)
|
||||||
|
.ifETagDoesntMatch("abc")
|
||||||
|
.ifModifiedSince(Date.from(Instant.EPOCH));
|
||||||
|
var optionsResult = NoCacheBlobStore.resetCacheHeaders(options);
|
||||||
|
assertThat(optionsResult.getRanges()).isEqualTo(options.getRanges());
|
||||||
|
assertThat(optionsResult.getIfNoneMatch()).isEqualTo(null);
|
||||||
|
assertThat(optionsResult.getIfModifiedSince()).isEqualTo((Date) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResetCacheHeadersNoRange() {
|
||||||
|
var options = GetOptions.Builder
|
||||||
|
.ifETagMatches("abc")
|
||||||
|
.ifUnmodifiedSince(Date.from(Instant.EPOCH));
|
||||||
|
var optionsResult = NoCacheBlobStore.resetCacheHeaders(options);
|
||||||
|
assertThat(optionsResult.getRanges()).isEqualTo(options.getRanges());
|
||||||
|
assertThat(optionsResult.getIfMatch()).isEqualTo(null);
|
||||||
|
assertThat(optionsResult.getIfUnmodifiedSince()).isEqualTo((Date) null);
|
||||||
|
}
|
||||||
|
}
|
Ładowanie…
Reference in New Issue