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

Support for passing arbitrary parameters #1057

Merged
merged 1 commit into from
Nov 21, 2017
Merged

Support for passing arbitrary parameters #1057

merged 1 commit into from
Nov 21, 2017

Conversation

ob-stripe
Copy link
Contributor

r? @remi-stripe
cc @stripe/api-libraries

This PR adds support for passing arbitrary parameters when making API requests. If the Options class inherit from StripeParamsBase, users can call AddExtraParam to add arbitrary key/value pairs to the request.

Copy link
Contributor

@remi-stripe remi-stripe left a comment

Choose a reason for hiding this comment

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

added a few comments

foreach (KeyValuePair<string, string> pair in (Dictionary<string, string>) field.GetValue(obj))
{
var key = WebUtility.UrlEncode(pair.Key);
RequestStringBuilder.ApplyParameterToRequestString(ref requestString, key, pair.Value);
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean that you could pass extra_params[sub_params][subsub_value] and it would work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The brackets would be URL-encoded. I think the API doesn't mind and would still interpret the value as a nested object, but not entirely sure tbh. Maybe URL-encoding the key is not the right thing to do here, and instead we'd make it the caller's responsibility to pass a properly URL-encoded key?

Copy link
Contributor

Choose a reason for hiding this comment

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

hmmm that seems frustrating for users to have to do this (url encoding themselves). Maybe not supporting sub-hashes for now is fine then. Also we could do a plugin that says "oh this is a dictionary, let's properly encode those"

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'd rather keep the feature simple for now. If someone actually needs to use this method with nested objects we can think about it then.


namespace Stripe
{
public class StripeParamsBase
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the new name but should it be StripeBaseOptions to match the rest of the class naming?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's probably a better name.

@@ -33,6 +33,16 @@ public static string ApplyAllParameters(this StripeService service, object obj,
RequestStringBuilder.ProcessPlugins(ref requestString, attribute, property, value, obj);
}
}

var field = obj.GetType().GetRuntimeField("ExtraParams");
if (field != null)
Copy link
Contributor

Choose a reason for hiding this comment

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

This was added temporarily right? Should we assert if you option doesn't have that value so that you know you forgot to inherit from StripeParamsBase?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unless that breaks the reflection logic beyond saving, I think a better solution would be to change the ApplyAllParameters signature to receive a StripeParamsBase (or whatever name we choose for the parent class) instead of an object.

But to answer your question, yes, all params classes should inherit from StripeParamsBase and so there's no reason why ExtraParams would not be available.

Copy link
Contributor

Choose a reason for hiding this comment

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

So what I meant is that if we remove the if, then we can catch cases where someone creates a new Options class but forgets to inherit from the Base class.

Copy link
Contributor

Choose a reason for hiding this comment

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

@ob-stripe Now that all class derive from StripeBaseOptions should we remove the check? Or assert if field == null as it should not happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, an assert seems reasonable 👍

@remi-stripe
Copy link
Contributor

remi-stripe commented Nov 16, 2017

@ob-stripe flagging that I just pushed this:

Move all top-level Options classes to StripeBaseOptions

  • Ensure that RequestOptions does not inherit from it as it's used in a different way in the library (extra headers)
  • Same for INestedOptions as it's specific to sub-resources and should not have extra parameters.
  • Ensure StripeBaseOptions does not reference itself!

@@ -10,7 +10,7 @@ namespace Stripe.Infrastructure
{
internal static class ParameterBuilder
{
public static string ApplyAllParameters(this StripeService service, object obj, string url, bool isListMethod = false)
public static string ApplyAllParameters(this StripeService service, StripeBaseOptions obj, string url, bool isListMethod = false)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I actually went with what I mentioned before: the method now expects a StripeBaseOptions instance instead of just an object. That way if we forget to derive from StripeBaseOptions the error will be immediately visible at compile time rather than at runtime. (I actually caught a few classes that you'd forgotten this way ;)

Plus, there's no need to muck with reflection to access ExtraParams now, so the code is a bit cleaner.

@ob-stripe
Copy link
Contributor Author

ptal @remi-stripe

ExtraParams.Add(key, value);
}

public Dictionary<string, string> ExtraParams = new Dictionary<string, string>();
Copy link
Contributor

Choose a reason for hiding this comment

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

@ob-stripe did we want to figure out how to make that one not public before merging?

Copy link
Contributor

@remi-stripe remi-stripe left a comment

Choose a reason for hiding this comment

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

LGTM

@ob-stripe ob-stripe merged commit 20ce1d1 into master Nov 21, 2017
@ob-stripe ob-stripe deleted the ob-add-extra branch November 21, 2017 17:15
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.

2 participants