Commit 264aa6ba authored by Matija Obreza's avatar Matija Obreza

Repository download: Check request headers and return NOT_MODIFIED if cache is valid

- Also fixed _thumb origin headers
parent 2a013e40
......@@ -19,6 +19,7 @@ package org.genesys2.server.api.v1;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
......@@ -35,6 +36,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -58,44 +60,56 @@ public class RepositoryDownloadController {
@Autowired
private BytesStorageService byteStorageService;
private void downloadFile(final String path, final String uuid, final String ext, final HttpServletResponse response) throws IOException {
private void downloadFile(final Path path, final String name, final String ext, final HttpServletResponse response, HttpServletRequest request) throws IOException {
byte[] data;
boolean noCache = "no-cache".equalsIgnoreCase(request.getHeader(HttpHeaders.CACHE_CONTROL))
|| "no-cache".equalsIgnoreCase(request.getHeader(HttpHeaders.PRAGMA));
if (path.startsWith(ImageGalleryService.THUMB_PATH) && ext.equals(ImageGalleryService.THUMB_EXT)) {
final String filename = uuid + ext;
final String filename = name + ext;
if (LOG.isDebugEnabled()) {
LOG.debug("_thumb path={} filename={}", path, filename);
}
data = this.byteStorageService.get(Paths.get(path, filename));
if (data == null) {
throw new NotFoundElement("No thumbnail at " + Paths.get(path, filename));
}
try {
final RepositoryFile repositoryFile = this.repositoryService.getFile(UUID.fromString(uuid));
// TODO check Request Cache headers (Modified-Since, ETag)
final RepositoryFile repositoryFile = this.repositoryService.getFile(UUID.fromString(path.getFileName().toString()));
// check Request Cache headers (Modified-Since, ETag)
if (! noCache && clientCacheValid(repositoryFile, request, response)) {
LOG.debug("Client cache is valid.");
return;
}
response.setDateHeader(HttpHeaders.LAST_MODIFIED, repositoryFile.getLastModifiedDate().getTime());
response.setHeader(HttpHeaders.ETAG, repositoryFile.getSha1Sum());
} catch (NoSuchRepositoryFileException e) {
throw new NotFoundElement("No file for thumb " + uuid);
throw new NotFoundElement("No file for thumb " + name);
}
data = this.byteStorageService.get(path.resolve(filename));
if (data == null) {
throw new NotFoundElement("No thumbnail at " + path.resolve(filename));
}
response.setContentType("image/png");
// Cache for 24hrs
response.setHeader(HttpHeaders.CACHE_CONTROL, "max-age=86400, s-maxage=86400, public, no-transform");
} else {
// Regular repository file
try {
final RepositoryFile repositoryFile = this.repositoryService.getFile(UUID.fromString(uuid));
final RepositoryFile repositoryFile = this.repositoryService.getFile(UUID.fromString(name));
sanityCheck(Paths.get(path), ext, repositoryFile);
sanityCheck(path, ext, repositoryFile);
// TODO check Request Cache headers (Modified-Since, ETag)
// check Request Cache headers (Modified-Since, ETag)
if (! noCache && clientCacheValid(repositoryFile, request, response)) {
LOG.debug("Client cache is valid.");
return;
}
data = this.repositoryService.getFileBytes(repositoryFile);
......@@ -126,6 +140,23 @@ public class RepositoryDownloadController {
}
}
private boolean clientCacheValid(RepositoryFile repositoryFile, HttpServletRequest request, HttpServletResponse response) throws IOException {
if (repositoryFile.getSha1Sum().equals(request.getHeader(HttpHeaders.IF_NONE_MATCH))) {
LOG.debug("ETag matches");
response.setStatus(HttpStatus.NOT_MODIFIED.value());
response.flushBuffer();
return true;
}
long sinceDate = request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
if (sinceDate >= -1 && repositoryFile.getLastModifiedDate().getTime() < sinceDate) {
LOG.debug("Not modified since: {} < {}", repositoryFile.getLastModifiedBy(), new Date(sinceDate));
response.setStatus(HttpStatus.NOT_MODIFIED.value());
response.flushBuffer();
return true;
}
return false;
}
private void sanityCheck(final Path path, final String ext, final RepositoryFile repositoryFile) {
if (repositoryFile == null) {
throw new ResourceNotFoundException("No such thing");
......@@ -149,14 +180,20 @@ public class RepositoryDownloadController {
}
final String ext = fullpath.substring(fullpath.lastIndexOf("."));
final String uuid = fullpath.substring(fullpath.lastIndexOf("/") + 1, fullpath.lastIndexOf("."));
final String name = fullpath.substring(fullpath.lastIndexOf("/") + 1, fullpath.lastIndexOf("."));
final String path = fullpath.substring(0, fullpath.lastIndexOf('/'));
if (LOG.isDebugEnabled()) {
LOG.debug("{} {}", path, uuid + ext);
LOG.debug("{} {}", path, name + ext);
// Enumeration<String> headerNames = request.getHeaderNames();
// while (headerNames.hasMoreElements()) {
// String headerName = headerNames.nextElement();
// LOG.debug(">> {}: {}", headerName, request.getHeader(headerName));
// }
}
downloadFile(path, uuid, ext, response);
downloadFile(Paths.get(path), name, ext, response, request);
}
/**
......
......@@ -19,6 +19,7 @@ package org.genesys2.server.mvc;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
......@@ -35,6 +36,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -53,44 +55,56 @@ public class RepositoryDownloadController extends BaseController {
@Autowired
private BytesStorageService byteStorageService;
private void downloadFile(final String path, final String uuid, final String ext, final HttpServletResponse response) throws IOException {
private void downloadFile(final Path path, final String name, final String ext, final HttpServletResponse response, HttpServletRequest request) throws IOException {
byte[] data;
boolean noCache = "no-cache".equalsIgnoreCase(request.getHeader(HttpHeaders.CACHE_CONTROL))
|| "no-cache".equalsIgnoreCase(request.getHeader(HttpHeaders.PRAGMA));
if (path.startsWith(ImageGalleryService.THUMB_PATH) && ext.equals(ImageGalleryService.THUMB_EXT)) {
final String filename = uuid + ext;
final String filename = name + ext;
if (LOG.isDebugEnabled()) {
LOG.debug("_thumb path={} filename={}", path, filename);
}
data = this.byteStorageService.get(Paths.get(path, filename));
if (data == null) {
throw new NotFoundElement("No thumbnail at " + Paths.get(path, filename));
}
try {
final RepositoryFile repositoryFile = this.repositoryService.getFile(UUID.fromString(uuid));
final RepositoryFile repositoryFile = this.repositoryService.getFile(UUID.fromString(path.getFileName().toString()));
// check Request Cache headers (Modified-Since, ETag)
if (! noCache && clientCacheValid(repositoryFile, request, response)) {
LOG.debug("Client cache is valid.");
return;
}
// TODO check Request Cache headers (Modified-Since, ETag)
response.setDateHeader(HttpHeaders.LAST_MODIFIED, repositoryFile.getLastModifiedDate().getTime());
response.setHeader(HttpHeaders.ETAG, repositoryFile.getSha1Sum());
} catch (NoSuchRepositoryFileException e) {
throw new NotFoundElement("No file for thumb " + uuid);
throw new NotFoundElement("No file for thumb " + name);
}
data = this.byteStorageService.get(path.resolve(filename));
if (data == null) {
throw new NotFoundElement("No thumbnail at " + path.resolve(filename));
}
response.setContentType("image/png");
// Cache for 24hrs
response.setHeader(HttpHeaders.CACHE_CONTROL, "max-age=86400, s-maxage=86400, public, no-transform");
} else {
// Regular repo file
// Regular repository file
try {
final RepositoryFile repositoryFile = this.repositoryService.getFile(UUID.fromString(uuid));
final RepositoryFile repositoryFile = this.repositoryService.getFile(UUID.fromString(name));
sanityCheck(Paths.get(path), ext, repositoryFile);
sanityCheck(path, ext, repositoryFile);
// TODO check Request Cache headers (Modified-Since, ETag)
// check Request Cache headers (Modified-Since, ETag)
if (! noCache && clientCacheValid(repositoryFile, request, response)) {
LOG.debug("Client cache is valid.");
return;
}
data = this.repositoryService.getFileBytes(repositoryFile);
......@@ -114,8 +128,28 @@ public class RepositoryDownloadController extends BaseController {
if (data != null) {
response.setContentLength(data.length);
response.getOutputStream().write(data);
response.flushBuffer();
} else {
throw new NotFoundElement("No such thing. Sorry");
}
}
private boolean clientCacheValid(RepositoryFile repositoryFile, HttpServletRequest request, HttpServletResponse response) throws IOException {
if (repositoryFile.getSha1Sum().equals(request.getHeader(HttpHeaders.IF_NONE_MATCH))) {
LOG.debug("ETag matches");
response.setStatus(HttpStatus.NOT_MODIFIED.value());
response.flushBuffer();
return true;
}
long sinceDate = request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
if (sinceDate >= -1 && repositoryFile.getLastModifiedDate().getTime() < sinceDate) {
LOG.debug("Not modified since: {} < {}", repositoryFile.getLastModifiedBy(), new Date(sinceDate));
response.setStatus(HttpStatus.NOT_MODIFIED.value());
response.flushBuffer();
return true;
}
response.flushBuffer();
return false;
}
private void sanityCheck(final Path path, final String ext, final RepositoryFile repositoryFile) {
......@@ -141,14 +175,19 @@ public class RepositoryDownloadController extends BaseController {
}
final String ext = fullpath.substring(fullpath.lastIndexOf("."));
final String uuid = fullpath.substring(fullpath.lastIndexOf("/") + 1, fullpath.lastIndexOf("."));
final String name = fullpath.substring(fullpath.lastIndexOf("/") + 1, fullpath.lastIndexOf("."));
final String path = fullpath.substring(0, fullpath.lastIndexOf('/'));
if (LOG.isDebugEnabled()) {
LOG.debug("{} {}", path, uuid + ext);
LOG.debug("{} {}", path, name + ext);
// Enumeration<String> headerNames = request.getHeaderNames();
// while (headerNames.hasMoreElements()) {
// String headerName = headerNames.nextElement();
// LOG.debug(">> {}: {}", headerName, request.getHeader(headerName));
// }
}
downloadFile(path, uuid, ext, response);
downloadFile(Paths.get(path), name, ext, response, request);
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment