# Provedores de Serviço

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

Provedores de Serviço são uma forma de portar sua aplicação Sisk para diferentes ambientes com um arquivo de configuração portátil. Esse recurso permite alterar a porta do servidor, parâmetros e outras opções sem precisar modificar o código da aplicação para cada ambiente. Este módulo depende da sintaxe de construção do Sisk e pode ser configurado através do método UsePortableConfiguration.

Um provedor de configuração é implementado com IConfigurationProvider, que fornece um leitor de configuração e pode receber qualquer implementação. Por padrão, o Sisk fornece um leitor de configuração JSON, mas também há um pacote para arquivos INI. Você também pode criar seu próprio provedor de configuração e registrá-lo com:

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

Como mencionado anteriormente, o provedor padrão é um arquivo JSON. Por padrão, o nome de arquivo procurado é service-config.json, e ele é buscado no diretório atual do processo em execução, não no diretório do executável.

Você pode escolher alterar o nome do arquivo, bem como onde o Sisk deve procurar o arquivo de configuração, com:

```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();
```

O código acima procurará o arquivo config.toml no diretório atual do processo em execução. Se não for encontrado, ele buscará então no diretório onde o executável está localizado. Se o arquivo não existir, o parâmetro createIfDontExists será respeitado, criando o arquivo, sem conteúdo, no último caminho testado (com base em lookupDirectories), e um erro será lançado no console, impedindo a inicialização da aplicação.

> [!TIP]
> 
> Você pode olhar o código-fonte do leitor de configuração INI e do leitor de configuração JSON para entender como um IConfigurationProvider é implementado.

## Lendo configurações de um arquivo JSON

Por padrão, o Sisk fornece um provedor de configuração que lê configurações de um arquivo JSON. Este arquivo segue uma estrutura fixa e é composto pelos seguintes parâmetros:

```json
{
    "Server": {
        "DefaultEncoding": "UTF-8",
        "ThrowExceptions": true,
        "IncludeRequestIdHeader": true
    },
    "ListeningHost": {
        "Label": "My sisk application",
        "Ports": [
            "http://localhost:80/",
            "https://localhost:443/",  // Arquivos de configuração também suportam comentários
        ],
        "CrossOriginResourceSharingPolicy": {
            "AllowOrigin": "*",
            "AllowOrigins": [ "*" ],   // new on 0.14
            "AllowMethods": [ "*" ],
            "AllowHeaders": [ "*" ],
            "MaxAge": 3600
        },
        "Parameters": {
            "MySqlConnection": "server=localhost;user=root;"
        }
    }
}
```

Os parâmetros criados a partir de um arquivo de configuração podem ser acessados no construtor do servidor:

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

Cada leitor de configuração fornece uma forma de ler os parâmetros de inicialização do servidor. Algumas propriedades são indicadas para estar no ambiente do processo em vez de serem definidas no arquivo de configuração, como dados sensíveis de API, chaves de API, etc.

## Estrutura do arquivo de configuração

<table>
    <thead>
        <tr>
            <th>Propriedade</th>
            <th>Obrigatório</th>
            <th>Descrição</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Server</td>
            <td>Obrigatório</td>
            <td>Representa o próprio servidor com suas configurações.</td>
        </tr>
        <tr>
            <td>Server.AccessLogsStream</td>
            <td>Opcional</td>
            <td>Por padrão <code>console</code>. Especifica o fluxo de saída do log de acesso. Pode ser um nome de arquivo, <code>null</code> ou <code>console</code>.</td>
        </tr>
        <tr>
            <td>Server.ErrorsLogsStream</td>
            <td>Opcional</td>
            <td>Por padrão <code>null</code>. Especifica o fluxo de saída do log de erros. Pode ser um nome de arquivo, <code>null</code> ou <code>console</code>.</td>
        </tr>
        <tr>
            <td>Server.MaximumContentLength</td>
            <td>Opcional</td>
            <td>Especifica o comprimento máximo do conteúdo em bytes. Zero significa infinito. Quando o objeto <code>Server</code> está presente e esta propriedade é omitida, o valor é <code>0</code> (infinito), o que sobrescreve o padrão de 100 MB de <a href="/api/Sisk.Core.Http.HttpServerConfiguration.MaximumContentLength">HttpServerConfiguration.MaximumContentLength</a>.</td>
        </tr>
        <tr>
            <td>Server.IncludeRequestIdHeader</td>
            <td>Opcional</td>
            <td>Por padrão <code>false</code>. Especifica se o servidor HTTP deve enviar o cabeçalho <code>X-Request-Id</code>.</td>
        </tr>
        <tr>
            <td>Server.ThrowExceptions</td>
            <td>Opcional</td>
            <td>Por padrão <code>true</code>. Especifica se exceções não tratadas devem ser lançadas. Defina como <code>false</code> em produção e <code>true</code> ao depurar.</td>
        </tr>
        <tr>
            <td>ListeningHost</td>
            <td>Obrigatório</td>
            <td>Representa o host de escuta do servidor.</td>
        </tr>
        <tr>
            <td>ListeningHost.Label</td>
            <td>Opcional</td>
            <td>Representa o rótulo da aplicação.</td>
        </tr>
        <tr>
            <td>ListeningHost.Ports</td>
            <td>Obrigatório</td>
            <td>Representa um array de strings, correspondendo à sintaxe de <a href="/api/Sisk.Core.Http.ListeningPort">ListeningPort</a>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy</td>
            <td>Opcional</td>
            <td>Configura os cabeçalhos CORS para a aplicação.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowCredentials</td>
            <td>Opcional</td>
            <td>Por padrão <code>false</code>. Especifica o cabeçalho <code>Allow-Credentials</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.ExposeHeaders</td>
            <td>Opcional</td>
            <td>Por padrão <code>null</code>. Esta propriedade espera um array de strings. Especifica o cabeçalho <code>Expose-Headers</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowOrigin</td>
            <td>Opcional</td>
            <td>Por padrão <code>null</code>. Esta propriedade espera uma string. Especifica o cabeçalho <code>Allow-Origin</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowOrigins</td>
            <td>Opcional</td>
            <td>Por padrão <code>null</code>. Esta propriedade espera um array de strings. Especifica múltiplos cabeçalhos <code>Allow-Origin</code>. Veja <a href="/api/Sisk.Core.Entity.CrossOriginResourceSharingHeaders.AllowOrigins">AllowOrigins</a> para mais informações.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowMethods</td>
            <td>Opcional</td>
            <td>Por padrão <code>null</code>. Esta propriedade espera um array de strings. Especifica o cabeçalho <code>Allow-Methods</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.AllowHeaders</td>
            <td>Opcional</td>
            <td>Por padrão <code>null</code>. Esta propriedade espera um array de strings. Especifica o cabeçalho <code>Allow-Headers</code>.</td>
        </tr>
        <tr>
            <td>ListeningHost.CrossOriginResourceSharingPolicy.MaxAge</td>
            <td>Opcional</td>
            <td>Por padrão <code>null</code>. Esta propriedade espera um inteiro. Especifica o cabeçalho <code>Max-Age</code> em segundos.</td>
        </tr>
        <tr>
            <td>ListeningHost.Parameters</td>
            <td>Opcional</td>
            <td>Especifica as propriedades fornecidas ao método de configuração da aplicação.</td>
        </tr>
    </tbody>
</table>
