From da43caa8cd81339a14e7abf791be245769eb60c1 Mon Sep 17 00:00:00 2001 From: a <a@tuxpa.in> Date: Sat, 3 Jun 2023 04:25:06 -0500 Subject: [PATCH] refactor --- contrib/codecs/codecs.go | 7 +++ {pkg/codec => contrib}/codecs/http/client.go | 20 ++++---- .../codecs/http/client_test.go | 7 +-- {pkg/codec => contrib}/codecs/http/codec.go | 6 +-- {pkg/codec => contrib}/codecs/http/const.go | 0 {pkg/codec => contrib}/codecs/http/handler.go | 5 +- .../codecs/http/http_test.go | 6 ++- .../codec => contrib}/codecs/inproc/client.go | 16 +++--- .../codec => contrib}/codecs/inproc/inproc.go | 3 +- .../codecs/inproc/inproc_test.go | 12 ++--- {pkg/codec => contrib}/codecs/ipc/ipc.go | 0 {pkg/codec => contrib}/codecs/ipc/ipc_js.go | 0 {pkg/codec => contrib}/codecs/ipc/ipc_test.go | 0 {pkg/codec => contrib}/codecs/ipc/ipc_unix.go | 0 .../codecs/ipc/ipc_windows.go | 0 .../codecs/stdio/server_test.go | 0 {pkg/codec => contrib}/codecs/stdio/stdio.go | 0 .../codecs/websocket/client.go | 3 +- .../codecs/websocket/client_example_test.go | 0 .../codecs/websocket/codec.go | 0 .../codecs/websocket/const.go | 0 .../codecs/websocket/dial.go | 0 .../codecs/websocket/websocket.go | 6 +-- .../codecs/websocket/websocket_test.go | 37 +++++++------- .../codecs/websocket/wsjson/writer_test.go | 0 .../codecs/websocket/wsjson/wsjson.go | 0 {pkg => contrib}/handlers/argreflect/json.go | 2 +- .../handlers/argreflect/reflect_handler.go | 12 ++--- {pkg => contrib}/jmux/mux.go | 49 +++++++++---------- {pkg => contrib}/jmux/router.go | 20 ++++---- {pkg => contrib}/jmux/router_chain.go | 18 ++++--- {pkg => contrib}/jmux/router_context.go | 5 +- {pkg => contrib}/jmux/router_tree.go | 19 ++++--- contrib/middleware/log.go | 8 +-- contrib/middleware/middleware.go | 10 ++-- contrib/middleware/recoverer.go | 9 ++-- contrib/middleware/request_id.go | 9 ++-- contrib/openrpc/out/example/main.go | 3 +- {pkg => contrib}/subscription/conn.go | 5 +- {pkg => contrib}/subscription/engine.go | 0 {pkg => contrib}/subscription/subscription.go | 0 doc.go | 4 ++ example/echo/main.go | 6 ++- example/proxy/main.go | 6 ++- example/subscription/main.go | 8 +-- exports.go | 48 ++++++++++++++++++ pkg/clientutil/helper.go | 4 +- pkg/codec/codecs/codecs.go | 5 -- helper.go => pkg/codec/helper.go | 9 ++-- jrpc.go => pkg/codec/jrpc.go | 2 +- pkg/codec/json.go | 2 +- request.go => pkg/codec/reqresp.go | 45 ++++++++++++----- pkg/jrpctest/server.go | 17 +++---- pkg/jrpctest/services.go | 12 ++--- pkg/jrpctest/suites.go | 45 ++++++++--------- server.go => pkg/server/server.go | 15 +++--- readme.md | 40 +++++++++------ response.go | 26 ---------- 58 files changed, 323 insertions(+), 268 deletions(-) create mode 100644 contrib/codecs/codecs.go rename {pkg/codec => contrib}/codecs/http/client.go (86%) rename {pkg/codec => contrib}/codecs/http/client_test.go (71%) rename {pkg/codec => contrib}/codecs/http/codec.go (97%) rename {pkg/codec => contrib}/codecs/http/const.go (100%) rename {pkg/codec => contrib}/codecs/http/handler.go (83%) rename {pkg/codec => contrib}/codecs/http/http_test.go (98%) rename {pkg/codec => contrib}/codecs/inproc/client.go (84%) rename {pkg/codec => contrib}/codecs/inproc/inproc.go (99%) rename {pkg/codec => contrib}/codecs/inproc/inproc_test.go (60%) rename {pkg/codec => contrib}/codecs/ipc/ipc.go (100%) rename {pkg/codec => contrib}/codecs/ipc/ipc_js.go (100%) rename {pkg/codec => contrib}/codecs/ipc/ipc_test.go (100%) rename {pkg/codec => contrib}/codecs/ipc/ipc_unix.go (100%) rename {pkg/codec => contrib}/codecs/ipc/ipc_windows.go (100%) rename {pkg/codec => contrib}/codecs/stdio/server_test.go (100%) rename {pkg/codec => contrib}/codecs/stdio/stdio.go (100%) rename {pkg/codec => contrib}/codecs/websocket/client.go (90%) rename {pkg/codec => contrib}/codecs/websocket/client_example_test.go (100%) rename {pkg/codec => contrib}/codecs/websocket/codec.go (100%) rename {pkg/codec => contrib}/codecs/websocket/const.go (100%) rename {pkg/codec => contrib}/codecs/websocket/dial.go (100%) rename {pkg/codec => contrib}/codecs/websocket/websocket.go (95%) rename {pkg/codec => contrib}/codecs/websocket/websocket_test.go (83%) rename {pkg/codec => contrib}/codecs/websocket/wsjson/writer_test.go (100%) rename {pkg/codec => contrib}/codecs/websocket/wsjson/wsjson.go (100%) rename {pkg => contrib}/handlers/argreflect/json.go (96%) rename {pkg => contrib}/handlers/argreflect/reflect_handler.go (92%) rename {pkg => contrib}/jmux/mux.go (89%) rename {pkg => contrib}/jmux/router.go (83%) rename {pkg => contrib}/jmux/router_chain.go (68%) rename {pkg => contrib}/jmux/router_context.go (98%) rename {pkg => contrib}/jmux/router_tree.go (97%) rename {pkg => contrib}/subscription/conn.go (77%) rename {pkg => contrib}/subscription/engine.go (100%) rename {pkg => contrib}/subscription/subscription.go (100%) create mode 100644 exports.go delete mode 100644 pkg/codec/codecs/codecs.go rename helper.go => pkg/codec/helper.go (90%) rename jrpc.go => pkg/codec/jrpc.go (99%) rename request.go => pkg/codec/reqresp.go (72%) rename server.go => pkg/server/server.go (97%) delete mode 100644 response.go diff --git a/contrib/codecs/codecs.go b/contrib/codecs/codecs.go new file mode 100644 index 0000000..f9b42ca --- /dev/null +++ b/contrib/codecs/codecs.go @@ -0,0 +1,7 @@ +package codecs + +import ( + "gfx.cafe/open/jrpc/contrib/codecs/inproc" +) + +var NewInProc = inproc.NewCodec diff --git a/pkg/codec/codecs/http/client.go b/contrib/codecs/http/client.go similarity index 86% rename from pkg/codec/codecs/http/client.go rename to contrib/codecs/http/client.go index c31d568..542879e 100644 --- a/pkg/codec/codecs/http/client.go +++ b/contrib/codecs/http/client.go @@ -6,16 +6,14 @@ import ( "encoding/json" "errors" "fmt" + "gfx.cafe/open/jrpc/pkg/codec" "io" "net/http" "sync/atomic" "time" "gfx.cafe/open/jrpc/pkg/clientutil" - "gfx.cafe/open/jrpc/pkg/codec" "gfx.cafe/util/go/bufpool" - - "gfx.cafe/open/jrpc" ) var ( @@ -32,7 +30,7 @@ const ( subscribeTimeout = 5 * time.Second // overall timeout eth_subscribe, rpc_modules calls ) -var _ jrpc.Conn = (*Client)(nil) +var _ codec.Conn = (*Client)(nil) // Client represents a connection to an RPC server. type Client struct { @@ -57,7 +55,7 @@ func (c *Client) SetHeader(key string, value string) { } func (c *Client) Do(ctx context.Context, result any, method string, params any) error { - req := jrpc.NewRequestInt(ctx, int(c.id.Add(1)), method, params) + req := codec.NewRequestInt(ctx, int(c.id.Add(1)), method, params) resp, err := c.post(req) if err != nil { return err @@ -90,7 +88,7 @@ func (c *Client) Do(ctx context.Context, result any, method string, params any) return nil } -func (c *Client) post(req *jrpc.Request) (*http.Response, error) { +func (c *Client) post(req *codec.Request) (*http.Response, error) { //TODO: use buffer for this buf := bufpool.GetStd() defer bufpool.PutStd(buf) @@ -112,7 +110,7 @@ func (c *Client) post(req *jrpc.Request) (*http.Response, error) { } func (c *Client) Notify(ctx context.Context, method string, params any) error { - req := jrpc.NewNotification(ctx, method, params) + req := codec.NewNotification(ctx, method, params) resp, err := c.post(req) if err != nil { return err @@ -121,16 +119,16 @@ func (c *Client) Notify(ctx context.Context, method string, params any) error { return err } -func (c *Client) BatchCall(ctx context.Context, b ...*jrpc.BatchElem) error { - reqs := make([]*jrpc.Request, len(b)) +func (c *Client) BatchCall(ctx context.Context, b ...*codec.BatchElem) error { + reqs := make([]*codec.Request, len(b)) ids := make([]int, 0, len(b)) for _, v := range b { if v.IsNotification { - reqs = append(reqs, jrpc.NewRequest(ctx, "", v.Method, v.Params)) + reqs = append(reqs, codec.NewRequest(ctx, "", v.Method, v.Params)) } else { id := int(c.id.Add(1)) ids = append(ids, id) - reqs = append(reqs, jrpc.NewRequestInt(ctx, id, v.Method, v.Params)) + reqs = append(reqs, codec.NewRequestInt(ctx, id, v.Method, v.Params)) } } dat, err := json.Marshal(b) diff --git a/pkg/codec/codecs/http/client_test.go b/contrib/codecs/http/client_test.go similarity index 71% rename from pkg/codec/codecs/http/client_test.go rename to contrib/codecs/http/client_test.go index b99934a..822c36c 100644 --- a/pkg/codec/codecs/http/client_test.go +++ b/contrib/codecs/http/client_test.go @@ -1,20 +1,21 @@ package http import ( + "gfx.cafe/open/jrpc/pkg/codec" + "gfx.cafe/open/jrpc/pkg/server" "net/http/httptest" "testing" - "gfx.cafe/open/jrpc" "gfx.cafe/open/jrpc/pkg/jrpctest" "github.com/stretchr/testify/require" ) func TestBasicSuite(t *testing.T) { jrpctest.RunBasicTestSuite(t, jrpctest.BasicTestSuiteArgs{ - ServerMaker: func() (*jrpc.Server, jrpctest.ClientMaker, func()) { + ServerMaker: func() (*server.Server, jrpctest.ClientMaker, func()) { s := jrpctest.NewServer() hsrv := httptest.NewServer(&Server{Server: s}) - return s, func() jrpc.Conn { + return s, func() codec.Conn { conn, err := DialHTTP(hsrv.URL) require.NoError(t, err) return conn diff --git a/pkg/codec/codecs/http/codec.go b/contrib/codecs/http/codec.go similarity index 97% rename from pkg/codec/codecs/http/codec.go rename to contrib/codecs/http/codec.go index 4ebad41..2faf2ba 100644 --- a/pkg/codec/codecs/http/codec.go +++ b/contrib/codecs/http/codec.go @@ -7,13 +7,11 @@ import ( "encoding/json" "errors" "fmt" + "gfx.cafe/open/jrpc/pkg/codec" "io" "mime" "net/http" "net/url" - - "gfx.cafe/open/jrpc" - "gfx.cafe/open/jrpc/pkg/codec" ) type Codec struct { @@ -85,7 +83,7 @@ func (r *Codec) doReadGet() (msgs json.RawMessage, err error) { if id == "" { id = "1" } - req := jrpc.NewRequest(r.ctx, id, method_up, json.RawMessage(param)) + req := codec.NewRequest(r.ctx, id, method_up, json.RawMessage(param)) return req.MarshalJSON() } diff --git a/pkg/codec/codecs/http/const.go b/contrib/codecs/http/const.go similarity index 100% rename from pkg/codec/codecs/http/const.go rename to contrib/codecs/http/const.go diff --git a/pkg/codec/codecs/http/handler.go b/contrib/codecs/http/handler.go similarity index 83% rename from pkg/codec/codecs/http/handler.go rename to contrib/codecs/http/handler.go index c4f74a5..90a4139 100644 --- a/pkg/codec/codecs/http/handler.go +++ b/contrib/codecs/http/handler.go @@ -1,13 +1,12 @@ package http import ( + "gfx.cafe/open/jrpc/pkg/server" "net/http" - - "gfx.cafe/open/jrpc" ) type Server struct { - Server *jrpc.Server + Server *server.Server } func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/codec/codecs/http/http_test.go b/contrib/codecs/http/http_test.go similarity index 98% rename from pkg/codec/codecs/http/http_test.go rename to contrib/codecs/http/http_test.go index 9f8e4b0..91b3d8c 100644 --- a/pkg/codec/codecs/http/http_test.go +++ b/contrib/codecs/http/http_test.go @@ -25,8 +25,10 @@ import ( "time" "gfx.cafe/open/jrpc" + "gfx.cafe/open/jrpc/contrib/jmux" "gfx.cafe/open/jrpc/pkg/codec" - "gfx.cafe/open/jrpc/pkg/jmux" + "gfx.cafe/open/jrpc/pkg/server" + "gfx.cafe/open/jrpc/pkg/jrpctest" ) @@ -88,7 +90,7 @@ func TestHTTPErrorResponseWithValidRequest(t *testing.T) { func confirmHTTPRequestYieldsStatusCode(t *testing.T, method, contentType, body string, expectedStatusCode int) { t.Helper() - s := jrpc.NewServer(jmux.NewMux()) + s := server.NewServer(jmux.NewMux()) defer s.Stop() ts := httptest.NewServer(&Server{Server: s}) defer ts.Close() diff --git a/pkg/codec/codecs/inproc/client.go b/contrib/codecs/inproc/client.go similarity index 84% rename from pkg/codec/codecs/inproc/client.go rename to contrib/codecs/inproc/client.go index 2bdae6f..0d85933 100644 --- a/pkg/codec/codecs/inproc/client.go +++ b/contrib/codecs/inproc/client.go @@ -7,18 +7,16 @@ import ( "gfx.cafe/open/jrpc/pkg/clientutil" "gfx.cafe/open/jrpc/pkg/codec" "sync" - - "gfx.cafe/open/jrpc" ) type Client struct { p *clientutil.IdReply c *Codec - handler jrpc.Handler + handler codec.Handler } -func NewClient(c *Codec, handler jrpc.Handler) *Client { +func NewClient(c *Codec, handler codec.Handler) *Client { cl := &Client{ p: clientutil.NewIdReply(), c: c, @@ -52,7 +50,7 @@ func (c *Client) listen() error { func (c *Client) Do(ctx context.Context, result any, method string, params any) error { id := c.p.NextId() - req := jrpc.NewRequestInt(ctx, id, method, params) + req := codec.NewRequestInt(ctx, id, method, params) fwd, err := json.Marshal(req) if err != nil { return err @@ -71,14 +69,14 @@ func (c *Client) Do(ctx context.Context, result any, method string, params any) return nil } -func (c *Client) BatchCall(ctx context.Context, b ...*jrpc.BatchElem) error { +func (c *Client) BatchCall(ctx context.Context, b ...*codec.BatchElem) error { buf := new(bytes.Buffer) enc := json.NewEncoder(buf) - reqs := make([]*jrpc.Request, 0, len(b)) + reqs := make([]*codec.Request, 0, len(b)) ids := make([]int, 0, len(b)) for _, v := range b { id := c.p.NextId() - req := jrpc.NewRequestInt(ctx, id, v.Method, v.Params) + req := codec.NewRequestInt(ctx, id, v.Method, v.Params) ids = append(ids, id) reqs = append(reqs, req) } @@ -121,7 +119,7 @@ func (c *Client) Close() error { } func (c *Client) Notify(ctx context.Context, method string, params any) error { - req := jrpc.NewRequest(ctx, "", method, params) + req := codec.NewRequest(ctx, "", method, params) fwd, err := json.Marshal(req) if err != nil { return err diff --git a/pkg/codec/codecs/inproc/inproc.go b/contrib/codecs/inproc/inproc.go similarity index 99% rename from pkg/codec/codecs/inproc/inproc.go rename to contrib/codecs/inproc/inproc.go index 53b60de..1d86952 100644 --- a/pkg/codec/codecs/inproc/inproc.go +++ b/contrib/codecs/inproc/inproc.go @@ -4,9 +4,8 @@ import ( "bufio" "context" "encoding/json" - "io" - "gfx.cafe/open/jrpc/pkg/codec" + "io" ) type Codec struct { diff --git a/pkg/codec/codecs/inproc/inproc_test.go b/contrib/codecs/inproc/inproc_test.go similarity index 60% rename from pkg/codec/codecs/inproc/inproc_test.go rename to contrib/codecs/inproc/inproc_test.go index c49ca17..5351566 100644 --- a/pkg/codec/codecs/inproc/inproc_test.go +++ b/contrib/codecs/inproc/inproc_test.go @@ -2,22 +2,22 @@ package inproc_test import ( "context" - "gfx.cafe/open/jrpc/pkg/codec/codecs/inproc" - "gfx.cafe/open/jrpc/pkg/jmux" + inproc2 "gfx.cafe/open/jrpc/contrib/codecs/inproc" + "gfx.cafe/open/jrpc/contrib/jmux" + "gfx.cafe/open/jrpc/pkg/server" "testing" - "gfx.cafe/open/jrpc" "github.com/stretchr/testify/require" ) func TestInprocSetup(t *testing.T) { mux := jmux.NewMux() - srv := jrpc.NewServer(mux) + srv := server.NewServer(mux) ctx := context.Background() - clientCodec := inproc.NewCodec() - client := inproc.NewClient(clientCodec, nil) + clientCodec := inproc2.NewCodec() + client := inproc2.NewClient(clientCodec, nil) go func() { srv.ServeCodec(ctx, clientCodec) }() diff --git a/pkg/codec/codecs/ipc/ipc.go b/contrib/codecs/ipc/ipc.go similarity index 100% rename from pkg/codec/codecs/ipc/ipc.go rename to contrib/codecs/ipc/ipc.go diff --git a/pkg/codec/codecs/ipc/ipc_js.go b/contrib/codecs/ipc/ipc_js.go similarity index 100% rename from pkg/codec/codecs/ipc/ipc_js.go rename to contrib/codecs/ipc/ipc_js.go diff --git a/pkg/codec/codecs/ipc/ipc_test.go b/contrib/codecs/ipc/ipc_test.go similarity index 100% rename from pkg/codec/codecs/ipc/ipc_test.go rename to contrib/codecs/ipc/ipc_test.go diff --git a/pkg/codec/codecs/ipc/ipc_unix.go b/contrib/codecs/ipc/ipc_unix.go similarity index 100% rename from pkg/codec/codecs/ipc/ipc_unix.go rename to contrib/codecs/ipc/ipc_unix.go diff --git a/pkg/codec/codecs/ipc/ipc_windows.go b/contrib/codecs/ipc/ipc_windows.go similarity index 100% rename from pkg/codec/codecs/ipc/ipc_windows.go rename to contrib/codecs/ipc/ipc_windows.go diff --git a/pkg/codec/codecs/stdio/server_test.go b/contrib/codecs/stdio/server_test.go similarity index 100% rename from pkg/codec/codecs/stdio/server_test.go rename to contrib/codecs/stdio/server_test.go diff --git a/pkg/codec/codecs/stdio/stdio.go b/contrib/codecs/stdio/stdio.go similarity index 100% rename from pkg/codec/codecs/stdio/stdio.go rename to contrib/codecs/stdio/stdio.go diff --git a/pkg/codec/codecs/websocket/client.go b/contrib/codecs/websocket/client.go similarity index 90% rename from pkg/codec/codecs/websocket/client.go rename to contrib/codecs/websocket/client.go index 2f16f1d..86b7f35 100644 --- a/pkg/codec/codecs/websocket/client.go +++ b/contrib/codecs/websocket/client.go @@ -2,6 +2,7 @@ package websocket import ( "context" + jrpc2 "gfx.cafe/open/jrpc/pkg/codec" "sync" "gfx.cafe/open/jrpc" @@ -32,7 +33,7 @@ func (c *Client) Do(ctx context.Context, result any, method string, params any) panic("not implemented") // TODO: Implement } -func (c *Client) BatchCall(ctx context.Context, b ...jrpc.BatchElem) error { +func (c *Client) BatchCall(ctx context.Context, b ...jrpc2.BatchElem) error { panic("not implemented") // TODO: Implement } diff --git a/pkg/codec/codecs/websocket/client_example_test.go b/contrib/codecs/websocket/client_example_test.go similarity index 100% rename from pkg/codec/codecs/websocket/client_example_test.go rename to contrib/codecs/websocket/client_example_test.go diff --git a/pkg/codec/codecs/websocket/codec.go b/contrib/codecs/websocket/codec.go similarity index 100% rename from pkg/codec/codecs/websocket/codec.go rename to contrib/codecs/websocket/codec.go diff --git a/pkg/codec/codecs/websocket/const.go b/contrib/codecs/websocket/const.go similarity index 100% rename from pkg/codec/codecs/websocket/const.go rename to contrib/codecs/websocket/const.go diff --git a/pkg/codec/codecs/websocket/dial.go b/contrib/codecs/websocket/dial.go similarity index 100% rename from pkg/codec/codecs/websocket/dial.go rename to contrib/codecs/websocket/dial.go diff --git a/pkg/codec/codecs/websocket/websocket.go b/contrib/codecs/websocket/websocket.go similarity index 95% rename from pkg/codec/codecs/websocket/websocket.go rename to contrib/codecs/websocket/websocket.go index 7ad5c2a..ea2d3ea 100644 --- a/pkg/codec/codecs/websocket/websocket.go +++ b/contrib/codecs/websocket/websocket.go @@ -4,13 +4,13 @@ import ( "context" "encoding/base64" "encoding/json" + "gfx.cafe/open/jrpc/contrib/codecs/websocket/wsjson" codec2 "gfx.cafe/open/jrpc/pkg/codec" - "gfx.cafe/open/jrpc/pkg/codec/codecs/websocket/wsjson" + "gfx.cafe/open/jrpc/pkg/server" "net/http" "net/url" "time" - "gfx.cafe/open/jrpc" "nhooyr.io/websocket" ) @@ -18,7 +18,7 @@ import ( // // allowedOrigins should be a comma-separated list of allowed origin URLs. // To allow connections with any origin, pass "*". -func WebsocketHandler(s *jrpc.Server, allowedOrigins []string) http.Handler { +func WebsocketHandler(s *server.Server, allowedOrigins []string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { conn, err := websocket.Accept(w, r, &websocket.AcceptOptions{ OriginPatterns: allowedOrigins, diff --git a/pkg/codec/codecs/websocket/websocket_test.go b/contrib/codecs/websocket/websocket_test.go similarity index 83% rename from pkg/codec/codecs/websocket/websocket_test.go rename to contrib/codecs/websocket/websocket_test.go index 2aec7d1..0009913 100644 --- a/pkg/codec/codecs/websocket/websocket_test.go +++ b/contrib/codecs/websocket/websocket_test.go @@ -3,21 +3,20 @@ package websocket_test import ( "context" "errors" + websocket2 "gfx.cafe/open/jrpc/contrib/codecs/websocket" + "gfx.cafe/open/jrpc/contrib/jmux" "gfx.cafe/open/jrpc/pkg/codec" - "gfx.cafe/open/jrpc/pkg/codec/codecs/websocket" - "gfx.cafe/open/jrpc/pkg/jmux" jrpctest2 "gfx.cafe/open/jrpc/pkg/jrpctest" + "gfx.cafe/open/jrpc/pkg/server" "net/http/httptest" "strings" "testing" - - "gfx.cafe/open/jrpc" ) func TestWebsocketClientHeaders(t *testing.T) { t.Parallel() - endpoint, header, err := websocket.WsClientHeaders("wss://testuser:test-PASS_01@example.com:1234", "https://example.com") + endpoint, header, err := websocket2.WsClientHeaders("wss://testuser:test-PASS_01@example.com:1234", "https://example.com") if err != nil { t.Fatalf("wsGetConfig failed: %s", err) } @@ -38,24 +37,24 @@ func TestWebsocketOriginCheck(t *testing.T) { var ( srv = jrpctest2.NewTestServer() - httpsrv = httptest.NewServer(websocket.WebsocketHandler(srv, []string{"http://example.com"})) + httpsrv = httptest.NewServer(websocket2.WebsocketHandler(srv, []string{"http://example.com"})) wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:") ) defer srv.Stop() defer httpsrv.Close() - client, err := websocket.DialWebsocket(context.Background(), wsURL, "http://ekzample.com") + client, err := websocket2.DialWebsocket(context.Background(), wsURL, "http://ekzample.com") if err == nil { client.Close() t.Fatal("no error for wrong origin") } - wantErr := websocket.NewHandshakeError(errors.New("403"), "403 Forbidden") + wantErr := websocket2.NewHandshakeError(errors.New("403"), "403 Forbidden") if !strings.Contains(err.Error(), wantErr.Error()) { t.Fatalf("wrong error for wrong origin: got: '%q', want: '%s'", err, wantErr) } // Connections without origin header should work. - client, err = websocket.DialWebsocket(context.Background(), wsURL, "") + client, err = websocket2.DialWebsocket(context.Background(), wsURL, "") if err != nil { t.Fatalf("error for empty origin: %v", err) } @@ -68,13 +67,13 @@ func TestWebsocketLargeCall(t *testing.T) { var ( srv = jrpctest2.NewTestServer() - httpsrv = httptest.NewServer(websocket.WebsocketHandler(srv, []string{"*"})) + httpsrv = httptest.NewServer(websocket2.WebsocketHandler(srv, []string{"*"})) wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:") ) defer srv.Stop() defer httpsrv.Close() - client, err := websocket.DialWebsocket(context.Background(), wsURL, "") + client, err := websocket2.DialWebsocket(context.Background(), wsURL, "") if err != nil { t.Fatalf("can't dial: %v", err) } @@ -82,7 +81,7 @@ func TestWebsocketLargeCall(t *testing.T) { // This call sends slightly less than the limit and should work. var result jrpctest2.EchoResult - arg := strings.Repeat("x", websocket.MaxRequestContentLength-200) + arg := strings.Repeat("x", websocket2.MaxRequestContentLength-200) if err := client.Do(nil, &result, "test_echo", []any{arg, 1}); err != nil { t.Fatalf("valid call didn't work: %v", err) } @@ -91,7 +90,7 @@ func TestWebsocketLargeCall(t *testing.T) { } // This call sends twice the allowed size and shouldn't work. - arg = strings.Repeat("x", websocket.MaxRequestContentLength*2) + arg = strings.Repeat("x", websocket2.MaxRequestContentLength*2) err = client.Do(nil, &result, "test_echo", []any{arg}) if err == nil { t.Fatal("no error for too large call") @@ -101,14 +100,14 @@ func TestWebsocketLargeCall(t *testing.T) { func TestWebsocketPeerInfo(t *testing.T) { var ( s = jrpctest2.NewTestServer() - ts = httptest.NewServer(websocket.WebsocketHandler(s, []string{"origin.example.com"})) + ts = httptest.NewServer(websocket2.WebsocketHandler(s, []string{"origin.example.com"})) tsurl = "ws:" + strings.TrimPrefix(ts.URL, "http:") ) defer s.Stop() defer ts.Close() ctx := context.Background() - c, err := websocket.DialWebsocket(ctx, tsurl, "http://origin.example.com") + c, err := websocket2.DialWebsocket(ctx, tsurl, "http://origin.example.com") if err != nil { t.Fatal(err) } @@ -137,17 +136,17 @@ func TestWebsocketPeerInfo(t *testing.T) { func TestClientWebsocketLargeMessage(t *testing.T) { mux := jmux.NewMux() var ( - srv = jrpc.NewServer(mux) - httpsrv = httptest.NewServer(websocket.WebsocketHandler(srv, nil)) + srv = server.NewServer(mux) + httpsrv = httptest.NewServer(websocket2.WebsocketHandler(srv, nil)) wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:") ) defer srv.Stop() defer httpsrv.Close() - respLength := websocket.WsMessageSizeLimit - 50 + respLength := websocket2.WsMessageSizeLimit - 50 mux.RegisterStruct("test", jrpctest2.LargeRespService{Length: respLength}) - c, err := websocket.DialWebsocket(context.Background(), wsURL, "") + c, err := websocket2.DialWebsocket(context.Background(), wsURL, "") if err != nil { t.Fatal(err) } diff --git a/pkg/codec/codecs/websocket/wsjson/writer_test.go b/contrib/codecs/websocket/wsjson/writer_test.go similarity index 100% rename from pkg/codec/codecs/websocket/wsjson/writer_test.go rename to contrib/codecs/websocket/wsjson/writer_test.go diff --git a/pkg/codec/codecs/websocket/wsjson/wsjson.go b/contrib/codecs/websocket/wsjson/wsjson.go similarity index 100% rename from pkg/codec/codecs/websocket/wsjson/wsjson.go rename to contrib/codecs/websocket/wsjson/wsjson.go diff --git a/pkg/handlers/argreflect/json.go b/contrib/handlers/argreflect/json.go similarity index 96% rename from pkg/handlers/argreflect/json.go rename to contrib/handlers/argreflect/json.go index 1e9dc3d..a46fe42 100644 --- a/pkg/handlers/argreflect/json.go +++ b/contrib/handlers/argreflect/json.go @@ -4,7 +4,7 @@ import ( "encoding/json" "errors" "fmt" - "gfx.cafe/open/jrpc/pkg/codec/codecs/websocket/wsjson" + "gfx.cafe/open/jrpc/contrib/codecs/websocket/wsjson" "reflect" ) diff --git a/pkg/handlers/argreflect/reflect_handler.go b/contrib/handlers/argreflect/reflect_handler.go similarity index 92% rename from pkg/handlers/argreflect/reflect_handler.go rename to contrib/handlers/argreflect/reflect_handler.go index e4457e5..55e4dc5 100644 --- a/pkg/handlers/argreflect/reflect_handler.go +++ b/contrib/handlers/argreflect/reflect_handler.go @@ -7,8 +7,6 @@ import ( "reflect" "runtime" "unicode" - - "gfx.cafe/open/jrpc" ) var ( @@ -16,16 +14,16 @@ var ( errorType = reflect.TypeOf((*error)(nil)).Elem() ) -func SuitableCallbacks(receiver reflect.Value) map[string]jrpc.Handler { +func SuitableCallbacks(receiver reflect.Value) map[string]codec.Handler { return suitableCallbacks(receiver) } // suitableCallbacks iterates over the methods of the given type. It determines if a method // satisfies the criteria for a RPC callback or a subscription callback and adds it to the // collection of callbacks. See server documentation for a summary of these criteria. -func suitableCallbacks(receiver reflect.Value) map[string]jrpc.Handler { +func suitableCallbacks(receiver reflect.Value) map[string]codec.Handler { typ := receiver.Type() - callbacks := make(map[string]jrpc.Handler) + callbacks := make(map[string]codec.Handler) for m := 0; m < typ.NumMethod(); m++ { method := typ.Method(m) if method.PkgPath != "" { @@ -51,7 +49,7 @@ type callback struct { } // callback handler implements handler for the original receiver style that geth used -func (e *callback) ServeRPC(w jrpc.ResponseWriter, r *jrpc.Request) { +func (e *callback) ServeRPC(w codec.ResponseWriter, r *codec.Request) { argTypes := append([]reflect.Type{}, e.argTypes...) args, err := parsePositionalArguments(r.Params, argTypes) if err != nil { @@ -90,7 +88,7 @@ func (e *callback) ServeRPC(w jrpc.ResponseWriter, r *jrpc.Request) { w.Send(results[0].Interface(), nil) } -func NewCallback(receiver, fn reflect.Value) jrpc.Handler { +func NewCallback(receiver, fn reflect.Value) codec.Handler { return newCallback(receiver, fn) } diff --git a/pkg/jmux/mux.go b/contrib/jmux/mux.go similarity index 89% rename from pkg/jmux/mux.go rename to contrib/jmux/mux.go index 4b20c2c..4f882d2 100644 --- a/pkg/jmux/mux.go +++ b/contrib/jmux/mux.go @@ -4,11 +4,10 @@ import ( "context" "errors" "fmt" - "gfx.cafe/open/jrpc/pkg/handlers/argreflect" + "gfx.cafe/open/jrpc/contrib/handlers/argreflect" + "gfx.cafe/open/jrpc/pkg/codec" "reflect" "sync" - - "gfx.cafe/open/jrpc" ) var _ Router = &Mux{} @@ -24,13 +23,13 @@ var _ Router = &Mux{} type Mux struct { // The computed mux handler made of the chained middleware stack and // the tree router - handler jrpc.Handler + handler codec.Handler // The radix trie router tree *node // Custom method not allowed handler - methodNotAllowedHandler jrpc.HandlerFunc + methodNotAllowedHandler codec.HandlerFunc // A reference to the parent mux used by subrouters when mounting // to a parent mux @@ -40,10 +39,10 @@ type Mux struct { pool *sync.Pool // Custom route not found handler - notFoundHandler jrpc.HandlerFunc + notFoundHandler codec.HandlerFunc // The middleware stack - middlewares []func(jrpc.Handler) jrpc.Handler + middlewares []func(codec.Handler) codec.Handler // Controls the behaviour of middleware chain generation when a mux // is registered as an inline group inside another mux. @@ -92,7 +91,7 @@ func (m *Mux) RegisterFunc(name string, rcvr any) error { // ServeRPC is the single method of the Handler interface that makes // Mux interoperable with the standard library. It uses a sync.Pool to get and // reuse routing contexts for each request. -func (mx *Mux) ServeRPC(w jrpc.ResponseWriter, r *jrpc.Request) { +func (mx *Mux) ServeRPC(w codec.ResponseWriter, r *codec.Request) { // Ensure the mux has some routes defined on the mux if mx.handler == nil { mx.NotFoundHandler().ServeRPC(w, r) @@ -129,7 +128,7 @@ func (mx *Mux) ServeRPC(w jrpc.ResponseWriter, r *jrpc.Request) { // route to a specific handler, which provides opportunity to respond early, // change the course of the request execution, or set request-scoped values for // the next Handler. -func (mx *Mux) Use(middlewares ...func(jrpc.Handler) jrpc.Handler) { +func (mx *Mux) Use(middlewares ...func(codec.Handler) codec.Handler) { if mx.handler != nil { panic("chi: all middlewares must be defined before routes on a mux") } @@ -138,19 +137,19 @@ func (mx *Mux) Use(middlewares ...func(jrpc.Handler) jrpc.Handler) { // Handle adds the route `pattern` that matches any jrpc method to // execute the `handler` Handler. -func (mx *Mux) Handle(pattern string, handler jrpc.Handler) { +func (mx *Mux) Handle(pattern string, handler codec.Handler) { mx.handle(pattern, handler) } // HandleFunc adds the route `pattern` that matches any jrpc method to // execute the `handlerFn` HandlerFunc. -func (mx *Mux) HandleFunc(pattern string, handlerFn jrpc.HandlerFunc) { +func (mx *Mux) HandleFunc(pattern string, handlerFn codec.HandlerFunc) { mx.handle(pattern, handlerFn) } // NotFound sets a custom HandlerFunc for routing paths that could // not be found. The default 404 handler is `NotFound`. -func (mx *Mux) NotFound(handlerFn jrpc.HandlerFunc) { +func (mx *Mux) NotFound(handlerFn codec.HandlerFunc) { // Build NotFound handler chain m := mx hFn := handlerFn @@ -170,7 +169,7 @@ func (mx *Mux) NotFound(handlerFn jrpc.HandlerFunc) { // MethodNotAllowed sets a custom HandlerFunc for routing paths where the // method is unresolved. The default handler returns a 405 with an empty body. -func (mx *Mux) MethodNotAllowed(handlerFn jrpc.HandlerFunc) { +func (mx *Mux) MethodNotAllowed(handlerFn codec.HandlerFunc) { // Build MethodNotAllowed handler chain m := mx hFn := handlerFn @@ -189,7 +188,7 @@ func (mx *Mux) MethodNotAllowed(handlerFn jrpc.HandlerFunc) { } // With adds inline middlewares for an endpoint handler. -func (mx *Mux) With(middlewares ...func(jrpc.Handler) jrpc.Handler) Router { +func (mx *Mux) With(middlewares ...func(codec.Handler) codec.Handler) Router { // Similarly as in handle(), we must build the mux handler once additional // middleware registration isn't allowed for this stack, like now. if !mx.inline && mx.handler == nil { @@ -242,7 +241,7 @@ func (mx *Mux) Route(pattern string, fn func(r Router)) Router { // Note that Mount() simply sets a wildcard along the `pattern` that will continue // routing at the `handler`, which in most cases is another chi.Router. As a result, // if you define two Mount() routes on the exact same pattern the mount will panic. -func (mx *Mux) Mount(pattern string, handler jrpc.Handler) { +func (mx *Mux) Mount(pattern string, handler codec.Handler) { if handler == nil { panic(fmt.Sprintf("chi: attempting to Mount() a nil handler on '%s'", pattern)) } @@ -262,7 +261,7 @@ func (mx *Mux) Mount(pattern string, handler jrpc.Handler) { subr.MethodNotAllowed(mx.methodNotAllowedHandler) } - mountHandler := jrpc.HandlerFunc(func(w jrpc.ResponseWriter, r *jrpc.Request) { + mountHandler := codec.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) { rctx := RouteContext(r.Context()) // shift the url path past the previous subrouter @@ -318,7 +317,7 @@ func (mx *Mux) Match(rctx *Context, path string) bool { // NotFoundHandler returns the default Mux 404 responder whenever a route // cannot be found. -func (mx *Mux) NotFoundHandler() jrpc.HandlerFunc { +func (mx *Mux) NotFoundHandler() codec.HandlerFunc { if mx.notFoundHandler != nil { return mx.notFoundHandler } @@ -327,7 +326,7 @@ func (mx *Mux) NotFoundHandler() jrpc.HandlerFunc { // MethodNotAllowedHandler returns the default Mux 405 responder whenever // a method cannot be resolved for a route. -func (mx *Mux) MethodNotAllowedHandler() jrpc.HandlerFunc { +func (mx *Mux) MethodNotAllowedHandler() codec.HandlerFunc { if mx.methodNotAllowedHandler != nil { return mx.methodNotAllowedHandler } @@ -336,7 +335,7 @@ func (mx *Mux) MethodNotAllowedHandler() jrpc.HandlerFunc { // handle registers a Handler in the routing tree for a particular jrpc method // and routing pattern. -func (mx *Mux) handle(pattern string, handler jrpc.Handler) *node { +func (mx *Mux) handle(pattern string, handler codec.Handler) *node { if len(pattern) == 0 { panic(fmt.Sprintf("rpc: routing pattern must not be empty in '%s'", pattern)) } @@ -347,9 +346,9 @@ func (mx *Mux) handle(pattern string, handler jrpc.Handler) *node { } // Build endpoint handler with inline middlewares for the route - var h jrpc.Handler + var h codec.Handler if mx.inline { - mx.handler = jrpc.HandlerFunc(mx.routeRPC) + mx.handler = codec.HandlerFunc(mx.routeRPC) h = Chain(mx.middlewares...).Handler(handler) } else { h = handler @@ -361,7 +360,7 @@ func (mx *Mux) handle(pattern string, handler jrpc.Handler) *node { // routeJRPC routes a Request through the Mux routing tree to serve // the matching handler for a particular jrpc method. -func (mx *Mux) routeRPC(w jrpc.ResponseWriter, r *jrpc.Request) { +func (mx *Mux) routeRPC(w codec.ResponseWriter, r *codec.Request) { // Grab the route context object rctx := r.Context().Value(RouteCtxKey).(*Context) @@ -413,15 +412,15 @@ func (mx *Mux) updateSubRoutes(fn func(subMux *Mux)) { // point, no other middlewares can be registered on this Mux's stack. But you can still // compose additional middlewares via Group()'s or using a chained middleware handler. func (mx *Mux) updateRouteHandler() { - mx.handler = chain(mx.middlewares, jrpc.HandlerFunc(mx.routeRPC)) + mx.handler = chain(mx.middlewares, codec.HandlerFunc(mx.routeRPC)) } // methodNotAllowedHandler is a helper function to respond with a 405, // method not allowed. -func methodNotAllowedHandler(w jrpc.ResponseWriter, r *jrpc.Request) { +func methodNotAllowedHandler(w codec.ResponseWriter, r *codec.Request) { w.Send(nil, errors.New("forbidden")) } -func NotFound(w jrpc.ResponseWriter, r *jrpc.Request) { +func NotFound(w codec.ResponseWriter, r *codec.Request) { w.Send(nil, errors.New("not found")) } diff --git a/pkg/jmux/router.go b/contrib/jmux/router.go similarity index 83% rename from pkg/jmux/router.go rename to contrib/jmux/router.go index 3ad7a78..b1c0845 100644 --- a/pkg/jmux/router.go +++ b/contrib/jmux/router.go @@ -1,6 +1,8 @@ package jmux -import "gfx.cafe/open/jrpc" +import ( + "gfx.cafe/open/jrpc/pkg/codec" +) // NewRouter returns a new Mux object that implements the Router interface. func NewRouter() *Mux { @@ -19,15 +21,15 @@ type StructReflector interface { // Router consisting of the core routing methods used by chi's Mux, // adapted to fit json-rpc. type Router interface { - jrpc.Handler + codec.Handler Routes StructReflector // Use appends one or more middlewares onto the Router stack. - Use(middlewares ...func(jrpc.Handler) jrpc.Handler) + Use(middlewares ...func(codec.Handler) codec.Handler) // With adds inline middlewares for an endpoint handler. - With(middlewares ...func(jrpc.Handler) jrpc.Handler) Router + With(middlewares ...func(codec.Handler) codec.Handler) Router // Group adds a new inline-Router along the current routing // path, with a fresh middleware stack for the inline-Router. @@ -37,16 +39,16 @@ type Router interface { Route(pattern string, fn func(r Router)) Router // Mount attaches another Handler along ./pattern/* - Mount(pattern string, h jrpc.Handler) + Mount(pattern string, h codec.Handler) // Handle and HandleFunc adds routes for `pattern` that matches // all HTTP methods. - Handle(pattern string, h jrpc.Handler) - HandleFunc(pattern string, h jrpc.HandlerFunc) + Handle(pattern string, h codec.Handler) + HandleFunc(pattern string, h codec.HandlerFunc) // NotFound defines a handler to respond whenever a route could // not be found. - NotFound(h jrpc.HandlerFunc) + NotFound(h codec.HandlerFunc) } // Routes interface adds two methods for router traversal, which is also @@ -66,4 +68,4 @@ type Routes interface { // Middlewares type is a slice of standard middleware handlers with methods // to compose middleware chains and Handler's. -type Middlewares []func(jrpc.Handler) jrpc.Handler +type Middlewares []func(codec.Handler) codec.Handler diff --git a/pkg/jmux/router_chain.go b/contrib/jmux/router_chain.go similarity index 68% rename from pkg/jmux/router_chain.go rename to contrib/jmux/router_chain.go index 0eb1d3b..f44f20c 100644 --- a/pkg/jmux/router_chain.go +++ b/contrib/jmux/router_chain.go @@ -1,39 +1,41 @@ package jmux -import "gfx.cafe/open/jrpc" +import ( + "gfx.cafe/open/jrpc/pkg/codec" +) // Chain returns a Middlewares type from a slice of middleware handlers. -func Chain(middlewares ...func(jrpc.Handler) jrpc.Handler) Middlewares { +func Chain(middlewares ...func(codec.Handler) codec.Handler) Middlewares { return Middlewares(middlewares) } // Handler builds and returns a Handler from the chain of middlewares, // with `h Handler` as the final handler. -func (mws Middlewares) Handler(h jrpc.Handler) jrpc.Handler { +func (mws Middlewares) Handler(h codec.Handler) codec.Handler { return &ChainHandler{h, chain(mws, h), mws} } // HandlerFunc builds and returns a Handler from the chain of middlewares, // with `h Handler` as the final handler. -func (mws Middlewares) HandlerFunc(h jrpc.HandlerFunc) jrpc.Handler { +func (mws Middlewares) HandlerFunc(h codec.HandlerFunc) codec.Handler { return &ChainHandler{h, chain(mws, h), mws} } // ChainHandler is a Handler with support for handler composition and // execution. type ChainHandler struct { - Endpoint jrpc.Handler - chain jrpc.Handler + Endpoint codec.Handler + chain codec.Handler Middlewares Middlewares } -func (c *ChainHandler) ServeRPC(w jrpc.ResponseWriter, r *jrpc.Request) { +func (c *ChainHandler) ServeRPC(w codec.ResponseWriter, r *codec.Request) { c.chain.ServeRPC(w, r) } // chain builds a Handler composed of an inline middleware stack and endpoint // handler in the order they are passed. -func chain(middlewares []func(jrpc.Handler) jrpc.Handler, endpoint jrpc.Handler) jrpc.Handler { +func chain(middlewares []func(codec.Handler) codec.Handler, endpoint codec.Handler) codec.Handler { // Return ahead of time if there aren't any middlewares for the chain if len(middlewares) == 0 { return endpoint diff --git a/pkg/jmux/router_context.go b/contrib/jmux/router_context.go similarity index 98% rename from pkg/jmux/router_context.go rename to contrib/jmux/router_context.go index 828332b..7b851fd 100644 --- a/pkg/jmux/router_context.go +++ b/contrib/jmux/router_context.go @@ -2,13 +2,12 @@ package jmux import ( "context" + "gfx.cafe/open/jrpc/pkg/codec" "strings" - - "gfx.cafe/open/jrpc" ) // MethodParam returns the url parameter from a Request object. -func MethodParam(r *jrpc.Request, key string) string { +func MethodParam(r *codec.Request, key string) string { if rctx := RouteContext(r.Context()); rctx != nil { return rctx.MethodParam(key) } diff --git a/pkg/jmux/router_tree.go b/contrib/jmux/router_tree.go similarity index 97% rename from pkg/jmux/router_tree.go rename to contrib/jmux/router_tree.go index f5031e4..2b7a2f1 100644 --- a/pkg/jmux/router_tree.go +++ b/contrib/jmux/router_tree.go @@ -5,11 +5,10 @@ package jmux import ( "fmt" + "gfx.cafe/open/jrpc/pkg/codec" "regexp" "sort" "strings" - - "gfx.cafe/open/jrpc" ) type nodeTyp uint8 @@ -50,7 +49,7 @@ type node struct { type endpoint struct { // endpoint handler - handler jrpc.Handler + handler codec.Handler // pattern is the routing pattern for handler nodes pattern string @@ -59,7 +58,7 @@ type endpoint struct { paramKeys []string } -func (n *node) InsertRoute(pattern string, handler jrpc.Handler) *node { +func (n *node) InsertRoute(pattern string, handler codec.Handler) *node { var parent *node search := pattern for { @@ -263,7 +262,7 @@ func (n *node) getEdge(ntyp nodeTyp, label, tail byte, prefix string) *node { return nil } -func (n *node) setEndpoint(handler jrpc.Handler, pattern string) { +func (n *node) setEndpoint(handler codec.Handler, pattern string) { paramKeys := patParamKeys(pattern) n.endpoint = &endpoint{ handler: handler, @@ -272,7 +271,7 @@ func (n *node) setEndpoint(handler jrpc.Handler, pattern string) { } } -func (n *node) FindRoute(rctx *Context, path string) (*node, *endpoint, jrpc.Handler) { +func (n *node) FindRoute(rctx *Context, path string) (*node, *endpoint, codec.Handler) { // Reset the context routing pattern and params rctx.routePattern = "" rctx.routeParams.Keys = rctx.routeParams.Keys[:0] @@ -683,21 +682,21 @@ func (ns nodes) findEdge(label byte) *node { // Route describes the details of a routing handler. type Route struct { SubRoutes Routes - Handler jrpc.Handler + Handler codec.Handler Pattern string } // WalkFunc is the type of the function called for each method and route visited by Walk. -type WalkFunc func(route string, handler jrpc.Handler, middlewares ...func(jrpc.Handler) jrpc.Handler) error +type WalkFunc func(route string, handler codec.Handler, middlewares ...func(codec.Handler) codec.Handler) error // Walk walks any router tree that implements Routes interface. func Walk(r Routes, walkFn WalkFunc) error { return walk(r, walkFn, "") } -func walk(r Routes, walkFn WalkFunc, parentRoute string, parentMw ...func(jrpc.Handler) jrpc.Handler) error { +func walk(r Routes, walkFn WalkFunc, parentRoute string, parentMw ...func(codec.Handler) codec.Handler) error { for _, route := range r.Routes() { - mws := make([]func(jrpc.Handler) jrpc.Handler, len(parentMw)) + mws := make([]func(codec.Handler) codec.Handler, len(parentMw)) copy(mws, parentMw) mws = append(mws, r.Middlewares()...) diff --git a/contrib/middleware/log.go b/contrib/middleware/log.go index efd1e41..bd3fb8b 100644 --- a/contrib/middleware/log.go +++ b/contrib/middleware/log.go @@ -2,9 +2,9 @@ package middleware import ( "context" + "gfx.cafe/open/jrpc/pkg/codec" "time" - "gfx.cafe/open/jrpc" "tuxpa.in/a/zlog" "tuxpa.in/a/zlog/log" ) @@ -15,8 +15,8 @@ type ctxKeyLogger int // RequestIDKey is the key that holds the unique request ID in a request context. const LoggerKey ctxKeyLogger = 76 -func Logger(next jrpc.Handler) jrpc.Handler { - fn := func(w jrpc.ResponseWriter, r *jrpc.Request) { +func Logger(next codec.Handler) codec.Handler { + fn := func(w codec.ResponseWriter, r *codec.Request) { start := time.Now() l := log.Trace(). Str("remote", r.Remote()). @@ -29,7 +29,7 @@ func Logger(next jrpc.Handler) jrpc.Handler { l = l.Stringer("dur", time.Since(start)) l.Msg("RPC Request") } - return jrpc.HandlerFunc(fn) + return codec.HandlerFunc(fn) } func GetLogger(ctx context.Context) *zlog.Event { diff --git a/contrib/middleware/middleware.go b/contrib/middleware/middleware.go index 77cf2de..491a05a 100644 --- a/contrib/middleware/middleware.go +++ b/contrib/middleware/middleware.go @@ -1,11 +1,13 @@ package middleware -import "gfx.cafe/open/jrpc" +import ( + "gfx.cafe/open/jrpc/pkg/codec" +) // New will create a new middleware handler from a jrpc.Handler. -func New(h jrpc.Handler) func(next jrpc.Handler) jrpc.Handler { - return func(next jrpc.Handler) jrpc.Handler { - return jrpc.HandlerFunc(func(w jrpc.ResponseWriter, r *jrpc.Request) { +func New(h codec.Handler) func(next codec.Handler) codec.Handler { + return func(next codec.Handler) codec.Handler { + return codec.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) { h.ServeRPC(w, r) }) } diff --git a/contrib/middleware/recoverer.go b/contrib/middleware/recoverer.go index 866daf2..4102247 100644 --- a/contrib/middleware/recoverer.go +++ b/contrib/middleware/recoverer.go @@ -7,12 +7,11 @@ import ( "bytes" "errors" "fmt" + "gfx.cafe/open/jrpc/pkg/codec" "io" "os" "runtime/debug" "strings" - - "gfx.cafe/open/jrpc" ) // Recoverer is a middleware that recovers from panics, logs the panic (and a @@ -20,8 +19,8 @@ import ( // possible. Recoverer prints a request ID if one is provided. // // Alternatively, look at jrpcs://github.com/go-chi/jrpclog middleware pkgs. -func Recoverer(next jrpc.Handler) jrpc.Handler { - fn := func(w jrpc.ResponseWriter, r *jrpc.Request) { +func Recoverer(next codec.Handler) codec.Handler { + fn := func(w codec.ResponseWriter, r *codec.Request) { defer func() { if rvr := recover(); rvr != nil { PrintPrettyStack(rvr) @@ -32,7 +31,7 @@ func Recoverer(next jrpc.Handler) jrpc.Handler { next.ServeRPC(w, r) } - return jrpc.HandlerFunc(fn) + return codec.HandlerFunc(fn) } // for ability to test the PrintPrettyStack function diff --git a/contrib/middleware/request_id.go b/contrib/middleware/request_id.go index 2ed3018..cfed73f 100644 --- a/contrib/middleware/request_id.go +++ b/contrib/middleware/request_id.go @@ -8,11 +8,10 @@ import ( "crypto/rand" "encoding/base64" "fmt" + "gfx.cafe/open/jrpc/pkg/codec" "os" "strings" "sync/atomic" - - "gfx.cafe/open/jrpc" ) // Key to use when setting the request ID. @@ -67,15 +66,15 @@ func init() { // where "random" is a base62 random string that uniquely identifies this go // process, and where the last number is an atomically incremented request // counter. -func RequestID(next jrpc.Handler) jrpc.Handler { - fn := func(w jrpc.ResponseWriter, r *jrpc.Request) { +func RequestID(next codec.Handler) codec.Handler { + fn := func(w codec.ResponseWriter, r *codec.Request) { ctx := r.Context() myid := atomic.AddUint64(&reqid, 1) requestID := fmt.Sprintf("%s-%06d", prefix, myid) ctx = context.WithValue(ctx, RequestIDKey, requestID) next.ServeRPC(w, r.WithContext(ctx)) } - return jrpc.HandlerFunc(fn) + return codec.HandlerFunc(fn) } // GetReqID returns a request ID from the given context if one is present. diff --git a/contrib/openrpc/out/example/main.go b/contrib/openrpc/out/example/main.go index eaf4f72..0647e9d 100644 --- a/contrib/openrpc/out/example/main.go +++ b/contrib/openrpc/out/example/main.go @@ -3,6 +3,7 @@ package main import ( "context" "gfx.cafe/open/jrpc/contrib/openrpc/out" + jrpc2 "gfx.cafe/open/jrpc/pkg/server" "log" "net/http" @@ -16,7 +17,7 @@ func main() { rpc_handler := &out.GoOpenRPCHandler{Srv: handler} rmux := jrpc.NewMux() rpc_handler.RouteRPC(rmux) - srv := jrpc.NewServer(rmux) + srv := jrpc2.NewServer(rmux) log.Println(srv.Router().Routes()) log.Println("listening on port 9545") log.Println(http.ListenAndServe(":9545", srv)) diff --git a/pkg/subscription/conn.go b/contrib/subscription/conn.go similarity index 77% rename from pkg/subscription/conn.go rename to contrib/subscription/conn.go index 3346cdc..3655f25 100644 --- a/pkg/subscription/conn.go +++ b/contrib/subscription/conn.go @@ -2,12 +2,11 @@ package subscription import ( "context" - - "gfx.cafe/open/jrpc" + "gfx.cafe/open/jrpc/pkg/codec" ) type SubscriptionConn interface { - jrpc.StreamingConn + codec.StreamingConn Subscribe(ctx context.Context, namespace string, channel any, args ...any) (*ClientSubscription, error) } diff --git a/pkg/subscription/engine.go b/contrib/subscription/engine.go similarity index 100% rename from pkg/subscription/engine.go rename to contrib/subscription/engine.go diff --git a/pkg/subscription/subscription.go b/contrib/subscription/subscription.go similarity index 100% rename from pkg/subscription/subscription.go rename to contrib/subscription/subscription.go diff --git a/doc.go b/doc.go index 1d2e59d..2e81269 100644 --- a/doc.go +++ b/doc.go @@ -1,4 +1,8 @@ +// Package jrpc implements a jsonrpc2 server /* + + + */ package jrpc diff --git a/example/echo/main.go b/example/echo/main.go index c55c76c..cf6d9aa 100644 --- a/example/echo/main.go +++ b/example/echo/main.go @@ -1,6 +1,8 @@ package main import ( + "gfx.cafe/open/jrpc/pkg/codec" + "gfx.cafe/open/jrpc/pkg/server" "log" "net/http" @@ -10,9 +12,9 @@ import ( func main() { r := jrpc.NewRouter() - srv := jrpc.NewServer(r) + srv := server.NewServer(r) - r.HandleFunc("echo", func(w jrpc.ResponseWriter, r *jrpc.Request) { + r.HandleFunc("echo", func(w codec.ResponseWriter, r *codec.Request) { w.Send(r.Params, nil) }) diff --git a/example/proxy/main.go b/example/proxy/main.go index e241b77..6a2186d 100644 --- a/example/proxy/main.go +++ b/example/proxy/main.go @@ -3,6 +3,8 @@ package main import ( "encoding/json" "gfx.cafe/open/jrpc/contrib/middleware" + "gfx.cafe/open/jrpc/pkg/codec" + "gfx.cafe/open/jrpc/pkg/server" "log" "net/http" @@ -18,7 +20,7 @@ func main() { panic(err) } - r.HandleFunc("eth_*", func(w jrpc.ResponseWriter, r *jrpc.Request) { + r.HandleFunc("eth_*", func(w codec.ResponseWriter, r *codec.Request) { var res json.RawMessage err := c.Call(&res, r.Method(), r.ParamSlice()...) w.Send(res, err) @@ -26,7 +28,7 @@ func main() { log.Println("running on 8855") - srv := jrpc.NewServer(r) + srv := server.NewServer(r) log.Println(http.ListenAndServe(":8855", srv)) } diff --git a/example/subscription/main.go b/example/subscription/main.go index c003a09..4e1db2b 100644 --- a/example/subscription/main.go +++ b/example/subscription/main.go @@ -3,6 +3,8 @@ package main import ( "context" "gfx.cafe/open/jrpc/contrib/middleware" + "gfx.cafe/open/jrpc/pkg/codec" + "gfx.cafe/open/jrpc/pkg/server" "log" "net/http" "time" @@ -14,13 +16,13 @@ func main() { r := jrpc.NewRouter() r.Use(middleware.Logger) - srv := jrpc.NewServer(r) + srv := server.NewServer(r) - r.HandleFunc("echo", func(w jrpc.ResponseWriter, r *jrpc.Request) { + r.HandleFunc("echo", func(w codec.ResponseWriter, r *codec.Request) { w.Send(r.Params(), nil) }) - r.HandleFunc("testservice_subscribe", func(w jrpc.ResponseWriter, r *jrpc.Request) { + r.HandleFunc("testservice_subscribe", func(w codec.ResponseWriter, r *codec.Request) { sub, err := jrpc.UpgradeToSubscription(w, r) w.Send(sub, err) if err != nil { diff --git a/exports.go b/exports.go new file mode 100644 index 0000000..8694880 --- /dev/null +++ b/exports.go @@ -0,0 +1,48 @@ +package jrpc + +import ( + "context" + + "gfx.cafe/open/jrpc/pkg/codec" + "gfx.cafe/open/jrpc/pkg/server" +) + +// to make the repo cleaner, we export everything here. this way the packages dont need to ever import this + +type ( + // Conn + Conn = codec.Conn + // Handler + Handler = codec.Handler + // HandlerFunc + HandlerFunc = codec.HandlerFunc + // ResponseWriter + ResponseWriter = codec.ResponseWriter + // StreamingConn + StreamingConn = codec.Conn +) +type ( + // BatchElem + BatchElem = codec.BatchElem +) + +var ( + ContextWithConn = codec.ContextWithConn + ContextWithPeerInfo = server.ContextWithPeerInfo + + ConnFromContext = codec.ConnFromContext + PeerInfoFromContext = server.PeerInfoFromContext +) + +// Do +func Do[T any](ctx context.Context, c Conn, method string, args any) (*T, error) { + return codec.Do[T](ctx, c, method, args) +} + +// Call +func Call[T any](ctx context.Context, c Conn, method string, args ...any) (*T, error) { + return codec.Call[T](ctx, c, method, args...) +} + +// CallInto +var CallInto = codec.CallInto diff --git a/pkg/clientutil/helper.go b/pkg/clientutil/helper.go index 0e3177e..b0f70cd 100644 --- a/pkg/clientutil/helper.go +++ b/pkg/clientutil/helper.go @@ -4,8 +4,6 @@ import ( "encoding/json" "fmt" "gfx.cafe/open/jrpc/pkg/codec" - - "gfx.cafe/open/jrpc" "gfx.cafe/util/go/generic" ) @@ -23,7 +21,7 @@ func PutMessage(x *codec.Message) { msgPool.Put(x) } -func FillBatch(ids []int, msgs []*codec.Message, b []*jrpc.BatchElem) { +func FillBatch(ids []int, msgs []*codec.Message, b []*codec.BatchElem) { answers := map[int]*codec.Message{} for _, v := range msgs { answers[v.ID.Number()] = v diff --git a/pkg/codec/codecs/codecs.go b/pkg/codec/codecs/codecs.go deleted file mode 100644 index 983a7bb..0000000 --- a/pkg/codec/codecs/codecs.go +++ /dev/null @@ -1,5 +0,0 @@ -package codecs - -import "gfx.cafe/open/jrpc/pkg/codec/codecs/inproc" - -var NewInProc = inproc.NewCodec diff --git a/helper.go b/pkg/codec/helper.go similarity index 90% rename from helper.go rename to pkg/codec/helper.go index be79e44..491ef95 100644 --- a/helper.go +++ b/pkg/codec/helper.go @@ -1,9 +1,8 @@ -package jrpc +package codec -import ( - "context" -) +import "context" +// Do func Do[T any](ctx context.Context, c Conn, method string, args any) (*T, error) { var t T err := c.Do(ctx, &t, method, args) @@ -13,6 +12,7 @@ func Do[T any](ctx context.Context, c Conn, method string, args any) (*T, error) return &t, nil } +// Call func Call[T any](ctx context.Context, c Conn, method string, args ...any) (*T, error) { var t T err := c.Do(ctx, &t, method, args) @@ -22,6 +22,7 @@ func Call[T any](ctx context.Context, c Conn, method string, args ...any) (*T, e return &t, nil } +// CallInto func CallInto(ctx context.Context, c Conn, result any, method string, args ...any) error { err := c.Do(ctx, result, method, args) if err != nil { diff --git a/jrpc.go b/pkg/codec/jrpc.go similarity index 99% rename from jrpc.go rename to pkg/codec/jrpc.go index 766ab26..c398640 100644 --- a/jrpc.go +++ b/pkg/codec/jrpc.go @@ -1,4 +1,4 @@ -package jrpc +package codec import ( "context" diff --git a/pkg/codec/json.go b/pkg/codec/json.go index 1441247..673da9f 100644 --- a/pkg/codec/json.go +++ b/pkg/codec/json.go @@ -3,7 +3,7 @@ package codec import ( "bytes" "encoding/json" - "gfx.cafe/open/jrpc/pkg/codec/codecs/websocket/wsjson" + "gfx.cafe/open/jrpc/contrib/codecs/websocket/wsjson" "strconv" ) diff --git a/request.go b/pkg/codec/reqresp.go similarity index 72% rename from request.go rename to pkg/codec/reqresp.go index 315f6ff..5692866 100644 --- a/request.go +++ b/pkg/codec/reqresp.go @@ -1,19 +1,40 @@ -package jrpc +package codec import ( "context" - codec2 "gfx.cafe/open/jrpc/pkg/codec" - json "github.com/goccy/go-json" ) +type Response struct { + Version Version `json:"jsonrpc,omitempty"` + ID *ID `json:"id,omitempty"` + Result json.RawMessage `json:"result,omitempty"` + Error *JsonError `json:"error,omitempty"` +} + +func (r *Response) Msg() *Message { + out := &Message{} + if r.ID != nil { + out.ID = r.ID + } + if r.Error != nil { + out.Error = r.Error + } else { + out.Result = r.Result + } + return out +} + type Request struct { RequestMarshaling - ctx context.Context } +func NewRequestFromRaw(ctx context.Context, req *RequestMarshaling) *Request { + return &Request{ctx: ctx, RequestMarshaling: *req} +} + func (r *Request) UnmarshalJSON(xs []byte) error { return json.Unmarshal(xs, &r.RequestMarshaling) } @@ -23,11 +44,11 @@ func (r *Request) MarshalJSON() ([]byte, error) { } type RequestMarshaling struct { - Version codec2.Version `json:"jsonrpc"` - ID *codec2.ID `json:"id,omitempty"` + Version Version `json:"jsonrpc"` + ID *ID `json:"id,omitempty"` Method string `json:"method"` Params json.RawMessage `json:"params"` - Peer codec2.PeerInfo `json:"-"` + Peer PeerInfo `json:"-"` } func NewRequestInt(ctx context.Context, id int, method string, params any) *Request { @@ -36,7 +57,7 @@ func NewRequestInt(ctx context.Context, id int, method string, params any) *Requ } r := &Request{ctx: ctx} pms, _ := json.Marshal(params) - r.ID = codec2.NewNumberIDPtr(int64(id)) + r.ID = NewNumberIDPtr(int64(id)) r.Method = method r.Params = pms return r @@ -48,7 +69,7 @@ func NewRequest(ctx context.Context, id string, method string, params any) *Requ } r := &Request{ctx: ctx} pms, _ := json.Marshal(params) - r.ID = codec2.NewStringIDPtr(id) + r.ID = NewStringIDPtr(id) r.Method = method r.Params = pms return r @@ -66,7 +87,7 @@ func NewNotification(ctx context.Context, method string, params any) *Request { return r } -func (r *Request) makeError(err error) *codec2.Message { +func (r *Request) makeError(err error) *Message { m := r.Msg() return m.ErrorResponse(err) } @@ -103,8 +124,8 @@ func (r *Request) Context() context.Context { return r.ctx } -func (r *Request) Msg() codec2.Message { - return codec2.Message{ +func (r *Request) Msg() Message { + return Message{ ID: r.ID, Method: r.Method, Params: r.Params, diff --git a/pkg/jrpctest/server.go b/pkg/jrpctest/server.go index 6eb377c..613daff 100644 --- a/pkg/jrpctest/server.go +++ b/pkg/jrpctest/server.go @@ -1,18 +1,17 @@ package jrpctest import ( + jmux2 "gfx.cafe/open/jrpc/contrib/jmux" + "gfx.cafe/open/jrpc/pkg/server" "strings" - - "gfx.cafe/open/jrpc" - "gfx.cafe/open/jrpc/pkg/jmux" ) -func NewServer() *jrpc.Server { - server := jrpc.NewServer(NewRouter()) +func NewServer() *server.Server { + server := server.NewServer(NewRouter()) return server } -func NewRouter() *jmux.Mux { - mux := jmux.NewRouter() +func NewRouter() *jmux2.Mux { + mux := jmux2.NewRouter() //mux.HandleFunc("testservice_subscribe", func(w jrpc.ResponseWriter, r *jrpc.Request) { // sub, err := jrpc.UpgradeToSubscription(w, r) // w.Send(sub, err) @@ -40,8 +39,8 @@ func NewRouter() *jmux.Mux { } return mux } -func NewRouterWithMaxSize(size int) *jmux.Mux { - mux := jmux.NewRouter() +func NewRouterWithMaxSize(size int) *jmux2.Mux { + mux := jmux2.NewRouter() //mux.HandleFunc("testservice_subscribe", func(w jrpc.ResponseWriter, r *jrpc.Request) { // sub, err := jrpc.UpgradeToSubscription(w, r) // w.Send(sub, err) diff --git a/pkg/jrpctest/services.go b/pkg/jrpctest/services.go index 653a532..eb510c1 100644 --- a/pkg/jrpctest/services.go +++ b/pkg/jrpctest/services.go @@ -3,12 +3,10 @@ package jrpctest import ( "context" "errors" + "gfx.cafe/open/jrpc/pkg/codec" + "gfx.cafe/open/jrpc/pkg/server" "strings" "time" - - "gfx.cafe/open/jrpc/pkg/codec" - - "gfx.cafe/open/jrpc" ) type testService struct{} @@ -44,7 +42,7 @@ func (s *testService) EchoWithCtx(ctx context.Context, str string, i int, args * } func (s *testService) PeerInfo(ctx context.Context) codec.PeerInfo { - return jrpc.PeerInfoFromContext(ctx) + return server.PeerInfoFromContext(ctx) } func (s *testService) Sleep(ctx context.Context, duration time.Duration) { @@ -78,7 +76,7 @@ func (s *testService) ReturnError() error { } func (s *testService) CallMeBack(ctx context.Context, method string, args []any) (any, error) { - c, ok := jrpc.ConnFromContext(ctx) + c, ok := codec.ConnFromContext(ctx) if !ok { return nil, errors.New("no client") } @@ -88,7 +86,7 @@ func (s *testService) CallMeBack(ctx context.Context, method string, args []any) } func (s *testService) CallMeBackLater(ctx context.Context, method string, args []any) error { - c, ok := jrpc.ConnFromContext(ctx) + c, ok := codec.ConnFromContext(ctx) if !ok { return errors.New("no client") } diff --git a/pkg/jrpctest/suites.go b/pkg/jrpctest/suites.go index e040cda..34564a4 100644 --- a/pkg/jrpctest/suites.go +++ b/pkg/jrpctest/suites.go @@ -8,20 +8,21 @@ import ( "testing" "time" - "gfx.cafe/open/jrpc" "gfx.cafe/open/jrpc/pkg/codec" + "gfx.cafe/open/jrpc/pkg/server" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -type ClientMaker func() jrpc.Conn -type ServerMaker func() (*jrpc.Server, ClientMaker, func()) +type ClientMaker func() codec.Conn +type ServerMaker func() (*server.Server, ClientMaker, func()) type BasicTestSuiteArgs struct { ServerMaker ServerMaker } -type TestContext func(t *testing.T, server *jrpc.Server, client jrpc.Conn) +type TestContext func(t *testing.T, server *server.Server, client codec.Conn) func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) { var executeTest = func(t *testing.T, c TestContext) { @@ -40,7 +41,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) { } t.Parallel() - makeTest("Request", func(t *testing.T, server *jrpc.Server, client jrpc.Conn) { + makeTest("Request", func(t *testing.T, server *server.Server, client codec.Conn) { var resp EchoResult err := client.Do(nil, &resp, "test_echo", []any{"hello", 10, &EchoArgs{"world"}}) require.NoError(t, err) @@ -49,20 +50,20 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) { } }) - makeTest("ResponseType", func(t *testing.T, server *jrpc.Server, client jrpc.Conn) { - if err := jrpc.CallInto(nil, client, nil, "test_echo", "hello", 10, &EchoArgs{"world"}); err != nil { + makeTest("ResponseType", func(t *testing.T, server *server.Server, client codec.Conn) { + if err := codec.CallInto(nil, client, nil, "test_echo", "hello", 10, &EchoArgs{"world"}); err != nil { t.Errorf("Passing nil as result should be fine, but got an error: %v", err) } var resultVar EchoResult // Note: passing the var, not a ref - err := jrpc.CallInto(nil, client, resultVar, "test_echo", "hello", 10, &EchoArgs{"world"}) + err := codec.CallInto(nil, client, resultVar, "test_echo", "hello", 10, &EchoArgs{"world"}) if err == nil { t.Error("Passing a var as result should be an error") } }) - makeTest("BatchRequest", func(t *testing.T, server *jrpc.Server, client jrpc.Conn) { - batch := []*jrpc.BatchElem{ + makeTest("BatchRequest", func(t *testing.T, server *server.Server, client codec.Conn) { + batch := []*codec.BatchElem{ { Method: "test_echo", Params: []any{"hello", 10, &EchoArgs{"world"}}, @@ -82,7 +83,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) { if err := client.BatchCall(nil, batch...); err != nil { t.Fatal(err) } - wantResult := []*jrpc.BatchElem{ + wantResult := []*codec.BatchElem{ { Method: "test_echo", Params: []any{"hello", 10, &EchoArgs{"world"}}, @@ -113,21 +114,21 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) { } }) - makeTest("ResposeType", func(t *testing.T, server *jrpc.Server, client jrpc.Conn) { - if err := jrpc.CallInto(nil, client, nil, "test_echo", "hello", 10, &EchoArgs{"world"}); err != nil { + makeTest("ResposeType", func(t *testing.T, server *server.Server, client codec.Conn) { + if err := codec.CallInto(nil, client, nil, "test_echo", "hello", 10, &EchoArgs{"world"}); err != nil { t.Errorf("Passing nil as result should be fine, but got an error: %v", err) } var resultVar EchoResult // Note: passing the var, not a ref - err := jrpc.CallInto(nil, client, resultVar, "test_echo", "hello", 10, &EchoArgs{"world"}) + err := codec.CallInto(nil, client, resultVar, "test_echo", "hello", 10, &EchoArgs{"world"}) if err == nil { t.Error("Passing a var as result should be an error") } }) - makeTest("ErrorReturnType", func(t *testing.T, server *jrpc.Server, client jrpc.Conn) { + makeTest("ErrorReturnType", func(t *testing.T, server *server.Server, client codec.Conn) { var resp any - err := jrpc.CallInto(nil, client, &resp, "test_returnError") + err := codec.CallInto(nil, client, &resp, "test_returnError") require.Error(t, err) // Check code. @@ -143,13 +144,13 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) { t.Fatalf("wrong error data %#v, want %#v", e.ErrorData(), testError{}.ErrorData()) } }) - makeTest("Notify", func(t *testing.T, server *jrpc.Server, client jrpc.Conn) { + makeTest("Notify", func(t *testing.T, server *server.Server, client codec.Conn) { if err := client.Notify(context.Background(), "test_echo", []any{"hello", 10, &EchoArgs{"world"}}); err != nil { t.Fatal(err) } }) - makeTest("context cancel", func(t *testing.T, server *jrpc.Server, client jrpc.Conn) { + makeTest("context cancel", func(t *testing.T, server *server.Server, client codec.Conn) { maxContextCancelTimeout := 300 * time.Millisecond // The actual test starts here. var ( @@ -179,7 +180,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) { // Now perform a call with the context. // The key thing here is that no call will ever complete successfully. - err := jrpc.CallInto(ctx, client, nil, "test_block") + err := codec.CallInto(ctx, client, nil, "test_block") switch { case err == nil: _, hasDeadline := ctx.Deadline() @@ -198,7 +199,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) { }) } -type ServerRemaker func(address string) (*jrpc.Server, ClientMaker, func()) +type ServerRemaker func(address string) (*server.Server, ClientMaker, func()) type ReconnectTestSuiteArgs struct { ServerMaker ServerMaker @@ -215,7 +216,7 @@ func RunReconnectSuite(t *testing.T, args BasicTestSuiteArgs) { // This test checks that requests made through Call can be canceled by canceling // the context. -func cancelTester(t *testing.T, server *jrpc.Server, client jrpc.Conn) { +func cancelTester(t *testing.T, server *server.Server, client codec.Conn) { maxContextCancelTimeout := 300 * time.Millisecond // The actual test starts here. @@ -246,7 +247,7 @@ func cancelTester(t *testing.T, server *jrpc.Server, client jrpc.Conn) { // Now perform a call with the context. // The key thing here is that no call will ever complete successfully. - err := jrpc.CallInto(ctx, client, nil, "test_block") + err := codec.CallInto(ctx, client, nil, "test_block") switch { case err == nil: _, hasDeadline := ctx.Deadline() diff --git a/server.go b/pkg/server/server.go similarity index 97% rename from server.go rename to pkg/server/server.go index 9a4097e..2f591cc 100644 --- a/server.go +++ b/pkg/server/server.go @@ -1,4 +1,4 @@ -package jrpc +package server import ( "context" @@ -18,7 +18,7 @@ import ( // Server is an RPC server. type Server struct { - services Handler + services codec.Handler run int32 codecs mapset.Set Tracing Tracing @@ -29,7 +29,7 @@ type Tracing struct { } // NewServer creates a new server instance with no registered handlers. -func NewServer(r Handler) *Server { +func NewServer(r codec.Handler) *Server { server := &Server{ codecs: mapset.NewSet(), run: 1, @@ -121,16 +121,15 @@ func (s *Server) ServeCodec(pctx context.Context, remote codec.ReaderWriter) { } else { defer wg.Done() } - s.services.ServeRPC(v, &Request{ - ctx: ctx, - RequestMarshaling: RequestMarshaling{ + s.services.ServeRPC(v, codec.NewRequestFromRaw( + ctx, + &codec.RequestMarshaling{ ID: v.msg.ID, Version: v.msg.Version, Method: v.msg.Method, Params: v.msg.Params, Peer: remote.PeerInfo(), - }, - }) + })) }() } wg.Wait() diff --git a/readme.md b/readme.md index 9d106ce..c5bd253 100644 --- a/readme.md +++ b/readme.md @@ -5,19 +5,29 @@ this is a bottom up implementation of jsonrpc2, primarily made for hosting eth-l many packages are unused / incomplete. the one which are done i have put below in the readme ``` -conn.go - defines the interface a json rpc client -jrpc.go - define the Handler, HandlerFunc, and ResponseWriter -request.go - define Request, along with json marshaling for the request -response.go - define Response, along with json marshaling for the response -server.go - implemntation of a server, which uses a backing codec.ReaderWriter -codec/ - codec related things - stdio/ - implementation of jrpc.Conn and codec.ReaderWriter - errors.go - jsonrpc2 error codes and marshaling - json.go - jsonrpc2 json rules, encoding, decoding - peer.go - peerinfo - transport.go - define ReaderWriter interface - wire.go - jsonrpc2 wire protocol marshaling, like ID and Version -jmux/ - a chi based router which satisfies the jrpc.Handler interface -clientutil/ - common utilities for client implementations to use - idreply.go - generalizes making a request with an incrementing id, then waiting on it +exports.go - export things in subpackages to jrpc namespace, cleaning up the public use package +pkg/ - packages for implementing jrpc + clientutil/ - common utilities for client implementations to use + idreply.go - generalizes making a request with an incrementing id, then waiting on it + helper.go - helpers for decoding messages, etc + codec/ - codec related things. used by client and server implementations + errors.go - jsonrpc2 error codes and marshaling + json.go - jsonrpc2 json rules, encoding, decoding + peer.go - peerinfo + transport.go - define ReaderWriter interface + wire.go - jsonrpc2 wire protocol marshaling, like ID and Version + server.go - a server server implementation that uses the codec + jrpc.go - define the Handler, HandlerFunc, and ResponseWriter + reqresp.go - define Request, Response, along with json marshaling for the request + jrpctest/ - utilities for testing client and server. + suite.go - implementors of client and server should pass this +contrib/ - packages that add to jrpc + jmux/ - a chi based router which satisfies the jrpc.Handler interface + handlers/ - special jrpc handlers + argreflect/ - go-ethereum style struct reflection + middleware/ - pre implemented middleware + openrpc/ - openapi specification implementation + subscription - WIP: subscription engine for go-ethereum style subs + + ``` diff --git a/response.go b/response.go deleted file mode 100644 index 07ae27f..0000000 --- a/response.go +++ /dev/null @@ -1,26 +0,0 @@ -package jrpc - -import ( - "encoding/json" - codec2 "gfx.cafe/open/jrpc/pkg/codec" -) - -type Response struct { - Version codec2.Version `json:"jsonrpc,omitempty"` - ID *codec2.ID `json:"id,omitempty"` - Result json.RawMessage `json:"result,omitempty"` - Error *codec2.JsonError `json:"error,omitempty"` -} - -func (r *Response) Msg() *codec2.Message { - out := &codec2.Message{} - if r.ID != nil { - out.ID = r.ID - } - if r.Error != nil { - out.Error = r.Error - } else { - out.Result = r.Result - } - return out -} -- GitLab