feat: Support universe domain for Discovery based libraries#2675
Conversation
| /// Otherwise <paramref name="defaultUri"/>. | ||
| /// </list> | ||
| /// </returns> | ||
| protected internal string GetEffectiveUri(string explicitUri, string defaultUri) |
There was a problem hiding this comment.
@jskeet this is the method that we'll be using from generated code to calculate the base URI and the batch URI. I'll send that PR out tomorrow.
jskeet
left a comment
There was a problem hiding this comment.
A few nits, but generally fine.
| public static class HttpRequestMessageExtensions | ||
| { | ||
| /// <summary> | ||
| /// Set's the given key/value pair as a request option. |
There was a problem hiding this comment.
Done, and on the Get's below as well
| /// <summary> | ||
| /// Extension methods for <see cref="HttpRequestMessage"/>. | ||
| /// </summary> | ||
| public static class HttpRequestMessageExtensions |
There was a problem hiding this comment.
Rather than making this public, I wonder whether it would be better to have the same code in both projects. That way we can remove it entirely (eventually - it may be a very long time) without affecting the public API at all. We only really want it to be used in our projects, right?
There was a problem hiding this comment.
Yep, we only want it in our projects. But it's really in 3 projects that we need this: Google.Apis.Core, Google.Apis and Google.Apis.Auth. And, apart from the triplication, we need to keep it very much in sync because what is set on one side, needs to be equivalently read on the other side.
Plus, the dreprecation path for this is very very clear, with the alternative being "use the .NET provided Options collection instead", which is to say, I think we can deprecate it eventually, and remove after some significant time without a major version.
What do you think?
There was a problem hiding this comment.
Actually removing it would then be a binary breaking change, so I'd be nervous about doing that in a minor version.
Given that they need to be kept in sync, how about doing this in one source file that's linked in all three projects? I don't mind it being in the same namespace in all three assemblies.
There was a problem hiding this comment.
We discussed offline. A linked file generates some ambiguity issues in test projects so we are going with 3 identical copies.
| // it for the batch endpoint as well. The batch endpoint does not have an | ||
| // override mechanism, so we pass explicitUri as null in that case. | ||
|
|
||
| if (explicitUri is not null) |
There was a problem hiding this comment.
Possibly convert this all into a conditional ?: operator? (Could even use ?? and then a single ?: operator:
explicitUri ??
(UniverseDomain is not null
? defaultUri?.Replace(DefaultUniverseDomain, UniverseDomain)
: defaultUri)| /// <summary> | ||
| /// Key for a universe domain in a <see cref="HttpRequestMessage"/> options. | ||
| /// </summary> | ||
| public const string UniverseDomainKey = "__UniverseDomainKey"; |
There was a problem hiding this comment.
Does this need to be public?
There was a problem hiding this comment.
Not really, but all the other keys here were public already.
And we don't have to duplicate it in Google.Apis.Auth.
Happy to make it internal or private though, let me know.
There was a problem hiding this comment.
Would prefer to "default to internal" in general. We've definitely made more things public here than was probably wise (and the Google.Apis vs Google.Apis.Core split doesn't help; something we should consider addressing if we ever create a new major version) but I think it's worth trying to stop adding extra public things that don't need to be public.
There was a problem hiding this comment.
Yep, made internal.
| { | ||
| HttpRequestMessage request = new HttpRequestMessage(); | ||
|
|
||
| GoogleCredential credential = GoogleCredential.FromAccessToken("fake_token"); |
There was a problem hiding this comment.
Maybe just declare this using type IHttpExecuteInterceptor here, to avoid the "as" below?
| } | ||
|
|
||
| [Fact] | ||
| public async Task UniverseDomain_CustomInRequestAndCredential() |
There was a problem hiding this comment.
Maybe "DifferentCustomInRequestAndCredential"?
| if (targetUniverseDomain != credentialUniverseDomain) | ||
| { | ||
| throw new InvalidOperationException( | ||
| $"The service client universe domain {targetUniverseDomain} does not match the credential universe domain {credentialUniverseDomain}."); |
60c67de to
5f8263e
Compare
amanda-tarafa
left a comment
There was a problem hiding this comment.
@jskeet I've addressed or replied to all your comments. Changes are in ordered commits starting with "Address review".
Let me know what you think about the two remaining threads regarding visibility. I prefer them as they are, but that's not a hard preference for either.
| public static class HttpRequestMessageExtensions | ||
| { | ||
| /// <summary> | ||
| /// Set's the given key/value pair as a request option. |
There was a problem hiding this comment.
Done, and on the Get's below as well
| /// <summary> | ||
| /// Extension methods for <see cref="HttpRequestMessage"/>. | ||
| /// </summary> | ||
| public static class HttpRequestMessageExtensions |
There was a problem hiding this comment.
Yep, we only want it in our projects. But it's really in 3 projects that we need this: Google.Apis.Core, Google.Apis and Google.Apis.Auth. And, apart from the triplication, we need to keep it very much in sync because what is set on one side, needs to be equivalently read on the other side.
Plus, the dreprecation path for this is very very clear, with the alternative being "use the .NET provided Options collection instead", which is to say, I think we can deprecate it eventually, and remove after some significant time without a major version.
What do you think?
| // it for the batch endpoint as well. The batch endpoint does not have an | ||
| // override mechanism, so we pass explicitUri as null in that case. | ||
|
|
||
| if (explicitUri is not null) |
| /// <summary> | ||
| /// Key for a universe domain in a <see cref="HttpRequestMessage"/> options. | ||
| /// </summary> | ||
| public const string UniverseDomainKey = "__UniverseDomainKey"; |
There was a problem hiding this comment.
Not really, but all the other keys here were public already.
And we don't have to duplicate it in Google.Apis.Auth.
Happy to make it internal or private though, let me know.
| { | ||
| HttpRequestMessage request = new HttpRequestMessage(); | ||
|
|
||
| GoogleCredential credential = GoogleCredential.FromAccessToken("fake_token"); |
| } | ||
|
|
||
| [Fact] | ||
| public async Task UniverseDomain_CustomInRequestAndCredential() |
| if (targetUniverseDomain != credentialUniverseDomain) | ||
| { | ||
| throw new InvalidOperationException( | ||
| $"The service client universe domain {targetUniverseDomain} does not match the credential universe domain {credentialUniverseDomain}."); |
jskeet
left a comment
There was a problem hiding this comment.
All "address review" commits look good to me. I have a preference for avoiding the public extension method, but can live with it if you don't want the internal complexity of a linked source file.
5f8263e to
ab34224
Compare
amanda-tarafa
left a comment
There was a problem hiding this comment.
@jskeet Outstanding visibility concerns addressed in sorted "Address review" commits. PTAL.
(I'll squash most of these before merging)
| /// <summary> | ||
| /// Key for a universe domain in a <see cref="HttpRequestMessage"/> options. | ||
| /// </summary> | ||
| public const string UniverseDomainKey = "__UniverseDomainKey"; |
There was a problem hiding this comment.
Yep, made internal.
| /// <summary> | ||
| /// Extension methods for <see cref="HttpRequestMessage"/>. | ||
| /// </summary> | ||
| public static class HttpRequestMessageExtensions |
There was a problem hiding this comment.
We discussed offline. A linked file generates some ambiguity issues in test projects so we are going with 3 identical copies.
|
|
||
| using System.Net.Http; | ||
|
|
||
| namespace Google.Apis.Util.Extensions; |
There was a problem hiding this comment.
Why the ".Extensions" bit? We don't have that for TaskExtensions for example.
Perhaps this was left over from trying to do the link version?
There was a problem hiding this comment.
It's intentional, because in tests we already import Google.Apis.Util for other things. So, if we don't put these in specific namespaces, we'd still have the problem of ambiguity.
Note that most the namespaces in Google.Apis.Core are missing the Core bit (except for a few newly added and interal classes) so in Google.Apis.Core we also have Google.Apis.Util, so there I had to do Google.Apis.Core.Util.Extensions.
There was a problem hiding this comment.
Righto. Will take a closer look in the morning, but approve now as I'm sure it's fine - feel free to merge.
There was a problem hiding this comment.
OK, I know what we can do, we can test the one in Google.Apis instead of the one in Google.Apis.Core and then we can get rid of the Extensions in both. We still need to keep the Google.Apis.Core.Util though (instead of Google.Apis.Util that we normally have in Google.Apis.Core).
There was a problem hiding this comment.
Another option is to not use them as extension methods in tests - call them with fully-qualified names (Google.Apis.Utils.HttpRequestMessageExtensions.Xyz()) so the collision doesn't matter.
There was a problem hiding this comment.
Yes, but that still needs us to have the odd Google.Apis.Core.Utils: it's just Google.Apis.Utils even in Google.Apis.Core, that's the main problem, that in Google.Apis.Core we don't use Core in namespaces. I'm pushing shortly, I've had to use Core or else there's no way to disambiguate, but I was able to drop the Extensions bit.
There was a problem hiding this comment.
Pushed:
- The third commit is new, so that everything is normalized.
- And the two Addres Review commits have changed. We still have to use Google.Apis.Core.Utils in Google.Apis.Core even though the norma would have been to use Google.Apis.Utils.
ab34224 to
17f1315
Compare
We don't use Core in Google.Apis.Core, just Google.Apis.
The decision is hidden in HttpRequestMessage extension methods. Note that we had to use the namespace Google.Apis.Core.Utils in the Google.Apis.Core project even though normally it would have been just Google.Apis.Utils.
- The universe domain may be specified through the client service initializer. - A helper method to calculate effective URIs that takes into account the universe domain. This method is to be used by generated code, see googleapis/gapic-generator-csharp#746. - The universe domain is passed as a request option for the credential to validate against when intercepting and before setting the token.
17f1315 to
26e3450
Compare
|
I've squashed everything into more meaningful commits, I'll merge on green. |
@jskeet as always, one commit at a time. And I've left a note for you to flag the method we are using from generated code.