# Proveedores de Servicios

Source: https://docs.sisk-framework.org/es/docs/extensions/service-providers.html

Los Proveedores de Servicios son una forma de portar tu aplicación Sisk a diferentes entornos con un archivo de configuración portable. Esta característica permite cambiar el puerto del servidor, parámetros y otras opciones sin tener que modificar el código de la aplicación para cada entorno. Este módulo depende de la sintaxis de construcción de Sisk y puede configurarse mediante el método **UsePortableConfiguration**.

Un proveedor de configuración se implementa con **IConfigurationProvider**, que proporciona un lector de configuración y puede recibir cualquier implementación. Por defecto, Sisk ofrece un lector de configuración JSON, pero también existe un paquete para archivos INI. Puedes crear tu propio proveedor de configuración y registrarlo con:

```csharp
using var app = HttpServer.CreateBuilder()
    .UsePortableConfiguration(config =>
    {
        config.WithConfigReader<MyConfigurationReader>();
    })
    .Build();
```

Como se mencionó antes, el proveedor predeterminado es un archivo JSON. Por defecto, el nombre de archivo buscado es **service-config.json**, y se busca en el directorio actual del proceso en ejecución, no en el directorio del ejecutable.

Puedes elegir cambiar el nombre del archivo, así como dónde Sisk debe buscar el archivo de configuración, con:

```csharp
using Sisk.Core.Http;
using Sisk.Core.Http.Hosting;

using var app = HttpServer.CreateBuilder()
    .UsePortableConfiguration(config =>
    {
        config.WithConfigFile("config.toml",
            createIfDontExists: true,
            lookupDirectories:
                ConfigurationFileLookupDirectory.CurrentDirectory |
                ConfigurationFileLookupDirectory.AppDirectory);
    })
    .Build();
```

El código anterior buscará el archivo **config.toml** en el directorio actual del proceso en ejecución. Si no se encuentra, buscará en el directorio donde está ubicado el ejecutable. Si el archivo no existe, se respeta el parámetro **createIfDontExists**, creando el archivo, sin contenido, en la última ruta probada (según **lookupDirectories**), y se lanza un error en la consola, impidiendo que la aplicación se inicialice.

> [!TIP]
> 
> Puedes consultar el código fuente del lector de configuración INI y del lector de configuración JSON para entender cómo se implementa un **IConfigurationProvider**.

## Lectura de configuraciones desde un archivo JSON

Por defecto, Sisk proporciona un proveedor de configuración que lee configuraciones desde un archivo JSON. Este archivo sigue una estructura fija y está compuesto por los siguientes parámetros:

```json
{
    "Server": {
        "DefaultEncoding": "UTF-8",
        "ThrowExceptions": true,
        "IncludeRequestIdHeader": true
    },
    "ListeningHost": {
        "Label": "My sisk application",
        "Ports": [
            "http://localhost:80/",
            "https://localhost:443/",  // Los archivos de configuración también admiten comentarios
        ],
        "CrossOriginResourceSharingPolicy": {
            "AllowOrigin": "*",
            "AllowOrigins": [ "*" ],   // nuevo en 0.14
            "AllowMethods": [ "*" ],
            "AllowHeaders": [ "*" ],
            "MaxAge": 3600
        },
        "Parameters": {
            "MySqlConnection": "server=localhost;user=root;"
        }
    }
}
```

Los parámetros creados a partir de un archivo de configuración pueden accederse en el constructor del servidor:

```csharp
using var app = HttpServer.CreateBuilder()
    .UsePortableConfiguration(config =>
    {
        config.WithParameters(paramCollection =>
        {
            string databaseConnection = paramCollection.GetValueOrThrow("MySqlConnection");
        });
    })
    .Build();
```

Cada lector de configuración proporciona una forma de leer los parámetros de inicialización del servidor. Algunas propiedades se indican para estar en el entorno del proceso en lugar de definirse en el archivo de configuración, como datos sensibles de API, claves de API, etc.

## Estructura del archivo de configuración

El archivo de configuración JSON está compuesto por las siguientes propiedades:

<table>
    <thead>
        <tr>
            <th>Property</th>
            <th>Mandatory</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Server</td>
            <td>Required</td>
            <td>Representa el propio servidor con sus configuraciones.</td>
        </tr>
        <tr>
            <td>Server.AccessLogsStream</td>
            <td>Optional</td>
            <td>Por defecto <code>console</code>. Especifica la corriente de salida del registro de acceso. Puede ser un nombre de archivo,
                <code>null</code> o <code>console</code>.
            </td>
        </tr>
        <tr>
            <td>Server.ErrorsLogsStream</td>
            <td>Optional</td>
            <td>Por defecto <code>null</code>. Especifica la corriente de salida del registro de errores. Puede ser un nombre de archivo,
                <code>null</code> o <code>console</code>.
            </td>
        </tr>
        <tr>
            <td>Server.MaximumContentLength</td>
            <td>Optional</td>
            <tr>
            <td>Server.MaximumContentLength</td>
            <td>Optional</td>
            <td>Especifica la longitud máxima del contenido en bytes. Cero significa infinito. Cuando el objeto <code>Server</code> está presente y esta propiedad se omite, el valor es <code>0</code> (infinito), lo que sobrescribe el valor predeterminado de 100 MB de <a href="/api/Sisk.Core.Http.HttpServerConfiguration.MaximumContentLength">HttpServerConfiguration.MaximumContentLength</a>.</td>
        </tr>
        <tr>
            <td>Server.IncludeRequestIdHeader</td>
            <td>Optional</td>
            <td>Por defecto <code>false</code>. Especifica si el servidor HTTP debe enviar el encabezado <code>X-Request-Id</code>.</td>
        </tr>
        <tr>
            <td>Server.ThrowExceptions</td>
            <td>Optional</td>
            <td>Por defecto <code>true</code>. Especifica si las excepciones no manejadas deben lanzarse. Establece <code>false</code> en producción y <code>true</code> durante la depuración.</td>
        </tr>
        <tr>
            <td>ListeningHost</td>
            <td>Required</td>
            <td>Representa el host de escucha del servidor.</td>
        </tr>
        <tr>
            <td>ListeningHost.Label</td>
            <td>Optional</td>
            <td>Representa la etiqueta de la aplicación.</td>
        </tr>
        <tr>
            <td>ListeningHost.Ports</td>
            <td>Required</td>
            <td>Representa un arreglo de cadenas, que coincide con la sintaxis de <a href="/api/Sisk.Core.Http.ListeningPort">ListeningPort</a>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy</td>
            <td>Optional</td>
            <td>Configura los encabezados CORS para la aplicación.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowCredentials</td>
            <td>Optional</td>
            <td>Por defecto <code>false</code>. Especifica el encabezado <code>Allow-Credentials</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.ExposeHeaders</td>
            <td>Optional</td>
            <td>Por defecto <code>null</code>. Esta propiedad espera un arreglo de cadenas. Especifica el encabezado <code>Expose-Headers</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowOrigin</td>
            <td>Optional</td>
            <td>Por defecto <code>null</code>. Esta propiedad espera una cadena. Especifica el encabezado <code>Allow-Origin</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowOrigins</td>
            <td>Optional</td>
            <td>Por defecto <code>null</code>. Esta propiedad espera un arreglo de cadenas. Especifica múltiples encabezados <code>Allow-Origin</code>. Consulta <a href="/api/Sisk.Core.Entity.CrossOriginResourceSharingHeaders.AllowOrigins">AllowOrigins</a> para más información.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowMethods</td>
            <td>Optional</td>
            <td>Por defecto <code>null</code>. Esta propiedad espera un arreglo de cadenas. Especifica el encabezado <code>Allow-Methods</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowHeaders</td>
            <td>Optional</td>
            <td>Por defecto <code>null</code>. Esta propiedad espera un arreglo de cadenas. Especifica el encabezado <code>Allow-Headers</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.MaxAge</td>
            <td>Optional</td>
            <td>Por defecto <code>null</code>. Esta propiedad espera un entero. Especifica el encabezado <code>Max-Age</code> en segundos.</td>
        </tr>
        <tr>
            <td>ListeningHost.Parameters</td>
            <td>Optional</td>
            <td>Especifica las propiedades proporcionadas al método de configuración de la aplicación.</td>
        </tr>
    </tbody>
</table>
