# INI configuration provider

Source: https://docs.sisk-framework.org/docs/extensions/ini-configuration.html

Sisk has a method for obtaining startup configurations other than JSON. In fact, any pipeline that implements [IConfigurationReader](https://docs.sisk-framework.org/api/Sisk.Core.Http.Hosting.IConfigurationReader.md) can be used with [PortableConfigurationBuilder.WithConfigurationPipeline](https://docs.sisk-framework.org/api/Sisk.Core.Http.Hosting.PortableConfigurationBuilder.md), reading the server configuration from any file type.

The [Sisk.IniConfiguration](https://www.nuget.org/packages/Sisk.IniConfiguration/) package provides a stream-based INI file reader that does not throw exceptions for common syntax errors and has a simple configuration syntax. This package can be used outside the Sisk framework, offering flexibility for projects that require an efficient INI document reader.

## Installing

To install the package, you can start with:

```bash
$ dotnet add package Sisk.IniConfiguration
```

You can also install the core package, which doens't includes the INI [IConfigurationReader](https://docs.sisk-framework.org/api/Sisk.Core.Http.Hosting.IConfigurationReader), neither the Sisk dependency, just the INI serializers:

```bash
$ dotnet add package Sisk.IniConfiguration.Core
```

With the main package, you can use it in your code as shown in the example below:

```cs
class Program
{
    static HttpServerHostContext Host = null!;

    static void Main(string[] args)
    {
        Host = HttpServer.CreateBuilder()
            .UsePortableConfiguration(config =>
            {
                config.WithConfigFile("app.ini", createIfDontExists: true);
                
                // uses the IniConfigurationReader configuration reader
                config.WithConfigurationPipeline<IniConfigurationReader>();
            })
            .UseRouter(r =>
            {
                r.MapGet("/", SayHello);
            })
            .Build();
        
        Host.Start();
    }

    static HttpResponse SayHello(HttpRequest request)
    {
        string? name = Host.Parameters["name"] ?? "world";
        return new HttpResponse($"Hello, {name}!");
    }
}
```

The code above will look for an app.ini file in the process's current directory (CurrentDirectory). The INI file looks like this:

```ini
[Server]
# Multiple listen addresses are supported
Listen = http://localhost:5552/
Listen = http://localhost:5553/
ThrowExceptions = false
AccessLogsStream = console

[Cors]
AllowMethods = GET, POST
AllowHeaders = Content-Type, Authorization
AllowOrigin = *

[Parameters]
Name = "Kanye West"
```

## INI flavor and syntax

Current implementation flavor:

- Properties and section names are **case-insensitive**.
- Properties names and values are **trimmed**, unless values are quoted.
- Values can be quoted with single or double quotes. Quotes can have line-breaks inside them.
- Comments are supported with `#` and `;`. Also, **trailing comments are allowed**.
- Properties can have multiple values.

In detail, the documentation for the "flavor" of the INI parser used in Sisk is [available in this document](https://github.com/sisk-http/archive/blob/master/ext/ini-reader-syntax.md).

Using the following ini code as example:

```ini
One = 1
Value = this is an value
Another value = "this value
    has an line break on it"

; the code below has some colors
[some section]
Color = Red
Color = Blue
Color = Yellow ; do not use yellow
```

Parse it with:

```csharp
// parse the ini text from the string
IniDocument doc = IniDocument.FromString(iniText);

// get one value
string? one = doc.Global.GetOne("one");
string? anotherValue = doc.Global.GetOne("another value");

// get multiple values
string[]? colors = doc.GetSection("some section")?.GetMany("color");
```

## Configuration parameters

| Section and name | Allow multiple values | Description |
| ---------------- | --------------------- | ----------- |
| `Server.Listen` | Yes | The server listening addresses/ports. |
| `Server.Encoding` | No | The server default encoding. |
| `Server.MaximumContentLength` | No | The server max content-length size in bytes. |
| `Server.IncludeRequestIdHeader` | No | Specifies if the HTTP server should send the X-Request-Id header. |
| `Server.ThrowExceptions` | No |  Specifies if unhandled exceptions should be thrown.  |
| `Server.AccessLogsStream` | No |  Specifies the access log output stream. |
| `Server.ErrorsLogsStream` | No |  Specifies the error log output stream. |
| `Cors.AllowMethods` | No |  Specifies the CORS Allow-Methods header value. |
| `Cors.AllowHeaders` | No |  Specifies the CORS Allow-Headers header value. |
| `Cors.AllowOrigins` | No |  Specifies multiples Allow-Origin headers, separated by commas. [AllowOrigins](https://docs.sisk-framework.org/api/Sisk.Core.Entity.CrossOriginResourceSharingHeaders.AllowOrigins.md) for more information. |
| `Cors.AllowOrigin` | No |  Specifies one Allow-Origin header. |
| `Cors.ExposeHeaders` | No |  Specifies the CORS Expose-Headers header value. |
| `Cors.AllowCredentials` | No |  Specifies the CORS Allow-Credentials header value. |
| `Cors.MaxAge` | No |  Specifies the CORS Max-Age header value. |
