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

[proc_macro] Support named RPC parameters with naming conventions #920

Closed
2 tasks
Tracked by #857
lexnv opened this issue Oct 27, 2022 · 4 comments · Fixed by #921
Closed
2 tasks
Tracked by #857

[proc_macro] Support named RPC parameters with naming conventions #920

lexnv opened this issue Oct 27, 2022 · 4 comments · Fixed by #921

Comments

@lexnv
Copy link
Contributor

lexnv commented Oct 27, 2022

The RPC server can receive the parameters as named, or unnamed.

The spec does not enforce any naming conventions on those parameters:

  • named with snakeCase:
{ "jsonrpc": "2.0", "method": "subtract", "params": {"one_one": 23, "two_two": 42}, "id": 3}
  • name with camelCase:
{ "jsonrpc": "2.0", "method": "subtract", "params": {"oneOne": 23, "twoTwo": 42}, "id": 3}

The current implementation provides a 1-to-1 match, meaning that the definition of the method / subscription
is driving the deserialization of parameters.

The following form accepts only snake case named parameters.

#[method(name = "getString")]
async fn get_string(&self, one_one: String, two_two: String) -> String
  • Document this behavior and keep it as the default
  • Add a new macro attribute to allow deserialization from different naming convention

Suggestion:
The param_convention attribute will be applied to each parameter in order to find
the expected name for deserialization.
Note: This applies only to named parameters.

  • camelCase(one_one) == "oneOne" - the method expects "oneOne" and "twoTwo" parameters
#[method(name = "getString", param_convention="camelCase")]
async fn get_string(&self, one_one: String, two_two: String) -> String

Feature needed for: paritytech/substrate#12544.

@niklasad1
Copy link
Member

niklasad1 commented Oct 27, 2022

To elaborate currently jsonrpsee is using the naming of the variable in the trait and adds it directly as the name of the key of that Object when trying to decode the params.

Thus, it's possible to support snake_case and camelCase but it is poorly documented and a footgun. Then using camelCase in rust is a compile warn.

Ideally, we just try to decode it with the most common naming conventions and if all fails then return InvalidParams.
Perhaps https://serde.rs/field-attrs.html#alias would work quite nicely here

@jsdw
Copy link
Collaborator

jsdw commented Nov 3, 2022

Just wondering; why is this feature needed for paritytech/substrate#12544?

I can see that we'd want to be able to rename methods from their rust function names, because the new spec has a bit of a mashup of snake and camel case, but it feels a little magical to do as https://github.com/paritytech/jsonrpsee/pull/921/files does and just support two different conventions out of the box. Like, I guess I like the more explicit approach of #[alias = "foo"], and perhaps for the substrate stuff we just disable to lint on method names to avoid needing to rename anyway?

@niklasad1
Copy link
Member

niklasad1 commented Nov 3, 2022

#[alias = "foo"]

won't work because one might have arbitrary number of params where the naming convention should apply.

however, we could also have object_param_naming_convention = "<some naming convention>"

Just wondering; why is this feature needed for paritytech/substrate#12544?

I think the spec specifies that the object params should use camelCase.
Thus, if one does this:

#[rpc(client, server, namespace = "foo")]
pub trait Rpc {
     #[method(name = "foo")]
      fn hey(param_one: String) -> String;
}

The param will only accepted by "params": { "param_one": "foo" }

So folks could actually do:

#[rpc(client, server, namespace = "foo")]
pub trait Rpc {
     #[method(name = "foo")]
      fn hey(paramOne: String) -> String;
}

but it will generate a rust compile warning.

I'm just a bit concerned about the complexity of the the configurations of the RPC trait but yeye.

@jsdw
Copy link
Collaborator

jsdw commented Nov 3, 2022

Aah yes it's about param names and not method names!

Hmmm; I guess especially since param names are somewhat optional as it is, I think maybe I'm actually ok with your general solution of accepting either casing. It is a bit magical but then they are already optional, so yeah I'm good, ignore me :)

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 a pull request may close this issue.

3 participants