diff --git a/src/main/scala/gitbucket/core/controller/AccountController.scala b/src/main/scala/gitbucket/core/controller/AccountController.scala index 19c553a..86866e5 100644 --- a/src/main/scala/gitbucket/core/controller/AccountController.scala +++ b/src/main/scala/gitbucket/core/controller/AccountController.scala @@ -15,6 +15,7 @@ import org.apache.commons.io.FileUtils import org.scalatra.i18n.Messages import org.scalatra.BadRequest +import java.util.Date class AccountController extends AccountControllerBase @@ -149,11 +150,17 @@ get("/:userName/_avatar"){ val userName = params("userName") - getAccountByUserName(userName).flatMap(_.image).map { image => - RawData(FileUtil.getMimeType(image), new java.io.File(getUserUploadDir(userName), image)) - } getOrElse { - contentType = "image/png" - Thread.currentThread.getContextClassLoader.getResourceAsStream("noimage.png") + (for { + account <- getAccountByUserName(userName) + image <- account.image + } yield (account, image)) match{ + case Some((account, image)) => + response.setDateHeader("Last-Modified", account.updatedDate.getTime) + RawData(FileUtil.getMimeType(image), new java.io.File(getUserUploadDir(userName), image)) + case None => + contentType = "image/png" + response.setDateHeader("Last-Modified", (new Date(0)).getTime) + Thread.currentThread.getContextClassLoader.getResourceAsStream("noimage.png") } } diff --git a/src/main/scala/gitbucket/core/servlet/PluginAssetsServlet.scala b/src/main/scala/gitbucket/core/servlet/PluginAssetsServlet.scala index 0d43af3..6fe1ed3 100644 --- a/src/main/scala/gitbucket/core/servlet/PluginAssetsServlet.scala +++ b/src/main/scala/gitbucket/core/servlet/PluginAssetsServlet.scala @@ -26,6 +26,7 @@ val bytes = IOUtils.toByteArray(in) resp.setContentLength(bytes.length) resp.setContentType(FileUtil.getContentType(path, bytes)) + resp.setHeader("Cache-Control", "max-age=3600") resp.getOutputStream.write(bytes) } finally { in.close() diff --git a/src/main/scala/gitbucket/core/view/AvatarImageProvider.scala b/src/main/scala/gitbucket/core/view/AvatarImageProvider.scala index 8d316ab..8cd64d0 100644 --- a/src/main/scala/gitbucket/core/view/AvatarImageProvider.scala +++ b/src/main/scala/gitbucket/core/view/AvatarImageProvider.scala @@ -20,7 +20,7 @@ if(account.image.isEmpty && context.settings.gravatar){ s"""https://www.gravatar.com/avatar/${StringUtil.md5(account.mailAddress.toLowerCase)}?s=${size}&d=retro&r=g""" } else { - s"""${context.path}/${account.userName}/_avatar""" + s"""${context.path}/${account.userName}/_avatar?${helpers.hashDate(account.updatedDate)}""" } } getOrElse { s"""${context.path}/_unknown/_avatar""" @@ -31,7 +31,7 @@ if(account.image.isEmpty && context.settings.gravatar){ s"""https://www.gravatar.com/avatar/${StringUtil.md5(account.mailAddress.toLowerCase)}?s=${size}&d=retro&r=g""" } else { - s"""${context.path}/${account.userName}/_avatar""" + s"""${context.path}/${account.userName}/_avatar?${helpers.hashDate(account.updatedDate)}""" } } getOrElse { if(context.settings.gravatar){ @@ -49,4 +49,4 @@ } } -} \ No newline at end of file +} diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala index dc4e1c1..f16e81c 100644 --- a/src/main/scala/gitbucket/core/view/helpers.scala +++ b/src/main/scala/gitbucket/core/view/helpers.scala @@ -75,6 +75,21 @@ def date(date: Date): String = new SimpleDateFormat("yyyy-MM-dd").format(date) /** + * Format java.util.Date to "yyyyMMDDHHmmss" (for url hash ex. /some/path.css?19800101010203 + */ + def hashDate(date: Date): String = new SimpleDateFormat("yyyyMMddHHmmss").format(date) + + /** + * java.util.Date of boot timestamp. + */ + val bootDate: Date = new Date() + + /** + * hashDate of bootDate for /assets, /plugin-assets + */ + def hashQuery: String = hashDate(bootDate) + + /** * Returns singular if count is 1, otherwise plural. * If plural is not specified, returns singular + "s" as plural. */ @@ -212,6 +227,11 @@ def assets(implicit context: Context): String = s"${context.path}/assets" /** + * Returns the url to the path of assets. + */ + def assets(path: String)(implicit context: Context): String = s"${context.path}/assets${path}?${hashQuery}" + + /** * Generates the text link to the account page. * If user does not exist or disabled, this method returns user name as text without link. */ diff --git a/src/main/twirl/gitbucket/core/helper/diff.scala.html b/src/main/twirl/gitbucket/core/helper/diff.scala.html index 17fdea2..8217c37 100644 --- a/src/main/twirl/gitbucket/core/helper/diff.scala.html +++ b/src/main/twirl/gitbucket/core/helper/diff.scala.html @@ -130,8 +130,8 @@ } - - + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + @repository.map { repository => } - +
diff --git a/src/main/twirl/gitbucket/core/pulls/compare.scala.html b/src/main/twirl/gitbucket/core/pulls/compare.scala.html index d97b36f..d390c17 100644 --- a/src/main/twirl/gitbucket/core/pulls/compare.scala.html +++ b/src/main/twirl/gitbucket/core/pulls/compare.scala.html @@ -43,7 +43,7 @@ }
@if(commits.nonEmpty && context.loginAccount.isDefined){ diff --git a/src/main/twirl/gitbucket/core/pulls/conversation.scala.html b/src/main/twirl/gitbucket/core/pulls/conversation.scala.html index 85e862c..1785c89 100644 --- a/src/main/twirl/gitbucket/core/pulls/conversation.scala.html +++ b/src/main/twirl/gitbucket/core/pulls/conversation.scala.html @@ -21,7 +21,7 @@ @@ -63,4 +63,4 @@ }); } }); - \ No newline at end of file + diff --git a/src/main/twirl/gitbucket/core/repo/delete.scala.html b/src/main/twirl/gitbucket/core/repo/delete.scala.html index 57190ab..fc7e771 100644 --- a/src/main/twirl/gitbucket/core/repo/delete.scala.html +++ b/src/main/twirl/gitbucket/core/repo/delete.scala.html @@ -50,10 +50,10 @@ } } - - + + \ No newline at end of file + diff --git a/src/main/twirl/gitbucket/core/repo/editor.scala.html b/src/main/twirl/gitbucket/core/repo/editor.scala.html index cafbd29..282d060 100644 --- a/src/main/twirl/gitbucket/core/repo/editor.scala.html +++ b/src/main/twirl/gitbucket/core/repo/editor.scala.html @@ -72,9 +72,9 @@ } } - - - + + +