Static Files
Static file serving configuration with authorization and content parsing support.
Overview
json
{
"StaticFiles": {
"Enabled": false,
"RootPath": "wwwroot",
"AuthorizePaths": [],
"UnauthorizedRedirectPath": "/",
"UnauthorizedReturnToQueryParameter": "return_to",
"ParseContentOptions": {
"Enabled": false,
"AvailableClaims": [],
"AvailableEnvVars": [],
"CacheParsedFile": true,
"Headers": [
"Cache-Control: no-store, no-cache, must-revalidate",
"Pragma: no-cache",
"Expires: 0"
],
"FilePaths": ["*.html"],
"AntiforgeryFieldName": "antiForgeryFieldName",
"AntiforgeryToken": "antiForgeryToken"
}
}
}Settings Reference
| Setting | Type | Default | Description |
|---|---|---|---|
Enabled | bool | false | Enable static file serving. |
RootPath | string | "wwwroot" | Root directory for static files. |
AuthorizePaths | array | [] | File patterns requiring authorization. |
UnauthorizedRedirectPath | string | "/" | Redirect path for unauthorized requests. |
UnauthorizedReturnToQueryParameter | string | "return_to" | Query parameter name for return URL after authentication. |
ParseContentOptions | object | (see below) | Content parsing configuration. |
Authorization
Protect specific static files by requiring authentication:
json
{
"StaticFiles": {
"Enabled": true,
"AuthorizePaths": [
"/admin/*",
"/dashboard/*.html",
"/reports/*"
],
"UnauthorizedRedirectPath": "/login",
"UnauthorizedReturnToQueryParameter": "return_to"
}
}Path Patterns
File paths are relative to RootPath and pattern matching is case-insensitive:
| Pattern | Description |
|---|---|
*.html | All HTML files in any directory |
/admin/* | All files in the admin directory |
/user/profile.html | Specific file |
*.js | All JavaScript files |
Content Parsing
Parse static files and replace tags with claim values from authenticated users.
json
{
"StaticFiles": {
"ParseContentOptions": {
"Enabled": false,
"AvailableClaims": [],
"AvailableEnvVars": [],
"CacheParsedFile": true,
"Headers": [
"Cache-Control: no-store, no-cache, must-revalidate",
"Pragma: no-cache",
"Expires: 0"
],
"FilePaths": ["*.html"],
"AntiforgeryFieldName": "antiForgeryFieldName",
"AntiforgeryToken": "antiForgeryToken"
}
}
}Parse Content Settings Reference
| Setting | Type | Default | Description |
|---|---|---|---|
Enabled | bool | false | Enable content parsing for static files. |
AvailableClaims | array | object | [] | Claim types to parse. Array form (["name"]) replaces missing claims with NULL; object form ({"name":"guest"}) uses the given default when the claim is absent. |
AvailableEnvVars | array | object | [] | Environment variable names templated into static content (same {NAME} tags as claims). Array form (["BUILD_LABEL"]) yields the empty string when unset; object form ({"DEMO_FLAG":"false"}) uses the given default. Resolved once at startup. Public — never list a secret. |
CacheParsedFile | bool | true | Cache parsed file templates in memory. Caching applies to templates before parsing, not final content. |
Headers | array | (see below) | Response headers for parsed static files. Set to null or empty array to ignore. |
FilePaths | array | ["*.html"] | File patterns to parse. |
AntiforgeryFieldName | string | "antiForgeryFieldName" | Variable name for the antiforgery form field name in templates. |
AntiforgeryToken | string | "antiForgeryToken" | Variable name for the antiforgery token value in templates. |
Tag Replacement
When Enabled is true, tags in the format {claimType} are replaced with values from the user's claims:
html
<p>Welcome, {name}!</p>
<p>Your email: {email}</p>
<input type="hidden" name="{antiForgeryFieldName}" value="{antiForgeryToken}" />For unauthenticated users or missing claims, values are replaced with NULL.
You can also give a claim an explicit default with the object form:
json
"AvailableClaims": { "name": "guest", "email": "" }Environment Variable Injection
AvailableEnvVars templates app-wide, request-independent environment variable values into static content using the same {NAME} tag syntax. This is useful for Single-Page Apps deployed to Kubernetes: build the bundle once, and inject per-environment values (build label, feature flags, analytics IDs) from pod env vars at boot — no per-environment rebuild.
json
{
"StaticFiles": {
"ParseContentOptions": {
"Enabled": true,
"FilePaths": ["/index.html"],
"AvailableClaims": ["user_id", "user_name"],
"AvailableEnvVars": {
"BUILD_LABEL": "local",
"DEMO_FLAG": "false",
"TRACKING_ID": ""
}
}
}
}Values are substituted as complete, JSON-escaped literals, so the template uses the bare {NAME} token with no surrounding quotes:
html
<script>
window.__appConfig = {
userId: {user_id}, // claim → 123 or null
userName: {user_name}, // claim → "alice" or null
buildLabel: {BUILD_LABEL}, // env → "demo" (or "local" default)
demoMode: {DEMO_FLAG} === "true",
trackingId: {TRACKING_ID}
};
</script>Guarantees:
- Two forms. An array of names (
["BUILD_LABEL"]) — a missing variable becomes the empty string"". Or an object of name→default pairs ({"DEMO_FLAG":"false"}) — the default is used when the variable is absent. - Resolved once at startup. A value change requires a restart (a Kubernetes pod restart re-reads the values).
- JSON-escaped. An accidental quote or backslash in a value cannot break the JS string. (The relaxed encoder does not escape
</>, the same as the claim path — env values are operator-controlled, not untrusted input.) - Claims win on collision. If a name is both a user claim and an env var, the per-request claim value takes precedence.
Public allowlist
Anything you list in AvailableEnvVars is templated into static content served to any client. Templating a secret (database password, API key, signing token) into index.html leaks it to every user via browser DevTools. Treat the list as a public allowlist, never as a "make this reachable to the app" shortcut. Secrets stay in server-side code paths that read env directly. This is distinct from the server-side Config:ParseEnvironmentVariables mechanism, which substitutes {ENV} tokens into appsettings.json values that never leave the server.
Default Headers
The default headers disable caching for parsed content:
code
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Expires: 0Example Configuration
Serve static files with protected admin area and content parsing:
json
{
"StaticFiles": {
"Enabled": true,
"RootPath": "wwwroot",
"AuthorizePaths": [
"/admin/*",
"/dashboard/*"
],
"UnauthorizedRedirectPath": "/login.html",
"UnauthorizedReturnToQueryParameter": "return_to",
"ParseContentOptions": {
"Enabled": true,
"AvailableClaims": ["name", "email", "role"],
"CacheParsedFile": true,
"FilePaths": ["*.html", "*.htm"],
"AntiforgeryFieldName": "antiForgeryFieldName",
"AntiforgeryToken": "antiForgeryToken"
}
}
}Related
- Comment Annotations Guide - How annotations work
- Configuration Guide - How configuration works
Next Steps
- Authentication - Configure authentication methods
- Antiforgery - Configure CSRF protection