Skip to content

Commit 3c55076

Browse files
authored
Use decoded file path as cache key in StaticHandlerImpl (#2902) (#2905)
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 14ce53f commit 3c55076

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
@@ -166,10 +166,9 @@ public void handle(RoutingContext context) {
166166
*/
167167
private void sendStatic(RoutingContext context, FileSystem fileSystem, String path, boolean index) {
168168

169-
String file = null;
169+
final String file = getFile(context);
170170

171171
if (!includeHidden) {
172-
file = getFile(context);
173172
for (int idx = file.indexOf('/'); idx >= 0; idx = file.indexOf('/', idx + 1)) {
174173
String name = file.substring(idx + 1);
175174
if (name.length() > 0 && name.charAt(0) == '.') {
@@ -184,7 +183,7 @@ private void sendStatic(RoutingContext context, FileSystem fileSystem, String pa
184183
}
185184

186185
// Look in cache
187-
final CacheEntry entry = cache.get(path);
186+
final CacheEntry entry = cache.get(file);
188187

189188
if (entry != null) {
190189
if ((filesReadOnly || !entry.isOutOfDate())) {
@@ -214,22 +213,7 @@ private void sendStatic(RoutingContext context, FileSystem fileSystem, String pa
214213
}
215214

216215
final boolean dirty = cache.enabled() && entry != null;
217-
final String localFile;
218-
219-
if (file == null) {
220-
String ctxFile = getFile(context);
221-
if (index) {
222-
localFile = ctxFile + indexPage;
223-
} else {
224-
localFile = ctxFile;
225-
}
226-
} else {
227-
if (index) {
228-
localFile = file + indexPage;
229-
} else {
230-
localFile = file;
231-
}
232-
}
216+
final String localFile = index ? file + indexPage : file;
233217

234218
// verify if the file exists
235219
fileSystem
@@ -244,7 +228,7 @@ private void sendStatic(RoutingContext context, FileSystem fileSystem, String pa
244228
// file does not exist, continue...
245229
if (!exists) {
246230
if (cache.enabled()) {
247-
cache.put(path, null);
231+
cache.put(file, null);
248232
}
249233
if (!context.request().isEnded()) {
250234
context.request().resume();
@@ -259,7 +243,7 @@ private void sendStatic(RoutingContext context, FileSystem fileSystem, String pa
259243
if (fprops == null) {
260244
// File does not exist
261245
if (dirty) {
262-
cache.remove(path);
246+
cache.remove(file);
263247
}
264248
if (!context.request().isEnded()) {
265249
context.request().resume();
@@ -269,21 +253,21 @@ private void sendStatic(RoutingContext context, FileSystem fileSystem, String pa
269253
if (index) {
270254
// file does not exist (well it exists but it's a directory), continue...
271255
if (cache.enabled()) {
272-
cache.put(path, null);
256+
cache.put(file, null);
273257
}
274258
if (!context.request().isEnded()) {
275259
context.request().resume();
276260
}
277261
context.next();
278262
} else {
279263
if (dirty) {
280-
cache.remove(path);
264+
cache.remove(file);
281265
}
282266
sendDirectory(context, fileSystem, path, localFile);
283267
}
284268
} else {
285269
if (cache.enabled()) {
286-
cache.put(path, fprops);
270+
cache.put(file, fprops);
287271

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

0 commit comments

Comments
 (0)