Skip to content

Conversation

@chris-4chain
Copy link
Contributor

@chris-4chain chris-4chain commented Mar 17, 2025

I'm proposing a MethodNamer custom configuration option (for both client & server) to make it configurable what string is sent as method field in JSON-RPC.

Definition:

// MethodNamer is a function that takes a namespace and a method name and returns the full method name, sent via JSON-RPC.
// This is useful if you want to customize the default behaviour, e.g. send without the namespace or make it lowercase.
type MethodNamer func(string, string) string

Example:

// given a server:
rpcServer := jsonrpc.NewServer(jsonrpc.WithServerMethodNamer(jsonrpc.NoNamespaceMethodNamer))
serverHandler := &SimpleServerHandler{}
rpcServer.Register("SimpleServerHandler", serverHandler)

testServ := httptest.NewServer(rpcServer)
defer testServ.Close()

// and a client:
var client struct {
    AddGet func(int) int
}
closer, _:= jsonrpc.NewMergeClient(
	context.Background(),
	"http://"+testServ.Listener.Addr().String(),
	"SimpleServerHandler",
	[]any{&client},
	nil,
	jsonrpc.WithMethodNamer(jsonrpc.NoNamespaceMethodNamer),
)
defer closer()

// when:
n := client.AddGet(123)

// then:
// an RPC request should be sent with "AddGet" as "method" (without namespace)
// n should == 123 

It solves issues: Add support for lowercase methods and Add support for no namespace

  • I've provided most common (I guess) namers:
    • NoNamespaceMethodNamer - returns the method name as is, without the namespace.
    • NoNamespaceDecapitalizedMethodNamer - returns the method name as is, without the namespace, and decapitalizes the first letter.
  • I've added additional tests.
  • All tests pass (locally, 64bit computer)

@chris-4chain
Copy link
Contributor Author

chris-4chain commented Mar 17, 2025

On 32 bit machine, I can see that the tests fail, but, I suppose, it is not related to my changes 🤔

@BigLep BigLep requested a review from rvagg March 18, 2025 02:21
@BigLep
Copy link
Member

BigLep commented Mar 18, 2025

Thanks @chris-4chain for your contribution.

I'll let @rvagg chime in on next steps or assign another reviewer.

@BigLep BigLep added this to FilOz Mar 18, 2025
@github-project-automation github-project-automation bot moved this to 📌 Triage in FilOz Mar 18, 2025
@BigLep BigLep moved this from 📌 Triage to 🔎 Awaiting Review in FilOz Mar 18, 2025
@Stebalien
Copy link
Member

Gah. Sorry, I saw and merged #131 first, suggesting your exact design. However, that PR doesn't implement the client side. Mind rebasing your PR?

@Stebalien Stebalien mentioned this pull request Mar 21, 2025
@chris-4chain
Copy link
Contributor Author

chris-4chain commented Mar 24, 2025

@Stebalien No worries 👍 I'm glad to see this feature moving forward, regardless of who creates the PR 🙈

  • I've adjusted my code and added the client-side (MethodNameFormatter)
  • I've also adjusted the name "MethodNamer" (proposed by me) to the one, already merged ("MethodNameFormatter")
  • I've changed the option function for server from WithMethodNameFormatter to WithServerMethodNameFormatter (for consistency reasons). The WithMethodNameFormatter is now for the client side.
  • The issue with 32 bit is resolved - I've changed an order of fields in the client struct - it helped 🤞

README.md Outdated
There are three predefined formatters:
- `jsonrpc.DefaultMethodNameFormatter` - default method name formatter, e.g. `SimpleServerHandler.AddGet`
- `jsonrpc.NoNamespaceMethodNameFormatter` - method name formatter without namespace, e.g. `AddGet`
- `jsonrpc.NoNamespaceDecapitalizedMethodNameFormatter` - method name formatter without namespace and decapitalized, e.g. `addGet`
Copy link
Member

Choose a reason for hiding this comment

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

I don't love this name, but NoNamespaceLowerCamelCaseMethodNameFormatter would be getting a bit out of hand I think

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've adjusted it according to your idea with NewMethodNameFormatter

client.go Outdated
Comment on lines 144 to 146
methodNameFormatter: config.methodNamer,
paramEncoders: config.paramEncoders,
errors: config.errors,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
methodNameFormatter: config.methodNamer,
paramEncoders: config.paramEncoders,
errors: config.errors,
paramEncoders: config.paramEncoders,
errors: config.errors,
methodNameFormatter: config.methodNamer,

retain ordering of the fields as defined

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

client.go Outdated
paramEncoders: config.paramEncoders,
errors: config.errors,
namespace: namespace,
methodNameFormatter: config.methodNamer,
Copy link
Member

Choose a reason for hiding this comment

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

ditto here

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

client.go Outdated
paramEncoders: config.paramEncoders,
errors: config.errors,
namespace: namespace,
methodNameFormatter: config.methodNamer,
Copy link
Member

Choose a reason for hiding this comment

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

ditto

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

Comment on lines 9 to 26
// DefaultMethodNameFormatter joins the namespace and method name with a dot.
func DefaultMethodNameFormatter(namespace, method string) string {
return namespace + "." + method
}

// NoNamespaceMethodNameFormatter returns the method name as is, without the namespace.
func NoNamespaceMethodNameFormatter(_, method string) string {
return method
}

// NoNamespaceDecapitalizedMethodNameFormatter returns the method name as is, without the namespace, and decapitalizes the first letter.
// e.g. "Inc" -> "inc"
func NoNamespaceDecapitalizedMethodNameFormatter(_, method string) string {
if len(method) == 0 {
return ""
}
return strings.ToLower(method[:1]) + method[1:]
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// DefaultMethodNameFormatter joins the namespace and method name with a dot.
func DefaultMethodNameFormatter(namespace, method string) string {
return namespace + "." + method
}
// NoNamespaceMethodNameFormatter returns the method name as is, without the namespace.
func NoNamespaceMethodNameFormatter(_, method string) string {
return method
}
// NoNamespaceDecapitalizedMethodNameFormatter returns the method name as is, without the namespace, and decapitalizes the first letter.
// e.g. "Inc" -> "inc"
func NoNamespaceDecapitalizedMethodNameFormatter(_, method string) string {
if len(method) == 0 {
return ""
}
return strings.ToLower(method[:1]) + method[1:]
}
// CaseStyle represents the case style for method names.
type CaseStyle int
const (
OriginalCase CaseStyle = iota
LowerFirstCharCase
)
// NewMethodNameFormatter creates a new method name formatter based on the provided options.
func NewMethodNameFormatter(includeNamespace bool, nameCase CaseStyle) MethodNameFormatter {
return func(namespace, method string) string {
formattedMethod := method
if nameCase == LowerFirstCharCase && len(method) > 0 {
formattedMethod = strings.ToLower(method[:1]) + method[1:]
}
if includeNamespace {
return namespace + "." + formattedMethod
}
return formattedMethod
}
}
// DefaultMethodNameFormatter is a pass-through formatter with default options.
var DefaultMethodNameFormatter = NewMethodNameFormatter(true, OriginalCase)

How about something like this to solve the weird naming problem?

Copy link
Contributor Author

@chris-4chain chris-4chain Apr 1, 2025

Choose a reason for hiding this comment

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

Good idea 💯

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

@chris-4chain chris-4chain requested a review from rvagg April 1, 2025 07:43
Copy link
Member

@rvagg rvagg left a comment

Choose a reason for hiding this comment

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

great, thanks! sorry it's taken so long on our end

@github-project-automation github-project-automation bot moved this from 🔎 Awaiting Review to ✔️ Approved by reviewer in FilOz Apr 8, 2025
@rvagg rvagg merged commit e691565 into filecoin-project:master Apr 8, 2025
7 checks passed
@github-project-automation github-project-automation bot moved this from ✔️ Approved by reviewer to 🎉 Done in FilOz Apr 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🎉 Done

Development

Successfully merging this pull request may close these issues.

4 participants