{"id":49558300,"url":"https://github.com/omarjatoi/json-rpc.erl","last_synced_at":"2026-05-03T06:43:05.055Z","repository":{"id":355025804,"uuid":"820093954","full_name":"omarjatoi/json-rpc.erl","owner":"omarjatoi","description":"JSON-RPC 2.0 server and client implementation in Erlang.","archived":false,"fork":false,"pushed_at":"2026-05-01T14:12:04.000Z","size":79,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-01T14:29:09.752Z","etag":null,"topics":["erlang","json-rpc","json-rpc-2","json-rpc-client","json-rpc-server","json-rpc2"],"latest_commit_sha":null,"homepage":"https://www.jsonrpc.org/specification","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/omarjatoi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-06-25T19:35:19.000Z","updated_at":"2026-05-01T14:12:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/omarjatoi/json-rpc.erl","commit_stats":null,"previous_names":["omarjatoi/json-rpc.erl"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/omarjatoi/json-rpc.erl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/omarjatoi%2Fjson-rpc.erl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/omarjatoi%2Fjson-rpc.erl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/omarjatoi%2Fjson-rpc.erl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/omarjatoi%2Fjson-rpc.erl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/omarjatoi","download_url":"https://codeload.github.com/omarjatoi/json-rpc.erl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/omarjatoi%2Fjson-rpc.erl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32560914,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["erlang","json-rpc","json-rpc-2","json-rpc-client","json-rpc-server","json-rpc2"],"created_at":"2026-05-03T06:43:00.247Z","updated_at":"2026-05-03T06:43:05.042Z","avatar_url":"https://github.com/omarjatoi.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# json-rpc\n\n[JSON-RPC-2.0](https://www.jsonrpc.org/specification) server in Erlang, exposed\nover plain HTTP and WebSocket via [Cowboy](https://github.com/ninenines/cowboy).\n\n## Endpoints\n\nThe application starts a single Cowboy listener with two routes:\n\n| Route          | Method | Purpose                              |\n|----------------|--------|--------------------------------------|\n| `POST /rpc`    | POST   | One-shot JSON-RPC call/notification/batch. |\n| `GET /ws`      | GET    | Persistent JSON-RPC channel over WebSocket text frames. |\n\nThe HTTP transport answers with `200 OK` for any well-formed JSON-RPC payload —\nJSON-RPC errors live in the response body, not the HTTP status. The transport\nlayer itself returns:\n\n- `204 No Content` for notifications and all-notification batches (no body).\n- `405 Method Not Allowed` (with `Allow: POST`) for non-`POST` requests to `/rpc`.\n- `413 Payload Too Large` (with a `-32700` JSON-RPC body) when the request body\n  exceeds `max_body_bytes`.\n- `415 Unsupported Media Type` when `Content-Type` is not `application/json`.\n\nThe WebSocket endpoint accepts JSON-RPC payloads as text frames and responds\nwith text frames (notifications produce no frame at all). Malformed JSON\nyields a `-32700` envelope as a text frame.\n\n## Usage\n\n### Register a method\n\n```erlang\nok = json_rpc_methods:register_method(\n    \u003c\u003c\"subtract\"\u003e\u003e,\n    {my_handlers, subtract}\n).\n```\n\nHandlers are `{Module, Function}` pairs invoked as arity-1 (the function\nreceives the JSON-RPC `params` value). They may surface application-level\nerrors by throwing the structured tuple `{jsonrpc_error, Code, Msg}` or\n`{jsonrpc_error, Code, Msg, Data}`; the values flow through to the JSON-RPC\n`error` object verbatim.\n\n### HTTP examples\n\nA call:\n\n```sh\ncurl -sS -X POST http://localhost:8080/rpc \\\n    -H 'Content-Type: application/json' \\\n    -d '{\"jsonrpc\":\"2.0\",\"method\":\"subtract\",\"params\":[42,23],\"id\":1}'\n# -\u003e {\"jsonrpc\":\"2.0\",\"result\":19,\"id\":1}\n```\n\nA notification (no `id` member, expect `204 No Content`):\n\n```sh\ncurl -sS -i -X POST http://localhost:8080/rpc \\\n    -H 'Content-Type: application/json' \\\n    -d '{\"jsonrpc\":\"2.0\",\"method\":\"update\",\"params\":[1,2,3]}'\n# -\u003e HTTP/1.1 204 No Content\n```\n\nA batch (notifications inside a batch are silently dropped from the response\narray; an all-notification batch yields `204 No Content`):\n\n```sh\ncurl -sS -X POST http://localhost:8080/rpc \\\n    -H 'Content-Type: application/json' \\\n    -d '[\n        {\"jsonrpc\":\"2.0\",\"method\":\"sum\",\"params\":[1,2,4],\"id\":\"1\"},\n        {\"jsonrpc\":\"2.0\",\"method\":\"notify_hello\",\"params\":[7]},\n        {\"jsonrpc\":\"2.0\",\"method\":\"subtract\",\"params\":[42,23],\"id\":\"2\"}\n    ]'\n# -\u003e [{\"jsonrpc\":\"2.0\",\"result\":7,\"id\":\"1\"},\n#     {\"jsonrpc\":\"2.0\",\"result\":19,\"id\":\"2\"}]\n```\n\n## Configuration\n\nSet these via `application:set_env/3` (or `sys.config`) before\n`application:ensure_all_started(json_rpc)`.\n\n| Key                | Default       | Meaning |\n|--------------------|---------------|---------|\n| `port`             | `8080`        | TCP port for the Cowboy listener. |\n| `max_body_bytes`   | `1_048_576`   | Per-request body cap. Overflow → `413` with a `-32700` body. |\n| `max_connections`  | `1_024`       | `ranch`'s `max_connections` for the listener. |\n| `num_acceptors`    | `10`          | Number of acceptor processes. |\n| `idle_timeout_ms`  | `60_000`      | Cowboy `idle_timeout` (applies to keep-alive HTTP and WebSocket). |\n\n## Securing your endpoint\n\nThe library ships **no** authentication, no TLS listener, and no `Authorization`\nparsing of any kind. By design it expects to sit plaintext behind an L7 proxy\n(Envoy, nginx, HAProxy, …) that terminates TLS, enforces rate limits, and\napplies whatever auth scheme you use (mTLS, bearer tokens, OIDC, …). If you\nneed to authenticate inside the BEAM, slot a Cowboy middleware in front of the\ntwo handlers; full recipes will land in a later phase.\n\n## Development\n\n`erlang` and `rebar3` are the two required development dependencies; `erlfmt` is useful but not mandatory. There is a [`flake.nix`](./flake.nix) with a development shell with both dependencies present, you can run the shell with `nix develop` (you may want to pass `--command /bin/zsh` on macOS), or via `make sh`.\n\nThere is a [`Makefile`](./Makefile) with the common tasks; run `make` to see\nthem:\n\n```\nRun tasks for json-rpc\n\n  build      compile the json-rpc application\n  clean      run rebar3 clean and delete the build dir\n  deps       get dependencies for the project\n  format     run the erlfmt formatter\n  lint       run linter (rebar3_lint)\n  xref       run rebar3 xref\n  dialyzer   run rebar3 dialyzer\n  check      run format, lint, xref, dialyzer (fail fast)\n  test       run all common_test suites\n  ct         run rebar3 ct\n  sh         launch a nix shell with zsh (erlang, rebar3)\n```\n\nAlternatively, you can use `rebar3` directly.\n\n|Command|Description|\n|-|-|\n|`rebar3 update`|Download any dependencies|\n|`rebar3 compile`|Build the project|\n|`rebar3 ct`|Run all common_test suites|\n|`rebar3 xref`|Run cross-reference checks|\n|`rebar3 dialyzer`|Run the static type analyzer|\n|`rebar3 format`|Run the [Erlang formatter](https://github.com/WhatsApp/erlfmt)|\n\n## License\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fomarjatoi%2Fjson-rpc.erl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fomarjatoi%2Fjson-rpc.erl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fomarjatoi%2Fjson-rpc.erl/lists"}