Unify configuration
Implementation of #234
This is a draft of the implementation, I'm opening to check if the approach makes sense. cc: @teamon
Proposed solution
Use nimble_options to validate the opts given to a middleware. For a option to be fetched from Application Configuration, it needs to set global: true in the config_schema of the middleware.
It follows a clear precedence of first fetching from application and then overriding with the configuration given directly as options to the middleware. It also always fetches the configuration in runtime.
Based on the schema a documentation for the options is generated:

TODO
- [ ] Documentation
- [ ] Unit Tests
- [ ] Use in all middlewares
Thank you, @thiamsantos, for picking this up!
I think this looks good, especially that it would introduce proper options validation instead of ad-hoc solutions implemented in some middlewares. I'm naturally hesitant with introducing a new dependency, but since it will be used by all middlewares it makes sense to include it (instead of reimplement option validation inside tesla).
In general, there are two cases that need to be taken care of:
- Client module in the same codebase - full access to code, configuration can be done via options passed directly to middleware, application env useful when providing different setting for different environments (dev/test/prod)
- Client module from third-party library - no direct access to code, configuration only possible if exposed or via application env
Recently, I've been using this pattern to configure first-party clients:
defmodule SomeAPI do
def get_foo(client \\ new(), id), do: ...
def new(opts \\ []) do
config = Application.get_env(:myapp, __MODULE__, [])
opts = Keyword.merge(config, opts)
middleware = [
{Tesla.Middleware.BaseUrl, opts[:base_url]},
...
]
Tesla.client(middleware, config[:adapter])
end
end
It is especially useful for changing base URL and/or adapter in test.
@hodak @amatalai @rafapaez Would you mind taking a look at this proposal in terms of how would it affect your codebases?
cc @elixir-tesla/tesla