Skip to content

Commit 57d1697

Browse files
committed
feat: adjust to MethodNameFormatter concept
1 parent fe5d436 commit 57d1697

File tree

8 files changed

+97
-70
lines changed

8 files changed

+97
-70
lines changed

README.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,24 @@ if err := client.Call(); err != nil {
246246

247247
## Options
248248

249-
### Using `WithMethodNameFormatter`
249+
### Using `WithServerMethodNameFormatter`
250+
251+
`WithServerMethodNameFormatter` allows you to customize a function that formats the JSON-RPC method name, given namespace and method name.
252+
253+
There are three predefined formatters:
254+
- `jsonrpc.DefaultMethodNameFormatter` - default method name formatter, e.g. `SimpleServerHandler.AddGet`
255+
- `jsonrpc.NoNamespaceMethodNameFormatter` - method name formatter without namespace, e.g. `AddGet`
256+
- `jsonrpc.NoNamespaceDecapitalizedMethodNameFormatter` - method name formatter without namespace and decapitalized, e.g. `addGet`
257+
258+
> [!NOTE]
259+
> The default method name formatter concatenates the namespace and method name with a dot.
260+
> Go exported methods are capitalized, so, the method name will be capitalized as well.
261+
> e.g. `SimpleServerHandler.AddGet` (capital "A" in "AddGet")
250262
251263
```go
252264
func main() {
253265
// create a new server instance with a custom separator
254-
rpcServer := jsonrpc.NewServer(jsonrpc.WithMethodNameFormatter(
266+
rpcServer := jsonrpc.NewServer(jsonrpc.WithServerMethodNameFormatter(
255267
func(namespace, method string) string {
256268
return namespace + "_" + method
257269
}),
@@ -273,11 +285,28 @@ func main() {
273285
}
274286
```
275287

288+
### Using `WithMethodNameFormatter`
289+
290+
`WithMethodNameFormatter` is the client-side counterpart to `WithServerMethodNameFormatter`.
291+
292+
```go
293+
func main() {
294+
closer, err := NewMergeClient(
295+
context.Background(),
296+
"http://example.com",
297+
"SimpleServerHandler",
298+
[]any{&client},
299+
nil,
300+
WithMethodNameFormatter(test.namer),
301+
)
302+
defer closer()
303+
}
304+
```
276305

277306
## Contribute
278307

279308
PRs are welcome!
280309

281310
## License
282311

283-
Dual-licensed under [MIT](https://github.com/filecoin-project/go-jsonrpc/blob/master/LICENSE-MIT) + [Apache 2.0](https://github.com/filecoin-project/go-jsonrpc/blob/master/LICENSE-APACHE)
312+
Dual-licensed under [MIT](https://github.com/filecoin-project/go-jsonrpc/blob/master/LICENSE-MIT) + [Apache 2.0](https://github.com/filecoin-project/go-jsonrpc/blob/master/LICENSE-APACHE)

client.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,14 @@ func NewClient(ctx context.Context, addr string, namespace string, handler inter
9898

9999
type client struct {
100100
namespace string
101-
methodNamer MethodNamer
102101
paramEncoders map[reflect.Type]ParamEncoder
103102
errors *Errors
104103

105104
doRequest func(context.Context, clientRequest) (clientResponse, error)
106105
exiting <-chan struct{}
107106
idCtr int64
107+
108+
methodNameFormatter MethodNameFormatter
108109
}
109110

110111
// NewMergeClient is like NewClient, but allows to specify multiple structs
@@ -139,10 +140,10 @@ func NewCustomClient(namespace string, outs []interface{}, doRequest func(ctx co
139140
}
140141

141142
c := client{
142-
namespace: namespace,
143-
methodNamer: config.methodNamer,
144-
paramEncoders: config.paramEncoders,
145-
errors: config.errors,
143+
namespace: namespace,
144+
methodNameFormatter: config.methodNamer,
145+
paramEncoders: config.paramEncoders,
146+
errors: config.errors,
146147
}
147148

148149
stop := make(chan struct{})
@@ -194,10 +195,10 @@ func NewCustomClient(namespace string, outs []interface{}, doRequest func(ctx co
194195

195196
func httpClient(ctx context.Context, addr string, namespace string, outs []interface{}, requestHeader http.Header, config Config) (ClientCloser, error) {
196197
c := client{
197-
namespace: namespace,
198-
methodNamer: config.methodNamer,
199-
paramEncoders: config.paramEncoders,
200-
errors: config.errors,
198+
namespace: namespace,
199+
methodNameFormatter: config.methodNamer,
200+
paramEncoders: config.paramEncoders,
201+
errors: config.errors,
201202
}
202203

203204
stop := make(chan struct{})
@@ -290,10 +291,10 @@ func websocketClient(ctx context.Context, addr string, namespace string, outs []
290291
}
291292

292293
c := client{
293-
namespace: namespace,
294-
methodNamer: config.methodNamer,
295-
paramEncoders: config.paramEncoders,
296-
errors: config.errors,
294+
namespace: namespace,
295+
methodNameFormatter: config.methodNamer,
296+
paramEncoders: config.paramEncoders,
297+
errors: config.errors,
297298
}
298299

299300
requests := c.setupRequestChan()
@@ -714,7 +715,7 @@ func (c *client) makeRpcFunc(f reflect.StructField) (reflect.Value, error) {
714715
return reflect.Value{}, xerrors.New("handler field not a func")
715716
}
716717

717-
name := c.methodNamer(c.namespace, f.Name)
718+
name := c.methodNameFormatter(c.namespace, f.Name)
718719
if tag, ok := f.Tag.Lookup(ProxyTagRPCMethod); ok {
719720
name = tag
720721
}

method_formatter.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package jsonrpc
2+
3+
import "strings"
4+
5+
// MethodNameFormatter is a function that takes a namespace and a method name and returns the full method name, sent via JSON-RPC.
6+
// This is useful if you want to customize the default behaviour, e.g. send without the namespace or make it lowercase.
7+
type MethodNameFormatter func(namespace, method string) string
8+
9+
// DefaultMethodNameFormatter joins the namespace and method name with a dot.
10+
func DefaultMethodNameFormatter(namespace, method string) string {
11+
return namespace + "." + method
12+
}
13+
14+
// NoNamespaceMethodNameFormatter returns the method name as is, without the namespace.
15+
func NoNamespaceMethodNameFormatter(_, method string) string {
16+
return method
17+
}
18+
19+
// NoNamespaceDecapitalizedMethodNameFormatter returns the method name as is, without the namespace, and decapitalizes the first letter.
20+
// e.g. "Inc" -> "inc"
21+
func NoNamespaceDecapitalizedMethodNameFormatter(_, method string) string {
22+
if len(method) == 0 {
23+
return ""
24+
}
25+
return strings.ToLower(method[:1]) + method[1:]
26+
}

namer_test.go renamed to method_formatter_test.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,26 @@ import (
1212

1313
func TestDifferentMethodNamers(t *testing.T) {
1414
tests := map[string]struct {
15-
namer MethodNamer
15+
namer MethodNameFormatter
1616

1717
requestedMethod string
1818
}{
1919
"default namer": {
20-
namer: DefaultMethodNamer,
20+
namer: DefaultMethodNameFormatter,
2121
requestedMethod: "SimpleServerHandler.Inc",
2222
},
2323
"no namespace namer": {
24-
namer: NoNamespaceMethodNamer,
24+
namer: NoNamespaceMethodNameFormatter,
2525
requestedMethod: "Inc",
2626
},
2727
"no namespace & decapitalized namer": {
28-
namer: NoNamespaceDecapitalizedMethodNamer,
28+
namer: NoNamespaceDecapitalizedMethodNameFormatter,
2929
requestedMethod: "inc",
3030
},
3131
}
3232
for name, test := range tests {
3333
t.Run(name, func(t *testing.T) {
34-
rpcServer := NewServer(WithServerMethodNamer(test.namer))
34+
rpcServer := NewServer(WithServerMethodNameFormatter(test.namer))
3535

3636
serverHandler := &SimpleServerHandler{}
3737
rpcServer.Register("SimpleServerHandler", serverHandler)
@@ -52,37 +52,37 @@ func TestDifferentMethodNamers(t *testing.T) {
5252

5353
func TestDifferentMethodNamersWithClient(t *testing.T) {
5454
tests := map[string]struct {
55-
namer MethodNamer
55+
namer MethodNameFormatter
5656
urlPrefix string
5757
}{
5858
"default namer & http": {
59-
namer: DefaultMethodNamer,
59+
namer: DefaultMethodNameFormatter,
6060
urlPrefix: "http://",
6161
},
6262
"default namer & ws": {
63-
namer: DefaultMethodNamer,
63+
namer: DefaultMethodNameFormatter,
6464
urlPrefix: "ws://",
6565
},
6666
"no namespace namer & http": {
67-
namer: NoNamespaceMethodNamer,
67+
namer: NoNamespaceMethodNameFormatter,
6868
urlPrefix: "http://",
6969
},
7070
"no namespace namer & ws": {
71-
namer: NoNamespaceMethodNamer,
71+
namer: NoNamespaceMethodNameFormatter,
7272
urlPrefix: "ws://",
7373
},
7474
"no namespace & decapitalized namer & http": {
75-
namer: NoNamespaceDecapitalizedMethodNamer,
75+
namer: NoNamespaceDecapitalizedMethodNameFormatter,
7676
urlPrefix: "http://",
7777
},
7878
"no namespace & decapitalized namer & ws": {
79-
namer: NoNamespaceDecapitalizedMethodNamer,
79+
namer: NoNamespaceDecapitalizedMethodNameFormatter,
8080
urlPrefix: "ws://",
8181
},
8282
}
8383
for name, test := range tests {
8484
t.Run(name, func(t *testing.T) {
85-
rpcServer := NewServer(WithServerMethodNamer(test.namer))
85+
rpcServer := NewServer(WithServerMethodNameFormatter(test.namer))
8686

8787
serverHandler := &SimpleServerHandler{}
8888
rpcServer.Register("SimpleServerHandler", serverHandler)
@@ -101,7 +101,7 @@ func TestDifferentMethodNamersWithClient(t *testing.T) {
101101
[]any{&client},
102102
nil,
103103
WithHTTPClient(testServ.Client()),
104-
WithMethodNamer(test.namer),
104+
WithMethodNameFormatter(test.namer),
105105
)
106106
require.NoError(t, err)
107107
defer closer()

namer.go

Lines changed: 0 additions & 25 deletions
This file was deleted.

options.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type Config struct {
3131
noReconnect bool
3232
proxyConnFactory func(func() (*websocket.Conn, error)) func() (*websocket.Conn, error) // for testing
3333

34-
methodNamer MethodNamer
34+
methodNamer MethodNameFormatter
3535
}
3636

3737
func defaultConfig() Config {
@@ -49,7 +49,7 @@ func defaultConfig() Config {
4949

5050
httpClient: _defaultHTTPClient,
5151

52-
methodNamer: DefaultMethodNamer,
52+
methodNamer: DefaultMethodNameFormatter,
5353
}
5454
}
5555

@@ -115,7 +115,7 @@ func WithHTTPClient(h *http.Client) func(c *Config) {
115115
}
116116
}
117117

118-
func WithMethodNamer(namer MethodNamer) func(c *Config) {
118+
func WithMethodNameFormatter(namer MethodNameFormatter) func(c *Config) {
119119
return func(c *Config) {
120120
c.methodNamer = namer
121121
}

options_server.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ type jsonrpcReverseClient struct{ reflect.Type }
1313

1414
type ParamDecoder func(ctx context.Context, json []byte) (reflect.Value, error)
1515

16-
type MethodNameFormatter func(namespace, method string) string
17-
1816
type ServerConfig struct {
1917
maxRequestSize int64
2018
pingInterval time.Duration
@@ -34,10 +32,8 @@ func defaultServerConfig() ServerConfig {
3432
paramDecoders: map[reflect.Type]ParamDecoder{},
3533
maxRequestSize: DEFAULT_MAX_REQUEST_SIZE,
3634

37-
pingInterval: 5 * time.Second,
38-
methodNameFormatter: func(namespace, method string) string {
39-
return namespace + "." + method
40-
},
35+
pingInterval: 5 * time.Second,
36+
methodNameFormatter: DefaultMethodNameFormatter,
4137
}
4238
}
4339

@@ -65,7 +61,7 @@ func WithServerPingInterval(d time.Duration) ServerOption {
6561
}
6662
}
6763

68-
func WithMethodNameFormatter(formatter MethodNameFormatter) ServerOption {
64+
func WithServerMethodNameFormatter(formatter MethodNameFormatter) ServerOption {
6965
return func(c *ServerConfig) {
7066
c.methodNameFormatter = formatter
7167
}
@@ -85,9 +81,9 @@ func WithReverseClient[RP any](namespace string) ServerOption {
8581
return func(c *ServerConfig) {
8682
c.reverseClientBuilder = func(ctx context.Context, conn *wsConn) (context.Context, error) {
8783
cl := client{
88-
namespace: namespace,
89-
methodNamer: c.methodNamer,
90-
paramEncoders: map[reflect.Type]ParamEncoder{},
84+
namespace: namespace,
85+
methodNameFormatter: c.methodNameFormatter,
86+
paramEncoders: map[reflect.Type]ParamEncoder{},
9187
}
9288

9389
// todo test that everything is closing correctly

rpc_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,7 @@ func TestNewCustomClient(t *testing.T) {
17191719
func TestReverseCallWithCustomMethodName(t *testing.T) {
17201720
// setup server
17211721

1722-
rpcServer := NewServer(WithMethodNameFormatter(func(namespace, method string) string { return namespace + "_" + method }))
1722+
rpcServer := NewServer(WithServerMethodNameFormatter(func(namespace, method string) string { return namespace + "_" + method }))
17231723
rpcServer.Register("Server", &RawParamHandler{})
17241724

17251725
// httptest stuff

0 commit comments

Comments
 (0)