2121 */
2222
2323import act .Act ;
24+ import act .ActResponse ;
2425import act .app .ActionContext ;
2526import act .controller .ParamNames ;
2627import act .handler .builtin .controller .FastRequestHandler ;
3839import java .util .*;
3940
4041import static org .osgl .http .H .Format .*;
42+ import static org .osgl .http .H .Header .Names .CACHE_CONTROL ;
4143
4244/**
4345 * Unlike a {@link FileGetter}, the
@@ -54,15 +56,15 @@ public class ResourceGetter extends FastRequestHandler {
5456 private int preloadSizeLimit ;
5557 private boolean isFolder ;
5658 private ByteBuffer buffer ;
57- private H .Format contentType ;
59+ private H .Format preloadedContentType ;
5860 private boolean preloadFailure ;
5961 private boolean preloaded ;
6062 private String etag ;
6163
6264 private Set <URL > folders = new HashSet <>();
6365 private Map <String , String > etags = new HashMap <>();
6466 private Map <String , ByteBuffer > cachedBuffers = new HashMap <>();
65- private Map <String , String > cachedContentType = new HashMap <>();
67+ private Map <String , H . Format > cachedContentType = new HashMap <>();
6668 private Map <String , Boolean > cachedFailures = new HashMap <>();
6769
6870 public ResourceGetter (String base ) {
@@ -114,43 +116,58 @@ public void handle(ActionContext context) {
114116 protected void handle (String path , ActionContext context ) {
115117 H .Request req = context .req ();
116118 if (Act .isProd ()) {
119+ ActResponse resp = context .prepareRespForWrite ();
117120 if (preloaded ) {
118121 // this is a reloaded file resource
119122 if (preloadFailure ) {
120123 AlwaysNotFound .INSTANCE .handle (context );
121124 } else {
125+ resp .contentType (preloadedContentType );
122126 if (req .etagMatches (etag )) {
123127 AlwaysNotModified .INSTANCE .handle (context );
124128 } else {
125- H .Response resp = context .prepareRespForWrite ();
126- resp .contentType (contentType .contentType ())
129+ H .Format contentType = cachedContentType .get (path );
130+ if (null == contentType ) {
131+ contentType = req .contentType ();
132+ }
133+ resp
134+ .contentType (contentType )
135+ .header (CACHE_CONTROL , "public, max-age=7200" )
127136 .etag (this .etag )
128137 .writeContent (buffer .duplicate ());
129138 }
130139 }
131140 return ;
132141 }
142+
133143 if (cachedFailures .containsKey (path )) {
134144 AlwaysNotFound .INSTANCE .handle (context );
135145 return ;
136146 }
137147
138148 if (null != req .etag () && req .etagMatches (etags .get (path ))) {
149+ H .Format contentType = cachedContentType .get (path );
150+ if (null == contentType ) {
151+ contentType = req .contentType ();
152+ }
153+ resp .contentType (contentType );
139154 AlwaysNotModified .INSTANCE .handle (context );
140155 return ;
141156 }
142157 }
143158 ByteBuffer buffer = cachedBuffers .get (path );
144159 if (null != buffer ) {
145- context .prepareRespForWrite ()
160+ context .resp ()
146161 .contentType (cachedContentType .get (path ))
162+ .header (CACHE_CONTROL , "public, max-age=7200" );
163+ context .applyContentType ();
164+ context .prepareRespForWrite ()
147165 .etag (etags .get (path ))
148166 .writeContent (buffer .duplicate ());
149167 return ;
150168 }
151169 try {
152170 URL target ;
153- H .Format fmt ;
154171 String loadPath ;
155172 if (S .blank (path )) {
156173 target = baseUrl ;
@@ -165,9 +182,12 @@ protected void handle(String path, ActionContext context) {
165182 if (preventFolderAccess (target , loadPath , context )) {
166183 return ;
167184 }
168- fmt = FileGetter .contentType (target .getPath ());
169- H .Response resp = context .prepareRespForWrite ();
170- resp .contentType (fmt .contentType ());
185+ H .Format contentType = FileGetter .contentType (target .getPath ());
186+ ActResponse resp = context .prepareRespForWrite ();
187+ resp .contentType (contentType );
188+ if (Act .isProd ()) {
189+ resp .header (CACHE_CONTROL , "public, max-age=7200" );
190+ }
171191 context .applyCorsSpec ().applyContentType ();
172192 try {
173193 int n = IO .copy (target .openStream (), resp .outputStream ());
@@ -180,7 +200,7 @@ protected void handle(String path, ActionContext context) {
180200 cachedFailures .put (path , true );
181201 } else {
182202 cachedBuffers .put (path , buffer );
183- cachedContentType .put (path , fmt . contentType () );
203+ cachedContentType .put (path , contentType );
184204 }
185205 }
186206 }
@@ -227,7 +247,7 @@ private void preloadCache() {
227247 if (Act .isDev ()) {
228248 return ;
229249 }
230- contentType = FileGetter .contentType (baseUrl .getPath ());
250+ H . Format contentType = FileGetter .contentType (baseUrl .getPath ());
231251 if (HTML == contentType || CSS == contentType || JAVASCRIPT == contentType
232252 || TXT == contentType || CSV == contentType
233253 || JSON == contentType || XML == contentType
@@ -239,6 +259,7 @@ private void preloadCache() {
239259 } else {
240260 this .etag = etagBag .get ();
241261 }
262+ preloadedContentType = contentType ;
242263 preloaded = true ;
243264 }
244265 }
0 commit comments