Class StaticAssetDetector
java.lang.Object
com.kingsrook.qqq.middleware.javalin.routeproviders.StaticAssetDetector
Utility class for detecting whether a request path represents a static asset
versus a client-side SPA route.
PROBLEM:
When serving SPAs with deep linking support, we need to distinguish between:
- 404s for missing static assets (should stay 404)
- 404s for SPA client-side routes (should serve index.html)
SOLUTION:
Use heuristics based on file extensions and common path patterns to make
an educated guess about whether a path is likely a static asset.
LIMITATIONS invalid input: '&' CAVEATS:
This class uses heuristics and cannot be 100% accurate because:
1. False Positives: SPA routes that look like assets (e.g., /learn/javascript.js)
will be incorrectly identified as assets and return 404 instead of serving
the SPA's index.html
2. False Negatives: Assets without standard extensions (e.g., /assets/logo)
may be incorrectly identified as routes and serve index.html instead of 404
3. Framework-Specific: Some frameworks use non-standard asset paths that may
not be recognized (e.g., Vite's /@vite/client)
4. Maintenance: New file formats and web standards require periodic updates
CUSTOMIZATION:
For cases where the default heuristics don't work, you can:
- Add custom extensions: detector.withCustomExtensions(".myext")
- Add custom path patterns: detector.withCustomPathPatterns("/my-assets/")
- Provide custom logic: detector.withCustomDetector(path -> ...)
METRICS:
Tracks detection statistics via incrementCounter() for monitoring and debugging.
Override incrementCounter() to integrate with your metrics system.
THREAD SAFETY:
This class is thread-safe for read operations after configuration.
Configuration methods should only be called during initialization.
- Since:
- 0.31.0
-
Constructor Summary
ConstructorsConstructorDescriptionConstructor - creates detector with default configuration -
Method Summary
Modifier and TypeMethodDescriptionGet the set of file extensions this detector recognizesGet the list of path patterns this detector recognizesprotected voidincrementCounter(String counterName) Increment a counter for metrics tracking.booleanisStaticAsset(String path) Detect if a request path represents a static asset.withCustomDetector(Predicate<String> detector) Fluent setter: Add custom detection logic Custom detectors are evaluated FIRST, before extension and path matching.withCustomExtensions(String... customExtensions) Fluent setter: Add custom file extensions to detect as static assetswithCustomPathPatterns(String... patterns) Fluent setter: Add custom path patterns to detect as static assetsFluent setter: Set a name for this detector (used in logging)
-
Constructor Details
-
StaticAssetDetector
public StaticAssetDetector()Constructor - creates detector with default configuration
-
-
Method Details
-
isStaticAsset
Detect if a request path represents a static asset. Uses the following logic in order: 1. Custom detectors (if any configured) 2. File extension matching (e.g., .js, .css, .png) 3. Path pattern matching (e.g., /assets/, /static/)- Parameters:
path- The request path to check (e.g., "/admin/assets/main.js")- Returns:
- true if the path appears to be a static asset, false otherwise
-
incrementCounter
Increment a counter for metrics tracking. Override this method to integrate with your metrics system (e.g., Prometheus, Micrometer, custom metrics). Default implementation does nothing.- Parameters:
counterName- Name of the counter to increment Values: "custom_detector", "extension_match", "path_pattern_match", "not_asset"
-
withCustomExtensions
Fluent setter: Add custom file extensions to detect as static assets- Parameters:
customExtensions- Extensions to add (e.g., ".myext", ".custom")- Returns:
- this for method chaining
-
withCustomPathPatterns
Fluent setter: Add custom path patterns to detect as static assets- Parameters:
patterns- Path patterns to add (e.g., "/my-assets/", "/resources/")- Returns:
- this for method chaining
-
withCustomDetector
Fluent setter: Add custom detection logic Custom detectors are evaluated FIRST, before extension and path matching. If any custom detector returns true, the path is considered a static asset.- Parameters:
detector- Predicate that returns true if path is a static asset- Returns:
- this for method chaining
-
withName
Fluent setter: Set a name for this detector (used in logging)- Parameters:
name- Name for this detector instance- Returns:
- this for method chaining
-
getExtensions
-
getPathPatterns
-