{"id":13469808,"url":"https://github.com/laruence/yar","last_synced_at":"2026-10-19T13:05:08.767Z","repository":{"id":3607790,"uuid":"4672654","full_name":"laruence/yar","owner":"laruence","description":"Lightweight, concurrent RPC framework for PHP\u0026C","archived":false,"fork":false,"pushed_at":"2026-09-23T16:34:25.000Z","size":845,"stargazers_count":1435,"open_issues_count":25,"forks_count":315,"subscribers_count":133,"default_branch":"master","last_synced_at":"2026-10-09T19:34:58.634Z","etag":null,"topics":["c","concurency","concurrency","json","msgpack","php","phpextension","rpc-framework","yar"],"latest_commit_sha":null,"homepage":"https://php.net/manual/book.yar","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/laruence.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","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,"claude":null,"gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null},"funding":{"github":"laruence","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"custom":null}},"created_at":"2012-06-15T07:42:26.000Z","updated_at":"2026-10-06T17:57:04.000Z","dependencies_parsed_at":"2026-08-06T07:19:28.099Z","dependency_job_id":null,"html_url":"https://github.com/laruence/yar","commit_stats":{"total_commits":562,"total_committers":21,"mean_commits":"26.761904761904763","dds":0.08185053380782914,"last_synced_commit":"de347c86da5f6550b437672277f8ff852efbfaf7"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/laruence/yar","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laruence%2Fyar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laruence%2Fyar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laruence%2Fyar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laruence%2Fyar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/laruence","download_url":"https://codeload.github.com/laruence/yar/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/laruence%2Fyar/sbom","scorecard":{"id":579434,"data":{"date":"2025-08-11","repo":{"name":"github.com/laruence/yar","commit":"a9ca8d05e21cbafd5268d4b53027da6d471dc7cf"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.9,"checks":[{"name":"Code-Review","score":0,"reason":"Found 2/27 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/integrate.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":5,"reason":"5 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/integrate.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/laruence/yar/integrate.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/integrate.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/laruence/yar/integrate.yml/master?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 5 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T18:47:17.923Z","repository_id":3607790,"created_at":"2025-08-20T18:47:17.923Z","updated_at":"2025-08-20T18:47:17.923Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":344872684,"owners_count":38356524,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-19T02:00:06.414Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["c","concurency","concurrency","json","msgpack","php","phpextension","rpc-framework","yar"],"created_at":"2024-07-31T16:00:16.803Z","updated_at":"2026-10-19T13:05:08.760Z","avatar_url":"https://github.com/laruence.png","language":"C","funding_links":["https://github.com/sponsors/laruence"],"categories":["Networking and Distributed","C","网站框架","RPC框架"],"sub_categories":["RPC and Messaging"],"readme":"# Yar - Yet Another RPC framework for PHP\n\n[![AppVeyor](https://ci.appveyor.com/api/projects/status/syhw33wlt2nad64i/branch/master?svg=true)](https://ci.appveyor.com/project/laruence/yar/branch/master) [![Linux](https://github.com/laruence/yar/actions/workflows/linux.yml/badge.svg?branch=master)](https://github.com/laruence/yar/actions/workflows/linux.yml) [![Windows](https://github.com/laruence/yar/actions/workflows/windows.yml/badge.svg?branch=master)](https://github.com/laruence/yar/actions/workflows/windows.yml)\n\nLight, concurrent RPC framework for PHP (see also: [Yar C framework](https://github.com/laruence/yar-c), [Yar Java framework](https://github.com/weibocom/yar-java), [Lua Yar framework](https://github.com/fangfengxiang/lua-yar))\n\n## Requirement\n\n- PHP 7.0+ (master branch)\n- PHP 5.2+ ([php5 branch](https://github.com/laruence/yar/tree/php5))\n- Curl\n- Json\n- Msgpack (Optional)\n\n## Introduction\n\nYar is an RPC framework which provides a simple and easy way to do communication between PHP applications. It also offers the ability to make multiple calls to remote services concurrently.\n\nYar is a **native PHP extension** — not a userland library. It uses a compact binary protocol (`yar_header_t` + packager payload) over HTTP or TCP, with no external runtime dependencies beyond curl. This means no Composer packages, no framework bootstrap, no separate proxy process. It's designed for the \"just works\" experience: install the extension, write a few lines of PHP, and you have RPC.\n\n### When to use Yar\n\n- **Best for**: RPC between PHP applications (or any combination of PHP, C, Java, and Lua via the respective Yar implementations). Microservices within the same infrastructure. Scenarios where low latency and minimal operational overhead matter more than schema-driven code generation.\n- **Not ideal for**: Public-facing APIs consumed by arbitrary third-party clients (use REST or gRPC with Protobuf instead). Environments that require built-in service discovery, load balancing, or streaming (gRPC is a better fit there).\n\n## Features\n\n- Fast, easy, simple\n- Concurrent RPC calls\n- Multiple data packagers supported (php, json, msgpack built-in)\n- Multiple transfer protocols supported (HTTP, HTTPS, TCP)\n- Detailed debug information\n\n## Install\n\n### Install via PECL\n\nYar is a PECL extension, simply install it by:\n\n```bash\n$ pecl install yar\n```\n\n### Compile from source\n\n```bash\n$ /path/to/phpize\n$ ./configure --with-php-config=/path/to/php-config/\n$ make \u0026\u0026 make install\n```\n\nAvailable configure options:\n\n```bash\n--with-curl=DIR\n--enable-msgpack / --disable-msgpack\n--enable-epoll / --disable-epoll (requires Yar 2.1.2)\n```\n\n`--enable-epoll` replaces the default `select()`-based I/O multiplexing with Linux `epoll`. This can improve performance for `Yar_Concurrent_Client` under high concurrency. It only affects Linux; on other platforms it has no effect.\n\n### Install Yar with msgpack\n\n1. Install msgpack extension for PHP:\n\n```bash\n$ pecl install msgpack\n```\n\nOr for Ubuntu:\n\n```bash\n$ apt-get install msgpack-php\n```\n\nOr, get the source from GitHub: https://github.com/msgpack/msgpack-php\n\n2. Configure with msgpack enabled:\n\n```bash\n$ /path/to/phpize\n$ ./configure --with-php-config=/path/to/php-config/ --enable-msgpack\n$ make \u0026\u0026 make install\n```\n\n## Runtime Configuration\n\n| INI Setting | Default | Description |\n|---|---|---|\n| `yar.timeout` | `5000` | Timeout in milliseconds |\n| `yar.connect_timeout` | `1000` | Connection timeout in milliseconds |\n| `yar.packager` | `\"php\"` (or `\"msgpack\"` if built with `--enable-msgpack`) | One of `\"php\"`, `\"json\"`, `\"msgpack\"` |\n| `yar.debug` | `Off` | Enable debug mode. When enabled, Yar emits `E_WARNING` messages with detailed protocol-level information for every request and response, prefixed with `[Debug Yar_Server]` or `[Debug Yar_Client]` and including timestamps. |\n| `yar.expose_info` | `On` | Whether to output the API info page for GET requests |\n| `yar.content_type` | `\"application/octet-stream\"` | Content-Type sent in responses |\n| `yar.ssl_verify` | `Off` | Whether to verify the TLS certificate of HTTPS servers. When enabled, the curl transport sets `CURLOPT_SSL_VERIFYPEER` and `CURLOPT_SSL_VERIFYHOST`, and requests against servers with invalid certificates will fail. Disabled by default for backward compatibility. Available since 2.4.0. |\n\n\u003e **Note**: `yar.connect_timeout` is in milliseconds. Prior to 1.2.1 it was measured in seconds.\n\n## Constants\n\n### Option Constants\n\n```php\nYAR_OPT_PACKAGER\nYAR_OPT_PERSISTENT\nYAR_OPT_TIMEOUT\nYAR_OPT_CONNECT_TIMEOUT\nYAR_OPT_HEADER          // Since 2.0.4\nYAR_OPT_PROXY           // Since 2.2.0\nYAR_OPT_RESOLVE         // Since 2.1.0\nYAR_OPT_PROVIDER        // Since 2.3.0\nYAR_OPT_TOKEN           // Since 2.3.0\n```\n\n### Version \u0026 Feature Constants\n\n```php\nYAR_VERSION\nYAR_HAS_MSGPACK   // 1 if compiled with --enable-msgpack, 0 otherwise\n```\n\n### Error Type Constants\n\nUsed by `Yar_Server_Exception::getType()` and `Yar_Client_Exception::getType()` to indicate the nature of the error:\n\n```php\nYAR_ERR_OKEY       = 0x00  // No error\nYAR_ERR_PACKAGER   = 0x01  // Packager error\nYAR_ERR_PROTOCOL   = 0x02  // Protocol error\nYAR_ERR_REQUEST    = 0x04  // Request error\nYAR_ERR_OUTPUT     = 0x08  // Output error\nYAR_ERR_TRANSPORT  = 0x10  // Transport error\nYAR_ERR_FORBIDDEN  = 0x20  // Forbidden (auth failed or info page disabled)\nYAR_ERR_EXCEPTION  = 0x40  // General exception\n```\n\n## Exception Classes\n\nYar defines a structured exception hierarchy for both server and client errors:\n\n```\nException / RuntimeException\n├── Yar_Server_Exception\n│   ├── Yar_Server_Request_Exception\n│   ├── Yar_Server_Protocol_Exception\n│   ├── Yar_Server_Packager_Exception\n│   └── Yar_Server_Output_Exception\n└── Yar_Client_Exception\n    ├── Yar_Client_Transport_Exception\n    ├── Yar_Client_Protocol_Exception\n    └── Yar_Client_Packager_Exception\n```\n\nBoth `Yar_Server_Exception` and `Yar_Client_Exception` extend `Exception` (or `RuntimeException` if SPL is available).\n\n`Yar_Server_Exception::getType()` returns the error type constant (e.g. `YAR_ERR_TRANSPORT`).\n\n`Yar_Client_Exception::getType()` returns the string `\"Yar_Exception_Client\"` — this is the exception class name, not an error type constant. If you need the actual error type on the client side, catch the specific sub-exception classes instead (e.g. `Yar_Client_Transport_Exception`, `Yar_Client_Protocol_Exception`, `Yar_Client_Packager_Exception`).\n\n## Server\n\n\u003e **Note**: `Yar_Server` is a `final` class and cannot be extended.\n\n### HTTP Server\n\nIt's very easy to set up a Yar HTTP RPC Server:\n\n```php\n\u003c?php\nclass API\n{\n    /**\n     * The doc info will be generated automatically into the service info page.\n     * @params\n     * @return\n     */\n    public function some_method($parameter, $option = \"foo\")\n    {\n    }\n\n    protected function client_can_not_see()\n    {\n    }\n}\n\n$service = new Yar_Server(new API());\n$service-\u003ehandle();\n```\n\nUsual RPC calls are issued as HTTP POST requests.\n\nIf an HTTP GET request is issued to the URI (access the API address directly via a browser), the service info page (generated from the doc comments above) will be returned:\n\n![yar service info page](https://github.com/laruence/laruence.github.com/raw/master/yar_server.png)\n\n### Yar_Server::__construct\n\n```php\nYar_Server::__construct(object $executor)\n```\n\nCreates a new Yar server wrapping the given `$executor` object. All public methods of `$executor` are exposed as RPC endpoints.\n\n### Yar_Server::handle\n\n```php\nYar_Server::handle(): bool\n```\n\nStarts processing the incoming RPC request. Returns `true` on success.\n\n### TCP Server\n\nYar's PHP extension only provides an HTTP server. For TCP-based RPC servers, use the standalone [Yar C framework](https://github.com/laruence/yar-c). It supports TCP and Unix socket protocols and is fully compatible with Yar PHP clients. The C framework is also the recommended backend for production deployments with high throughput requirements.\n\n### Custom Server Info\n\nSince 2.3.0, you can customise the output of the service info page by defining a `__info` magic method:\n\n```php\n\u003c?php\nclass API\n{\n    protected function __info($markup)\n    {\n        return \"Hello world\";\n    }\n}\n```\n\nThen if an HTTP GET request is issued, \"Hello world\" will be returned instead.\n\n### Authentication\n\nSince 2.3.0, Yar allows the server to authenticate client requests via `Provider` / `Token` fields in the header. To enable this, define a protected magic method named `__auth` on the server side:\n\n```php\n\u003c?php\nclass API\n{\n    protected function __auth($provider, $token)\n    {\n        return verify($provider, $token);\n    }\n}\n```\n\n\u003e **Note**: `__auth` must always be defined as `protected`.\n\nIf `__auth` is defined, it will be called at the very beginning of every request:\n\n- If `__auth` returns `true` (or any truthy value — `1`, a non-empty string, a non-empty array, etc.), the request proceeds.\n- If `__auth` returns `false` (exactly `false`), the request is terminated with an \"authentication failed\" error (`YAR_ERR_FORBIDDEN`).\n\nOn the client side, specify the provider and token via:\n\n```php\n\u003c?php\n$client-\u003esetOpt(YAR_OPT_PROVIDER, \"provider\");\n$client-\u003esetOpt(YAR_OPT_TOKEN, \"token\");\n$client-\u003ecall();\n```\n\n## Client\n\n\u003e **Note**: `Yar_Client` is a `final` class and cannot be extended.\n\n### Yar_Client::__construct\n\n```php\nYar_Client::__construct(string $uri[, array $options = null])\n```\n\nCreates a new Yar client. The `$uri` is the server address (e.g. `\"http://host/api/\"` or `\"tcp://host:port\"`).\n\n`$options` is an optional array of initial options, e.g.:\n\n```php\n$client = new Yar_Client(\"http://host/api/\", [\n    YAR_OPT_CONNECT_TIMEOUT =\u003e 1000,\n    YAR_OPT_PERSISTENT =\u003e 1,\n]);\n```\n\n### Yar_Client::setOpt\n\n```php\nYar_Client::setOpt(int $type, mixed $value): Yar_Client|bool\n```\n\nSet a client option. Returns `$this` on success (for chaining), `false` on failure.\n\nSee [Option Constants](#option-constants) for available `$type` values.\n\n### Yar_Client::getOpt\n\n```php\nYar_Client::getOpt(int $type): mixed\n```\n\nGet the current value of a client option.\n\n### Yar_Client::call\n\n```php\nYar_Client::call(string $method, array $arguments): mixed\n```\n\nCall a remote method by name. Returns the result on success.\n\n### Magic Method (__call)\n\n`Yar_Client` supports PHP's `__call`, so these are equivalent:\n\n```php\n$client-\u003ecall(\"some_method\", [$arg1, $arg2]);\n$client-\u003esome_method($arg1, $arg2);\n```\n\n### Synchronous Call\n\n```php\n\u003c?php\n$client = new Yar_Client(\"http://host/api/\");\n\n/* the following setOpt calls are optional */\n$client-\u003esetOpt(YAR_OPT_CONNECT_TIMEOUT, 1000);\n\n$client-\u003esetOpt(YAR_OPT_HEADER, [\"hd1: val\", \"hd2: val\"]); // Custom headers, Since 2.0.4\n\n/* call remote service */\n$result = $client-\u003esome_method(\"parameter\");\n```\n\n### Concurrent Call\n\nYar supports sending multiple calls concurrently and collecting the results via a callback loop.\n\n\u003e **Note**: `Yar_Concurrent_Client` only supports HTTP/HTTPS protocol. TCP and Unix socket concurrent calls are not available — use individual `Yar_Client` instances for those.\n\u003e\n\u003e **Note**: A maximum of **128** concurrent calls can be registered in a single `loop()`. Exceeding this limit triggers a warning.\n\nEach `callback` receives two arguments:\n- `$retval` — the return value of the remote method\n- `$callinfo` — an array with call metadata\n\nEach `error_callback` receives three arguments:\n- `$type` — the error type constant\n- `$error` — the error message\n- `$callinfo` — an array with call metadata\n\n```php\n\u003c?php\nfunction callback($retval, $callinfo)\n{\n    var_dump($retval);\n}\n\nfunction error_callback($type, $error, $callinfo)\n{\n    error_log($error);\n}\n\nYar_Concurrent_Client::call(\"http://host/api/\", \"some_method\", [\"parameters\"], \"callback\");\n\n// If no callback is specified, the callback in loop() will be used\nYar_Concurrent_Client::call(\"http://host/api/\", \"some_method\", [\"parameters\"]);\n\n// This server accepts json packager\nYar_Concurrent_Client::call(\"http://host/api/\", \"some_method\", [\"parameters\"],\n    \"callback\", \"error_callback\", [YAR_OPT_PACKAGER =\u003e \"json\"]);\n\n// Custom timeout\nYar_Concurrent_Client::call(\"http://host/api/\", \"some_method\", [\"parameters\"],\n    \"callback\", \"error_callback\", [YAR_OPT_TIMEOUT =\u003e 1]);\n\n// Send all requests. The error_callback and options are optional.\nYar_Concurrent_Client::loop(\"callback\", \"error_callback\", [YAR_OPT_PACKAGER =\u003e \"json\"]);\n```\n\n### Yar_Concurrent_Client::call\n\n```php\nYar_Concurrent_Client::call(\n    string $uri,\n    string $method,\n    ?array $arguments = null,\n    ?callable $callback = null,\n    ?callable $error_callback = null,\n    ?array $options = null\n): null|int|bool\n```\n\nRegisters a concurrent call. Returns `null` on error, or an opaque int ID on success.\n\n### Yar_Concurrent_Client::loop\n\n```php\nYar_Concurrent_Client::loop(\n    ?callable $callback = null,\n    ?callable $error_callback = null,\n    ?array $options = null\n): ?bool\n```\n\nSends all registered concurrent calls and waits for responses. Returns `true` on success, `null` on failure.\n\n### Yar_Concurrent_Client::reset\n\n```php\nYar_Concurrent_Client::reset(): bool\n```\n\nClears all registered concurrent calls without sending them. Returns `true` on success.\n\n### Persistent Connections\n\nSince 2.1.0, if `YAR_OPT_PERSISTENT` is set to `true`, Yar will use HTTP keep-alive to speed up repeated calls to the same address. The connection is released at the end of the PHP request lifecycle.\n\n```php\n\u003c?php\n$client = new Yar_Client(\"http://host/api/\");\n$client-\u003esetOpt(YAR_OPT_PERSISTENT, 1);\n\n$result = $client-\u003esome_method(\"parameter\");\n\n/* The following calls will speed up due to keep-alive */\n$result = $client-\u003esome_other_method1(\"parameter\");\n$result = $client-\u003esome_other_method2(\"parameter\");\n$result = $client-\u003esome_other_method3(\"parameter\");\n```\n\n### Custom Hostname Resolution\n\nSince 2.1.0, when running over HTTP, `YAR_OPT_RESOLVE` can be used to override hostname resolution.\n\n```php\n\u003c?php\n$client = new Yar_Client(\"http://host/api/\");\n\n$client-\u003esetOpt(YAR_OPT_RESOLVE, [\"host:80:127.0.0.1\"]);\n\n/* call goes to 127.0.0.1 instead of the DNS-resolved host */\n$result = $client-\u003esome_method(\"parameter\");\n```\n\n### Using an HTTP Proxy\n\nSince 2.2.1, when running over HTTP, `YAR_OPT_PROXY` can be used to route calls through an HTTP proxy (e.g. Fiddler or Charles).\n\n```php\n\u003c?php\n$client = new Yar_Client(\"http://host/api/\");\n\n$client-\u003esetOpt(YAR_OPT_PROXY, \"127.0.0.1:8888\"); // HTTP proxy, Since 2.2.0\n\n/* call is routed through the proxy */\n$result = $client-\u003esome_method(\"parameter\");\n```\n\n## Protocols\n\nYar is not only designed for PHP — all RPC requests and responses are transferred as binary data streams.\n\n### Yar Header\n\nKey messages are exchanged via a struct called \"Yar Header\":\n\n```c\n#ifdef PHP_WIN32\n#pragma pack(push)\n#pragma pack(1)\n#endif\ntypedef struct _yar_header {\n    uint32_t       id;            // transaction id\n    uint16_t       version;       // protocol version\n    uint32_t       magic_num;     // default is: 0x80DFEC60\n    uint32_t       reserved;\n    unsigned char  provider[32];  // request from who\n    unsigned char  token[32];     // request token, used for authentication\n    uint32_t       body_len;      // request body length\n}\n#ifndef PHP_WIN32\n__attribute__ ((packed))\n#endif\nyar_header_t;\n#ifdef PHP_WIN32\n#pragma pack(pop)\n#endif\n```\n\n### Packager Header\n\nYar supports multiple packager protocols via a `char[8]` identifier placed before the header struct. This indicates which packager was used to encode the body.\n\n### Request\n\nWhen a client makes an RPC request, the request body is sent as an array (in PHP):\n\n```php\n\u003c?php\n[\n    \"i\" =\u003e '', // transaction id\n    \"m\" =\u003e '', // the method being called\n    \"p\" =\u003e [], // parameters\n]\n```\n\n### Response\n\nWhen a server responds, the response body is also sent as an array (in PHP):\n\n```php\n\u003c?php\n[\n    \"i\" =\u003e '', // transaction id\n    \"s\" =\u003e '', // status\n    \"r\" =\u003e '', // return value\n    \"o\" =\u003e '', // output\n    \"e\" =\u003e '', // error or exception\n]\n```\n\nSince 2.4.0, the client validates the transaction id (`\"i\"`) of a response against the id of the request it belongs to. A response carrying a different, non-zero transaction id (for example, one misrouted by a proxy) is rejected with a protocol error (`response id mismatch`). This applies to both synchronous calls and `Yar_Concurrent_Client`. Responses with a zero/missing transaction id are still accepted for backward compatibility with older servers.\n\n## License\n\n[PHP-3.01](https://www.php.net/license/3_01.txt)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaruence%2Fyar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaruence%2Fyar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaruence%2Fyar/lists"}