Pipe Reference¶
Civi::pipe
was introduced in CiviCRM v5.47.
The Civi::pipe
transport provides a request-response mechanism for executing multiple tasks within a single CiviCRM process. It uses
a line-oriented message protocol and complies with JSON-RPC v2.0. The transport
is compatible with several mechanisms for bootstrapping CiviCRM.
The list of valid method calls is purposefully short. It allows for establishing/testing a session, authenticating, and sending API calls (APIv3 and APIv4).
Example¶
This example connects to a CiviCRM site running in /var/www/example.com/web
and issues two requests.
In bash
, open the pipe:
$ cd /var/www/example.com/web
$ cv ev 'Civi::pipe();'
The command responds with a welcome message:
{"Civi::pipe":{"v":"5.47.alpha1","t":"trusted","l":["login"]}}
Within this pipe, we may send requests and receive responses:
// Send request for `echo("hello world")`
{"jsonrpc":"2.0","method":"echo","params":["hello world"],"id":null}
// Receive response "hello world"
{"jsonrpc":"2.0","result":["hello world"],"id":null}
// Send request for `api3("System", "flush")`
{"jsonrpc":"2.0","method":"api3","params":["System","flush",{"check_permissions":0}],"id":null}
// Receive response
{"jsonrpc":"2.0","result":{"is_error":0,"version":3,"count":1,"values":1},"id":null}
Overview¶
The general flow for a pipe session is:
- A client opens a connection to
Civi::pipe()
- The server responds with a header (UTF-8, one-line, JSON).
- The client submits a request (UTF-8, one-line, JSON-RPC).
- The server sends a response (UTF-8, one-line, JSON-RPC).
- Go back to (3).
Requests are executed synchronously with a single thread of operation (one request then one response). This parallels the PHP-HTTP architecture ordinarily used by CiviCRM (one process handles one request at a time). However, it expands the lifetime of the PHP process to serve multiple requests. This avoids redundant bootstraps. It is suitable for a series of requests with a common context (eg several requests by the same user).
The pipe protocol is specifically focused on two-channel communication (STDIN
/STDOUT
). If there is a third (STDERR
)
channel, then the client MAY log or display it for debugging purposes. However, STDERR
must be ignored when parsing requests
and responses.
Connection¶
CLI¶
The function Civi::pipe()
begins the server process for evaluating requests. Here are a few examples to invoke Civi::pipe()
:
## Start with cv
$ cd /var/www/example.com/web
$ cv ev 'Civi::pipe();'
{"Civi::pipe":{"v":"5.47.alpha1","t":"trusted","l":["login"]}}
## Start with drush
$ cd /var/www/example.com/web
$ drush ev 'civicrm_initialize(); Civi::pipe();'
{"Civi::pipe":{"v":"5.47.alpha1","t":"trusted","l":["login"]}}
## Start with wp-cli
$ cd /var/www/example.com/web
$ wp eval 'civicrm_initialize(); Civi::pipe();'
{"Civi::pipe":{"v":"5.47.alpha1","t":"trusted","l":["login"]}}
## Start with SSH + cv
$ ssh webuser@backend.example.com cv ev --cwd=/var/www/example.com/web ev "Civi::pipe();"
{"Civi::pipe":{"v":"5.47.alpha1","t":"trusted","l":["login"]}}
At this point, the connection is established, and you may send requests.
Flags¶
When connecting, the pipe provides a welcome message with a series of flags.
Advanced clients may request a list of connection flags when calling Civi::pipe()
. Connection flags are useful for both reporting about the
connection and requesting specific features.
For example, this requests two flags (v
, u
) and receives a welcome message:
Civi::pipe("vu");
{"Civi::pipe":{"v":"5.47.alpha1","u":"untrusted"}
The v
flag reports on the active CiviCRM version. The u
flag marks the session as untrusted (which ensures that API calls must enforce permissions).
Valid flags are:
v
(version): Report the CiviCRM version. Ex:"v":"5.48.0"
j
(json-rpc): Report supported flavors of JSON-RPC. Ex:"j":["jsonrpc-2.0"]
l
(login): Report whether user logins are supported. Values may be"l":["login"]
(if the server supports AuthX) or"l":["nologin"]
(if there are no login mechanisms).t
(trusted): Mark session as trusted. Logins do not require credentials. API calls may execute with or without permission-checks.u
(untrusted): Mark session as untrusted. Logins require credentials. API calls may only execute with permission-checks.
Unrecognized flags must not cause a failure. They must report as null
. In this example, x
is an unrecognized flag:
Civi::pipe("uxv");
{"Civi::pipe":{"u":"untrusted","x":null,"v":"5.48.0"}
Line format¶
Each request and response is a JSON object formatted to fit on a single line. Lines are separated with the
conventional newline character (\n
).
Payload data MAY include escaped newlines ("\n"
).
JSON is rendered in condensed / ugly / non-"pretty-printed" format. It MUST NOT include the line-delimiter as whitespace.
For readability, some long examples in the documentation may be displayed with multiple lines. But these lines are not transmitted over the wire.
Each request-line and each response-line is formatted according to JSON-RPC v2.0.
Many PHP deployments include misconfigurations, bugs, or add-ons -- which can cause extra noise to be presented on STDOUT.
Clients SHOULD use the session option responsePrefix
to detect and discard noise.
Methods¶
api3
¶
The api3
method is used to invoke APIv3 actions. It receives the standard tuple of entity-action-params.
For example, to send a request for Contact.get
with rowCount=4
and check_permissions=false
:
> {"jsonrpc":"2.0",
"method":"api3",
"params":["Contact","get",{"rowCount":4,"check_permissions":false}],
"id":null}
< {"jsonrpc":"2.0",
"result":{"is_error":0,"count":4,values:[...]},
"id":null}
By defaut, APIv3 errors are converted to JSON-RPC error-format. For some use-cases, this could lose precision or
interoperability. You may change the error format with the apiError
option.
By default, APIv3 requests received on Civi::pipe()
will enforce permission-checks. On trusted connections,
you may opt-out with "check_permissions":false
or the apiCheckPermissions
option.
api4
¶
The api4
method is used to invoke APIv4 actions. It receives the standard tuple of entity-action-params.
> {"jsonrpc":"2.0",
"method":"api4",
"params":["Contact","get",{"limit":4,"checkPermissions":false}],
"id":null}
< {"jsonrpc":"2.0",
"result":[{"id":1,"contact_type":"Organization",...}],
"id":null}
By defaut, APIv4 errors are converted to JSON-RPC error-format. For some use-cases, this could lose precision or
interoperability. You may change the error format with the apiError
option.
By default, APIv4 requests received on Civi::pipe()
will enforce permission-checks. On trusted connections,
you may opt-out with "checkPermissions":false
or the apiCheckPermissions
option.
echo
¶
The echo
message is used for testing. It simply returns the input.
> {"jsonrpc":"2.0","method":"echo","params":["hello world"],"id":null}
< {"jsonrpc":"2.0","result":["hello world"],"id":null}
login
¶
Requirements: Login requires enabling the AuthX extension.
Set the active user/contact.
> {"jsonrpc":"2.0","method":"login","params":{"contactId":202},"id":null}
< {"jsonrpc":"2.0","result":{"contactId":202,"userId":1},"id":null}
The login principal may be specified with any ONE of the following:
cred
(string
; an AuthX credential such asBearer s3cr3tk3y
)contactId
(int
; requirestrusted
mode)userId
(int
; requirestrusted
mode)user
(string
; requirestrusted
mode)
options
¶
The options
method manages connectivity options. By default, it will return a list of all known options:
> {"jsonrpc":"2.0",
"method":"options",
"id":null}
< {"jsonrpc":"2.0",
"result":{"responsePrefix":null,"bufferSize":524288},
"id":null}
Additionally, you may use it to update an option. Any modified options will be returned.
> {"jsonrpc":"2.0",
"method":"options",
"params":{"responsePrefix":"\u0001\u0001"},
"id":null}
< {"jsonrpc":"2.0",
"result":{"responsePrefix":"\u0001\u0001"},
"id":null}
The following options are defined:
apiCheckPermissions
(bool
): By default, on all connections, API calls are executed with thecheckPermissions
/check_permission
flag. This default may be switched off (for trusted connections).apiError
(string
): Specify how CiviCRM APIs should report their errors. Either:array
: Errors are reported as part of the API's result-array. Useful for precise+generic handling.exception
: Errors are converted to exceptions and then to JSON-RPC errors. Some JSON-RPC clients will convert these to client-side exceptions.
bufferSize
(int
): The maximum length of a line in the control session, measured in bytes. This determines the maximum request size. (The default value is deployment-specific/implementation-specific. The default must be at least 64kb. At time of writing, the default for civicrm-core is 512kb.)responsePrefix
(string
): Before sending any response (but after evaluating the request), send an extra prefix or delimiter. (Defensively-coded clients may set a prefix and watch for it. If any output comes before the prefix, then the client may infer that the server is misbehaved - eg a debug hack or a bad plugin is creating interference. Disregard output before the prefix.)
Special cases¶
- If a request-line is received with an empty-string, it is ignored by the server.