Skip to content

Conversation

@hamzahrmalik
Copy link
Contributor

Users should be able to use swift-configuration to create the http client configuration object

Changes

  • duplicate package.swift to create a separate version for 6.0 and 6.1, since Configuration is 6.2+
  • add helper to create http client configuration using ConfigReader

public init(configReader: ConfigReader) throws {
self.init()

// Each entry in the list should be a colon separated pair e.g. localhost:127.0.0.1 or localhost:::1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not comma-separated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

colon felt more natural to me for defining key-value pairs. I don't mind though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comma would probably make the ipv6 case slightly eaiser to parse too

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, comma might be used for splitting the pairs themselves e.g. in env vars. Hmm then comma isn't great, but colon is a bit confusing.

@czechboy0
Copy link

lgtm, I'll let the maintainers actually approve though 🙂

Comment on lines +9 to +14
/// - `dnsOverrides` (string array, optional): Colon-separated host:IP pairs for DNS overrides (e.g., "localhost:127.0.0.1").
/// - `redirect` (scoped): Redirect handling configuration read by ``RedirectConfiguration/init(configReader:)``.
/// - `timeout` (scoped): Timeout configuration read by ``Timeout/init(configReader:)``.
/// - `connectionPool` (scoped): Connection pool configuration read by ``ConnectionPool/init(configReader:)``.
/// - `httpVersion` (string, optional, default: automatic): HTTP version to use ( "automatic" or "http1Only").
/// - `maximumUsesPerConnection` (int, optional, default: nil, no limit): Maximum uses per connection.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used dots for hierarchy but camel case for words

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dns.overrides and http.version make sense in that system. But maximum.uses.per.connection does not

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be connection.limits.maximum.uses. It is not the end of the world but it would be great if we could be a bit consistent around the ecosystem. @czechboy0 WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah i like that idea

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been doing the same as Hamzah - use dots for separating components, with individual components being camelCase. So http.maxConnectionCount, for example.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we document this somewhere? It feels like that would be good to have a recommendation at least for the ecosystem.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apple/swift-configuration#145

Feel free to add more questions to the issue, will add docs on this

@czechboy0 czechboy0 added the 🆕 semver/minor Adds new public API. label Jan 21, 2026
Comment on lines +162 to +164
let testProvider = InMemoryProvider(values: [
"dnsOverrides": .init(.stringArray(["invalidentry", "localhost:127.0.0.1"]), isSecret: false)
])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about spaces:

localhost: 127.0.0.1

Are we fine with the silent error here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will make it trim spaces, i think that's going to be the least surprising behaviour

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we think it's preferable to throw an error on invalid config? It would make it much more clear i suppose

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think throwing an error if the value of a key isn't valid is very reasonable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines 247 to 259
@Test
@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *)
func singleDnsOverride() throws {
let testProvider = InMemoryProvider(values: [
"dnsOverrides": .init(.stringArray(["api.example.com:10.0.0.1"]), isSecret: false)
])

let configReader = ConfigReader(provider: testProvider)
let config = try HTTPClient.Configuration(configReader: configReader)

#expect(config.dnsOverride["api.example.com"] == "10.0.0.1")
#expect(config.dnsOverride.count == 1)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the point of this test? what is tested here, that the other tests miss?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not needed. i think i wrote this one first but the other ones cover this and more so i'll remove it

@@ -0,0 +1,124 @@
// swift-tools-version:6.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way without duplicating, all the Package.swifts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not that i know of

@fabianfett
Copy link
Member

Am I correctly assuming, that this new behavior is only available to newly created clients and not the default shared one? If yes, is this the intended behavior?

@hamzahrmalik
Copy link
Contributor Author

Am I correctly assuming, that this new behavior is only available to newly created clients and not the default shared one? If yes, is this the intended behavior?

The changes in this PR allow you to create a configuration from a configuration reader

You can then use that configuration to make a client

The shared client does not support a custom configuration. Therefore you are correct that the changes in this PR do not apply to the singleton

@FranzBusch
Copy link
Collaborator

The shared client does not support a custom configuration. Therefore you are correct that the changes in this PR do not apply to the singleton

I think this is expected for now. We could think about letting the singleton client use the EnviornmentConfigProvider in the future but I would keep that in a separate PR to think about it more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🆕 semver/minor Adds new public API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants