Si tu SPA (Blazor WebAssembly, Angular, React, Vue…) la sirve una aplicación ASP.NET Core, Jazui.AspNetCore añade un middleware que atiende a los bots antes de los archivos estáticos y del fallback a index.html. Es la opción recomendada también en IIS cuando la aplicación es de .NET.
Antes de empezar
- .NET 8 o superior.
- Tu sitio verificado en Jazui y tu token.
- El origen de paquetes de AstrolUI (
https://nuget.astrolui.com/v3/index.json) añadido a NuGet.
Instalación
Jazui.AspNetCore no está en nuget.org: se publica en el repositorio de paquetes NuGet de AstrolUI, https://nuget.astrolui.com/v3/index.json. Añade ese origen una vez (en Visual Studio, con la línea de comandos o en un nuget.config) y después instala el paquete como cualquier otro. El paquete lleva el logo de Jazui y su versión sigue la de .NET con la que se publica (por ejemplo 10.0.13.1); funciona en aplicaciones de .NET 8 o superior.
En Visual Studio
- Abre Herramientas › Opciones › Administrador de paquetes NuGet › Orígenes de paquetes.
- Pulsa +, escribe Nombre:
AstrolUIy Origen:https://nuget.astrolui.com/v3/index.json, pulsa Actualizar y después Aceptar. - Con el botón derecho sobre tu proyecto, elige Administrar paquetes NuGet….
- Arriba a la derecha, en Origen del paquete, elige
AstrolUI(o Todo). - En Examinar, busca
Jazui.AspNetCore, elige la última versión y pulsa Instalar.
Si tu solución tiene un nuget.config con <clear />, Visual Studio solo usa los orígenes de ese archivo: añade AstrolUI ahí (abajo tienes el ejemplo).
Con la línea de comandos
dotnet nuget add source https://nuget.astrolui.com/v3/index.json --name AstrolUI
dotnet add package Jazui.AspNetCoreCon nuget.config
Para que todo el equipo y tu integración continua lo tengan sin configurar nada, pon un nuget.config junto a tu solución. Si ya usas la asignación de orígenes (packageSourceMapping), añade el patrón Jazui.* al origen AstrolUI; si no, basta con packageSources.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="AstrolUI" value="https://nuget.astrolui.com/v3/index.json" protocolVersion="3" />
</packageSources>
<!-- Solo si usas la asignación de orígenes: los paquetes Jazui.* salen de AstrolUI -->
<packageSourceMapping>
<packageSource key="AstrolUI">
<package pattern="Jazui.*" />
</packageSource>
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
</packageSourceMapping>
</configuration>Configuración
Registra el servicio y añade el middleware antes de UseStaticFiles y del MapFallbackToFile:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddJazui(builder.Configuration);
var app = builder.Build();
app.UseForwardedHeaders(); // solo si hay un proxy o CDN delante: la IP y el esquema del bot
app.UseJazui(); // antes de los archivos estáticos y del fallback de la SPA
app.UseStaticFiles();
app.MapFallbackToFile("index.html");
app.Run();{
"Jazui": {
"Token": "",
"SiteUrl": ""
}
}No pongas el token en appsettings.json: en producción usa la variable de entorno Jazui__Token (o los secretos de usuario en desarrollo). UseForwardedHeaders solo hace falta si hay un proxy o CDN delante, para que Jazui reciba la IP real del bot y el esquema https.
Opciones
Todas se leen de la sección Jazui de la configuración y se pueden cambiar también en código:
| Opción | Por defecto | Para qué |
|---|---|---|
Token | — | Token de la cuenta o del sitio. Sin token, el middleware no hace nada. |
ApiUrl | https://api.jazui.com | Dirección de la API. |
SiteUrl | — | Dominio público cuando la aplicación ve otro (proxy, pruebas). |
Timeout | 20 s | Pasado este tiempo se sirve la página normal. |
ExcludedPaths | /api, /_framework, /_content, /_blazor | Rutas que nunca pasan por Jazui (por segmento: /api cubre /api/x pero no /apis). |
ExtraBots | — | Fragmentos de agente de usuario que se suman a la lista de bots. |
RemoteBots | true | Descarga la lista de bots de Jazui al arrancar y cada BotsRefreshInterval. |
BotsRefreshInterval | 24 h | Cada cuánto se vuelve a descargar la lista. |
ReportUnknownBots | true | Avisa a Jazui de los agentes con pinta de bot que no están en la lista (sin enviar la página). |
builder.Services.AddJazui(builder.Configuration, options =>
{
options.Timeout = TimeSpan.FromSeconds(10);
options.ExcludedPaths = ["/api", "/_framework", "/_content", "/_blazor", "/admin"];
options.ExtraBots = ["mibotinterno"];
options.BotsRefreshInterval = TimeSpan.FromHours(12);
});Qué hace
Para cada petición que es de un bot, llama a la API con la dirección (o SiteUrl más la ruta), el agente de usuario, la IP del bot (de Connection.RemoteIpAddress) y el If-None-Match. Si Jazui responde con X-Jazui o con un bloqueo, copia el código, las cabeceras y el cuerpo; si tarda o falla, lo apunta en el registro como aviso y sigue con el resto de la aplicación. La versión de la lista de bots en uso está en JazuiMiddleware.BotsVersion.
<p>Pide tu portada como si fueras un bot, con el agente de usuario de pruebas <code>integration-test</code>:</p><pre><code>curl -I -A "integration-test" https://misitio.com/</code></pre><p>La respuesta debe llevar <code>x-jazui: true</code> y <code>x-jazui-cache: MISS</code> la primera vez y <code>HIT</code> después. Sin agente de bot (<code>curl -I https://misitio.com/</code>) debe llegar tu web de siempre, sin <code>x-jazui</code>. En el panel, la petición aparece en <b>Tráfico de bots</b> y la página en <b>Páginas en caché</b>.</p>
Pide tu portada como si fueras un bot, con el agente de usuario de pruebas integration-test:
curl -I -A "integration-test" https://misitio.com/La respuesta debe llevar x-jazui: true y x-jazui-cache: MISS la primera vez y HIT después. Sin agente de bot (curl -I https://misitio.com/) debe llegar tu web de siempre, sin x-jazui. En el panel, la petición aparece en Tráfico de bots y la página en Páginas en caché.
Si algo no funciona
- No se encuentra
Jazui.AspNetCore: falta el origen AstrolUI, o tunuget.configtiene<clear />o una asignación de orígenes sin el patrónJazui.*. - No aparece
x-jazui:UseJazui()tiene que ir antes deUseStaticFiles()y deMapFallbackToFile; revisa también que el token llega (variableJazui__Token). - Detrás de IIS o de un proxy, la URL sale con
http: configuraUseForwardedHeaderso defineSiteUrl. - Los avisos del registro («Jazui no respondió…») te dicen por qué se sirvió la página normal.