Skip to content

Commit 76da9fa

Browse files
authored
Use decoded file path as cache key in StaticHandlerImpl (#2902) (#2906)
Follows-up on #2900 After moving URI decoding into getFile(), sendStatic() was using context.normalizedPath() (which may still contain percent-encoded characters) as the cache key. Requests for the same file with different encodings (e.g. /foo/%62ar.txt vs /foo/bar.txt) created separate cache entries, wasting slots in the bounded LRU cache. Use the decoded file path from getFile() as the cache key so that encoding-equivalent paths share a single entry. As a side effect, getFile() is now called unconditionally at the top of sendStatic(), which simplifies the code. Previously, it was deferred when includeHidden was true (skipping the dot-segment check), requiring a null guard and a second getFile() call for the localFile computation. Some portions of this content were created with the assistance of Claude Code. Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
1 parent 846da52 commit 76da9fa

1 file changed

Lines changed: 8 additions & 24 deletions

File tree

vertx-web/src/main/java/io/vertx/ext/web/handler/impl/StaticHandlerImpl.java

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,9 @@ public void handle(RoutingContext context) {
180180
*/
181181
private void sendStatic(RoutingContext context, FileSystem fileSystem, String path, boolean index) {
182182

183-
String file = null;
183+
final String file = getFile(context);
184184

185185
if (!includeHidden) {
186-
file = getFile(context);
187186
for (int idx = file.indexOf('/'); idx >= 0; idx = file.indexOf('/', idx + 1)) {
188187
String name = file.substring(idx + 1);
189188
if (name.length() > 0 && name.charAt(0) == '.') {
@@ -198,7 +197,7 @@ private void sendStatic(RoutingContext context, FileSystem fileSystem, String pa
198197
}
199198

200199
// Look in cache
201-
final CacheEntry entry = cache.get(path);
200+
final CacheEntry entry = cache.get(file);
202201

203202
if (entry != null) {
204203
if ((filesReadOnly || !entry.isOutOfDate())) {
@@ -228,22 +227,7 @@ private void sendStatic(RoutingContext context, FileSystem fileSystem, String pa
228227
}
229228

230229
final boolean dirty = cache.enabled() && entry != null;
231-
final String localFile;
232-
233-
if (file == null) {
234-
String ctxFile = getFile(context);
235-
if (index) {
236-
localFile = ctxFile + indexPage;
237-
} else {
238-
localFile = ctxFile;
239-
}
240-
} else {
241-
if (index) {
242-
localFile = file + indexPage;
243-
} else {
244-
localFile = file;
245-
}
246-
}
230+
final String localFile = index ? file + indexPage : file;
247231

248232
// verify if the file exists
249233
fileSystem
@@ -259,7 +243,7 @@ private void sendStatic(RoutingContext context, FileSystem fileSystem, String pa
259243
// file does not exist, continue...
260244
if (!exists.result()) {
261245
if (cache.enabled()) {
262-
cache.put(path, null);
246+
cache.put(file, null);
263247
}
264248
if (!context.request().isEnded()) {
265249
context.request().resume();
@@ -275,7 +259,7 @@ private void sendStatic(RoutingContext context, FileSystem fileSystem, String pa
275259
if (fprops == null) {
276260
// File does not exist
277261
if (dirty) {
278-
cache.remove(path);
262+
cache.remove(file);
279263
}
280264
if (!context.request().isEnded()) {
281265
context.request().resume();
@@ -285,21 +269,21 @@ private void sendStatic(RoutingContext context, FileSystem fileSystem, String pa
285269
if (index) {
286270
// file does not exist (well it exists but it's a directory), continue...
287271
if (cache.enabled()) {
288-
cache.put(path, null);
272+
cache.put(file, null);
289273
}
290274
if (!context.request().isEnded()) {
291275
context.request().resume();
292276
}
293277
context.next();
294278
} else {
295279
if (dirty) {
296-
cache.remove(path);
280+
cache.remove(file);
297281
}
298282
sendDirectory(context, fileSystem, path, localFile);
299283
}
300284
} else {
301285
if (cache.enabled()) {
302-
cache.put(path, fprops);
286+
cache.put(file, fprops);
303287

304288
if (Utils.fresh(context, Utils.secondsFactor(fprops.lastModifiedTime()))) {
305289
context.response().setStatusCode(NOT_MODIFIED.code()).end();

0 commit comments

Comments
 (0)