Closes #172: smart images caching

This commit is contained in:
bgamard 2017-11-23 15:32:20 +01:00
parent b8176a9fe9
commit ecfa747a2c
3 changed files with 29 additions and 88 deletions

View File

@ -1,14 +1,8 @@
package com.sismics.util; package com.sismics.util;
import org.slf4j.Logger; import java.text.SimpleDateFormat;
import org.slf4j.LoggerFactory; import java.util.Date;
import java.util.Locale;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
/** /**
* HTTP request utilities. * HTTP request utilities.
@ -17,77 +11,17 @@ import java.net.URLConnection;
*/ */
public class HttpUtil { public class HttpUtil {
/** /**
* Logger. * Format of the expires header.
*/ */
private static final Logger log = LoggerFactory.getLogger(HttpUtil.class); private static final SimpleDateFormat EXPIRES_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
/** /**
* Loads the content of an URL into a string. * Build an Expires HTTP header.
* *
* @param url URL to load * @param futureTime Expire interval
* @return Contents of the resource * @return Formatted header value
*/ */
public static String readUrlIntoString(URL url) { public static String buildExpiresHeader(long futureTime) {
URLConnection connection; return EXPIRES_FORMAT.format(new Date().getTime() + futureTime);
BufferedReader in = null;
try {
connection = url.openConnection();
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder sb = new StringBuilder();
String inputLine;
while ((inputLine = in.readLine()) != null) {
sb.append(inputLine);
}
return sb.toString();
} catch (IOException e) {
if (log.isErrorEnabled()) {
log.error("Error reading URL", e);
}
return null;
} finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
// NOP
}
}
}
}
public static String postUrl(URL url, String data) throws IOException {
OutputStreamWriter wr = null;
BufferedReader rd = null;
try {
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
// Get the response
rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = rd.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
} finally {
if (wr != null) {
try {
wr.close();
} catch (IOException e) {
// NOP
}
}
if (rd != null) {
try {
rd.close();
} catch (IOException e) {
// NOP
}
}
}
} }
} }

View File

@ -14,12 +14,16 @@ import com.sismics.docs.core.event.FileCreatedAsyncEvent;
import com.sismics.docs.core.event.FileDeletedAsyncEvent; import com.sismics.docs.core.event.FileDeletedAsyncEvent;
import com.sismics.docs.core.model.jpa.File; import com.sismics.docs.core.model.jpa.File;
import com.sismics.docs.core.model.jpa.User; import com.sismics.docs.core.model.jpa.User;
import com.sismics.docs.core.util.*; import com.sismics.docs.core.util.DirectoryUtil;
import com.sismics.docs.core.util.EncryptionUtil;
import com.sismics.docs.core.util.FileUtil;
import com.sismics.docs.core.util.PdfUtil;
import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ClientException;
import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ForbiddenClientException;
import com.sismics.rest.exception.ServerException; import com.sismics.rest.exception.ServerException;
import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.JsonUtil;
import com.sismics.rest.util.ValidationUtil; import com.sismics.rest.util.ValidationUtil;
import com.sismics.util.HttpUtil;
import com.sismics.util.context.ThreadLocalContext; import com.sismics.util.context.ThreadLocalContext;
import com.sismics.util.mime.MimeType; import com.sismics.util.mime.MimeType;
import com.sismics.util.mime.MimeTypeUtil; import com.sismics.util.mime.MimeTypeUtil;
@ -30,18 +34,19 @@ import javax.json.Json;
import javax.json.JsonArrayBuilder; import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder; import javax.json.JsonObjectBuilder;
import javax.ws.rs.*; import javax.ws.rs.*;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.StreamingOutput;
import java.io.*; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
@ -581,9 +586,10 @@ public class FileResource extends BaseResource {
} }
return Response.ok(stream) return Response.ok(stream)
.header("Content-Disposition", "inline; filename=" + file.getFullName("data")) .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=" + file.getFullName("data"))
.header("Content-Type", mimeType) .header(HttpHeaders.CONTENT_TYPE, mimeType)
.header("Expires", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z").format(new Date().getTime() + 3600000 * 24)) .header(HttpHeaders.CACHE_CONTROL, "private")
.header(HttpHeaders.EXPIRES, HttpUtil.buildExpiresHeader(3_600_000L * 24L * 365L))
.build(); .build();
} }

View File

@ -12,12 +12,14 @@ import com.sismics.rest.exception.ForbiddenClientException;
import com.sismics.rest.exception.ServerException; import com.sismics.rest.exception.ServerException;
import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.JsonUtil;
import com.sismics.rest.util.ValidationUtil; import com.sismics.rest.util.ValidationUtil;
import com.sismics.util.HttpUtil;
import com.sismics.util.css.Selector; import com.sismics.util.css.Selector;
import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataParam; import org.glassfish.jersey.media.multipart.FormDataParam;
import javax.json.*; import javax.json.*;
import javax.ws.rs.*; import javax.ws.rs.*;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.StreamingOutput;
import java.io.IOException; import java.io.IOException;
@ -26,8 +28,6 @@ import java.io.OutputStream;
import java.io.StringReader; import java.io.StringReader;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map; import java.util.Map;
/** /**
@ -235,8 +235,9 @@ public class ThemeResource extends BaseResource {
} }
} }
}) })
.header("Content-Type", "image/*") .header(HttpHeaders.CONTENT_TYPE, "image/*")
.header("Expires", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z").format(new Date().getTime() + 3600000 * 24 * 15)) .header(HttpHeaders.CACHE_CONTROL, "public")
.header(HttpHeaders.EXPIRES, HttpUtil.buildExpiresHeader(3_600_000L * 24L * 15L))
.build(); .build();
} }