Skip to content

Support per-request ResourceTransformer execution for index.html to enable CSP nonce injection #3264

@kimtaa

Description

@kimtaa

Use case

We enforce a Content Security Policy with a per-request nonce (script-src 'nonce-{value}').
The nonce is generated fresh on every request and must be injected into the nonce attribute of
all <script> and <style> tags in index.html. We do this via a custom SwaggerIndexTransformer:

public class SwaggerNonceTransformer extends SwaggerIndexPageTransformer {                                                                  
    @Override   
    public Resource transform(HttpServletRequest request, Resource resource,
            ResourceTransformerChain chain) throws IOException {                                                                            
        Resource transformed = super.transform(request, resource, chain);
        if (resource.toString().contains("index.html")) {                                                                                   
            String html = new String(transformed.getInputStream().readAllBytes(), UTF_8);
            String nonce = request.getAttribute("cspNonce").toString();                                                                     
            html = html.replace("<script", "<script nonce='" + nonce + "'")
                       .replace("<style",  "<style nonce='" + nonce + "'");                                                                 
            return new TransformedResource(resource, html.getBytes());                                                                      
        }
        return transformed;                                                                                                                 
    }           
}

This worked correctly in springdoc 2.x, where all swagger-ui handlers used resourceChain(false)
and transformers ran on every request.

Problem

AbstractSwaggerConfigurer.getSwaggerHandlerConfigs() registers index.html with createCached(),
which causes SwaggerWebMvcConfigurer to use resourceChain(true, cache) for that handler.
This adds CachingResourceTransformer to the chain, which caches the transformer output after
the first request and never calls transform() again — making per-request transformation of
index.html impossible.

Interestingly, swagger-initializer.js is already served via createUncached() precisely
because it needs per-request transformer execution (for config injection). We need the same
capability for index.html.

Requested feature

Expose a way to opt out of CachingResourceTransformer for the index.html handler, for example:

  • A configuration property such as springdoc.swagger-ui.cache.transformer.disabled=true
  • Or making addSwaggerResourceHandler() check springdoc.swagger-ui.cache.disabled in addition to the existing springdoc.cache.disabled
    property

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions