Skip to content
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

feat: UrlSigner supports custom endpoints #12042

Merged
merged 6 commits into from
Mar 6, 2024

Conversation

amanda-tarafa
Copy link
Contributor

@amanda-tarafa amanda-tarafa commented Mar 5, 2024

And can be built from StorageClient

Closes #11313

@jskeet as always, one commit at a time. And a couple of notes:

@amanda-tarafa amanda-tarafa requested review from a team as code owners March 5, 2024 00:33
@amanda-tarafa amanda-tarafa force-pushed the storage-url-signer branch 2 times, most recently from 343a743 to 252d85d Compare March 5, 2024 06:09
Copy link
Collaborator

@jskeet jskeet left a comment

Choose a reason for hiding this comment

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

Almost entirely comment typos - but I think we should discuss the property vs method choice (unless you're happy to just make the change).

@@ -174,15 +195,31 @@ public sealed class Options
/// <param name="urlStyle">The new url style.</param>
/// <returns>A new set ofoptions with the given url style.</returns>
public Options WithUrlStyle(UrlStyle urlStyle) =>
new Options(Duration, Expiration, SigningVersion, urlStyle, Scheme, null);
new Options(Duration, Expiration, SigningVersion, urlStyle, Scheme, Host, Port, null);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Possibly note that this clears BucketBoundHostname? I'm pretty sure that's deliberate, but it confused me for a while.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, yes, done.

@@ -240,6 +241,45 @@ public void WithPort_Null()
Assert.NotSame(options, newOptions);
Assert.Null(newOptions.Port);
}

[Fact]
public void WithDefultOverrides_NullOverrideValues()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Defult => Default here and in the other tests

(And while amending this commit, the message is missing an "r" from "URLSigner".)

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, done, both, and default here and eerywhere.

{
/// <summary>
/// Overrides for default values for some of the options in <see cref="Options"/>.
/// Useful for creating signers where signing options default to specific valued, for instance
Copy link
Collaborator

Choose a reason for hiding this comment

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

valued => values

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


/// <summary>
/// The host to use for generating the signed URL.
/// This will never be null. If null is specified in <see cref="WithHost(string)"/>
/// then <see cref="DefaultStorageHost"/> will be used.
/// Will be ignored if <see cref="UrlStyle"/> is set to <see cref="UrlStyle.BucketBoundHostname"/>.
/// </summary>
public string Host { get; }
public string Host => ExplicitHost ?? DefaultOptionsOverrides?.Host ?? DefaultStorageHost;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the comment on line 82 may need to be amended.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, done.

TimeSpan? duration, DateTimeOffset? expiration, SigningVersion version, UrlStyle? urlStyle, string scheme, string host, int? port, string bucketBoundHostname)
/// <summary>
/// Values to be used as default for some options in case they are not set,
/// instead of the usual default values.May be null.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: space after the period before "May be null"

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

internal UrlSigner WithClock(IClock clock) => new UrlSigner(_blobSignerProvider, clock, _defaultOptionsOverrides);

/// <summary>
/// Returns a URL signer identical to this one, excepto for the default options overrides used for signing.
Copy link
Collaborator

Choose a reason for hiding this comment

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

excepto => except

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

/// on compatible credentials.
/// </summary>
/// <remarks>
/// Because credentials used by this client may changed, this property will return a new <see cref="UrlSigner"/> instance
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it would be better to make this a method (CreateUrlSigner()) in that case. It just makes it really clear - and it's unlikely to be significantly harder to use that way.

I'd argue that when it's a method, we should allow any exceptions to propagate instead of returning null, too. (Or maybe have a TryCreateUrlSigner method that returns null.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I debated over this, settled on a property, but I wasn't convinced. I'm adding the method then, CreateUrlSigner and letting exceptions bobble up.

Copy link
Contributor Author

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

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

All comments addressed on ordered commits prefixed review:.

Also, take a look at the Firestore change, or let me know if you'd prefer me to bring that out to another PR. According to googleapis/conformance-tests#84 you were fine with this, and it's simple enough though.

@@ -174,15 +195,31 @@ public sealed class Options
/// <param name="urlStyle">The new url style.</param>
/// <returns>A new set ofoptions with the given url style.</returns>
public Options WithUrlStyle(UrlStyle urlStyle) =>
new Options(Duration, Expiration, SigningVersion, urlStyle, Scheme, null);
new Options(Duration, Expiration, SigningVersion, urlStyle, Scheme, Host, Port, null);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, yes, done.

@@ -240,6 +241,45 @@ public void WithPort_Null()
Assert.NotSame(options, newOptions);
Assert.Null(newOptions.Port);
}

[Fact]
public void WithDefultOverrides_NullOverrideValues()
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, done, both, and default here and eerywhere.

{
/// <summary>
/// Overrides for default values for some of the options in <see cref="Options"/>.
/// Useful for creating signers where signing options default to specific valued, for instance
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


/// <summary>
/// The host to use for generating the signed URL.
/// This will never be null. If null is specified in <see cref="WithHost(string)"/>
/// then <see cref="DefaultStorageHost"/> will be used.
/// Will be ignored if <see cref="UrlStyle"/> is set to <see cref="UrlStyle.BucketBoundHostname"/>.
/// </summary>
public string Host { get; }
public string Host => ExplicitHost ?? DefaultOptionsOverrides?.Host ?? DefaultStorageHost;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, done.

TimeSpan? duration, DateTimeOffset? expiration, SigningVersion version, UrlStyle? urlStyle, string scheme, string host, int? port, string bucketBoundHostname)
/// <summary>
/// Values to be used as default for some options in case they are not set,
/// instead of the usual default values.May be null.
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

internal UrlSigner WithClock(IClock clock) => new UrlSigner(_blobSignerProvider, clock, _defaultOptionsOverrides);

/// <summary>
/// Returns a URL signer identical to this one, excepto for the default options overrides used for signing.
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

/// on compatible credentials.
/// </summary>
/// <remarks>
/// Because credentials used by this client may changed, this property will return a new <see cref="UrlSigner"/> instance
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I debated over this, settled on a property, but I wasn't convinced. I'm adding the method then, CreateUrlSigner and letting exceptions bobble up.

Copy link
Collaborator

@jskeet jskeet left a comment

Choose a reason for hiding this comment

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

Only nits left :)

@@ -65,8 +65,7 @@ public sealed class Options
/// <summary>
/// The Scheme to use for the request. Only http or https supported.
/// This will never be null. If null is specified in <see cref="WithScheme(string)"/>
/// then https will be used.
/// Defaults to https.
/// an appropiate default value will be used.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit (sorry) - appropiate => appropriate

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

@@ -79,7 +78,7 @@ public sealed class Options
/// <summary>
/// The host to use for generating the signed URL.
/// This will never be null. If null is specified in <see cref="WithHost(string)"/>
/// then <see cref="DefaultStorageHost"/> will be used.
/// then the appropiate default value will be used.
Copy link
Collaborator

Choose a reason for hiding this comment

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

And again

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

@@ -167,6 +132,29 @@ public UrlSigner UrlSigner
UnauthenticatedAccess = true
}.Build();

/// <summary>
/// Creates a URL signer built base on this client, that is using the same credential as this client, as well
Copy link
Collaborator

Choose a reason for hiding this comment

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

base => based (and maybe remove the "built"?)

is using => uses

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

@@ -167,6 +132,29 @@ public UrlSigner UrlSigner
UnauthenticatedAccess = true
}.Build();

/// <summary>
/// Creates a URL signer built base on this client, that is using the same credential as this client, as well
/// as defaulting to this client's URI scheme, host and port. If the credential used by this client is not compatible
Copy link
Collaborator

Choose a reason for hiding this comment

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

Possibly just use <exception> instead of summary for the exception bit? (I don't mind either way.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Duh, yes.

/// See <see cref="UrlSigner"/>'s documentation for more information on compatible credentials.
/// </summary>
/// <remarks>
/// Because credentials used by this client may changed, this method will always return a new <see cref="UrlSigner"/> instance
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we can probably remove these remarks now - I'd expect a method called "Create" to return a new instance anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, done

// If the original URI didn't specify a port, we want signed URLs to not have a port either;
// but Uri.Port returns the default port for the URI scheme when the port was not specified on the
// original URI.
baseUri.IsDefaultPort && !Service.BaseUri.Contains(baseUri.Port.ToString()) ? null : baseUri.Port));
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd personally move this logic (including the comment) into a separate local variable declaration of port, so we can then just use new UrlSigner.DefaultOptionsOverrides(baseUri.Scheme, baseUri.Host, port).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, done.

@jskeet
Copy link
Collaborator

jskeet commented Mar 6, 2024

Also, take a look at the Firestore change, or let me know if you'd prefer me to bring that out to another PR. According to googleapis/conformance-tests#84 you were fine with this, and it's simple enough though.

Yes, I'm fine doing that in this PR.

Copy link
Contributor Author

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

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

All comments addressed. I've squahsed in meaningful comments and will merge on green. Thanks!

@@ -65,8 +65,7 @@ public sealed class Options
/// <summary>
/// The Scheme to use for the request. Only http or https supported.
/// This will never be null. If null is specified in <see cref="WithScheme(string)"/>
/// then https will be used.
/// Defaults to https.
/// an appropiate default value will be used.
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

@@ -79,7 +78,7 @@ public sealed class Options
/// <summary>
/// The host to use for generating the signed URL.
/// This will never be null. If null is specified in <see cref="WithHost(string)"/>
/// then <see cref="DefaultStorageHost"/> will be used.
/// then the appropiate default value will be used.
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

@@ -167,6 +132,29 @@ public UrlSigner UrlSigner
UnauthenticatedAccess = true
}.Build();

/// <summary>
/// Creates a URL signer built base on this client, that is using the same credential as this client, as well
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

@@ -167,6 +132,29 @@ public UrlSigner UrlSigner
UnauthenticatedAccess = true
}.Build();

/// <summary>
/// Creates a URL signer built base on this client, that is using the same credential as this client, as well
/// as defaulting to this client's URI scheme, host and port. If the credential used by this client is not compatible
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Duh, yes.

/// See <see cref="UrlSigner"/>'s documentation for more information on compatible credentials.
/// </summary>
/// <remarks>
/// Because credentials used by this client may changed, this method will always return a new <see cref="UrlSigner"/> instance
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, done

// If the original URI didn't specify a port, we want signed URLs to not have a port either;
// but Uri.Port returns the default port for the URI scheme when the port was not specified on the
// original URI.
baseUri.IsDefaultPort && !Service.BaseUri.Contains(baseUri.Port.ToString()) ? null : baseUri.Port));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, done.

@amanda-tarafa amanda-tarafa merged commit 4f0d708 into googleapis:main Mar 6, 2024
10 checks passed
@amanda-tarafa amanda-tarafa deleted the storage-url-signer branch March 6, 2024 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

storage: Support custom endpoints for SignURLs
2 participants