-
Notifications
You must be signed in to change notification settings - Fork 125
#700 & #701: HTTPClient.shared a globally shared singleton #705
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
0aaeddf
to
42b1218
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM. Some small doc nits and I think we should highlight the new .shared
singleton a bit in docs.
2848911
to
ecf4bca
Compare
5384e59
to
784e0b5
Compare
/// - Linux (non-Android): Google Chrome | ||
/// | ||
/// - note: Don't rely on the values in here never changing, they will be adapted to better match the platform's default/prevalent browser. | ||
public static var browserLike: HTTPClient.Configuration { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced about this naming. Browser's have very strict rules about when to reuse a connection concerning cookies and auth headers. AHC does not implement any of those rules. It is questionable if AHC should implement those rules at all, since the use-case is very different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, this Configuration
aims to match this as closely as possible. It doesn't say that it's a perfect match and if we can't/won't implement something then that's okay.
The reason I think "browser like" is good is that it tells the users that we won't make arbitrary changes that diverge further from what browsers do. And also that it's a property that evolves (if anything we converge with what browsers do). For example, we can't change the meaning of Configuration()
because the user has certain expectations of it and may only change the properties they wish to change. With .browserLike
it's pretty clear that over time we will converge with what browsers do. That should make it clear that if you need a specific setting then don't use browserLike
and configure your own HTTPClient
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, this
Configuration
aims to match this as closely as possible. It doesn't say that it's a perfect match and if we can't/won't implement something then that's okay.
I can see your argument here, but I don't think that it is the right one, given that we throw our arms in the air when it comes to connection trust and reuse. All the security guarantees that users might associate with browser are completely non existent in AHC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we do implement them by not sending cookies at all, that's even more secure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in: browsers try (by implementing elaborate policies) to not send cookies to the wrong place. AHC also doesn't send cookies to the wrong place because I don't think it sends cookies to anything unless the user manually attaches right cookie headers manually, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fabianfett are you okay with keeping the browserLike
name here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah generally looks good. I think docs could still be clearer. There is still a httpClient.execute
in the first code example. Is the idea that people should use the shared instance by default? Maybe you need to have a section indicating the difference between using the shared instance and instantiating your own instance.
An an aside this is great timing for me. Soto is in alpha for a major version so I can ditch all the code that was managing my http client and just assume it is being managed outside of Soto.
I'm somewhat worried about this tbh and am wordering if rephrasing these APIs a bit could help? What if we documented "do a The docs could literarily say that the simplest way is:
and you can just exit the process if you want to -- you may lose in flight requests or whatever. And then we explain, well, if you do care -- please hook into service lifecycle, (and here's how ...). If folks don't care they can literarily plop a global The "make" could function the same as this " Note also that a global will become main actor isolated in Swift 6 most likely, so there will be a hop like that. The SDK will have the same issue, so yeah we'd be on equal footing, but I am wondering if we can't do better and recommend things like:
to avoid un-necessary hops to the global actor...? Either way, at least tracing in applications "will work" but Fabian's concern that parallel testing with asserting on traces will be impacted and not usable if shared instances are used. So... I guess this is fine, but I'm not very happy about it but I see the value provided of the simplicity here -- I'd like to consider if we can at least recommend "to the global variable yourself" and change how we phrase it in order to make "move away from static global func everywhere" less painful when people will need to do so. |
Hi, Has there been any progress on this PR? |
I'm eager for this change. It resolves the main issues I see people (including myself at times) run into with libraries that depend on AHC, and I feel that 99% of people will want the default configuration for AHC anyways. This change makes it much easier to set up libraries based on AHC for end-users, in addition to making it more accessible to send HTTP requests. One issue I tend to run into during (Lambda) application setup is that I need to fetch secrets before booting the remainder of services. If anything errors during this phase, and AHC is not correctly shut down under failing circumstances, the |
I'm also looking forward to be able to use this, but I do still want the configurability. Perhaps we can use some mechanism like Some libraries like the "aws-lambda" can provide APIs to users to be able to do a "pre-setup" so users can setup stuff like the |
After reading a recommendation to switch over from URLSession to this package, I too would love to see this land! |
Just today was working with AHC and wondering—what is the best way to work with the client? It's not very clear from description. The thing is, it became very manual to check all creations/shutdowns of clients, even for our small service, wondering how it's for bigger apps... So this PR is very welcoming. Though I have some questions:
Anyway, looking forward for PR to be merged! 🙂 |
If you are writing an app, then using a singleton like this is almost certainly the best approach. The main reason to use non-singleton clients is to isolate state. This is useful if you have separate privacy domains (e.g. different credentials, TLS identities, cookies, etc.) or if you want to be sure you're starting from a clean slate when you're writing tests. Otherwise, you should have long-lived clients and except in rare cases you should never shut them down. |
4d09635
to
ebbd85f
Compare
ebbd85f
to
b52a50a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it!
b52a50a
to
f2aef5f
Compare
build timeout:
|
@swift-server-bot test failed |
@swift-server-bot test this please |
Would love to see a release with this in. I'm just about to release the beta for Soto and this allows me to get rid of the requirement to shutdown the Soto client, as I don't have to manage an HTTPClient |
I would caution against Soto relying solely on If you design Soto to not have a shutdown, then Soto essentially becomes a singleton-only library which I don't think is a good and scalable design. What I would recommend is to design Soto to have a correct lifecycle and make shutdown calls always required. But additionally you may offer your own Personally I think it's really important that on the server side all important libraries have correct lifecycles and here are some of the reasons why:
|
Soto would not rely on the But I would like to be in the position where Soto is not controlling the lifecycle of of a HTTPClient. Currently the options for Soto are provide your own HTTPClient or Soto will create one for you. I would prefer it to be provide your own HTTPClient or Soto will use the shared instance. |
Yes, all are options. I'd just make sure that the API contracts are spelled with an always/never. Like in HTTPClient (I hope we removed exceptions):
In the past we tried this misguided I'd suggest a similar design in Soto: Either lifecycle or singleton, but not a combination thereof. Aside: I would imagine that over time Soto will have to manage other resources that aren't just a HTTPClient too. If you already have a |
Offer
HTTPClient.shared
, a global singletonHTTPClient
that doesn't need shutdown (because it lives as long as your application). This globally sharedHTTPClient
does not accept any special configuration and usesHTTPClient.Configuration.singletonConfiguration
(also introduced in this PR) which tries to mimic the platform's default browser as closely as possible.HTTPClient.Configuration.browserLike
#701