# Developer guide
Implementing a client library for xrDebug is straightforward since it's based on standard HTTP APIs. Client libraries act as wrappers around these HTTP endpoints, providing a clean interface that simplifies configuration and usage for end-users.
Welcome contributions
If you have an idea for a client library in a language or technology not listed here, please reach out to us. Your contributions help make xrDebug better for everyone.
# Design considerations
- Server doesn't enforce any specific message format and client software is responsible for formatting the debug information. It's recommended to use HTML for messages.
- "ID" field is used to identify messages and pauses. It should be unique, and it's up to the client to generate it.
Client software only requires to handle the following endpoints:
POST /messages
POST /pauses
GET /pauses/{id}
# Message
To send messages use the POST /messages
endpoint. In xrDebug is the client software which formats the debug information, so the server doesn't enforce any specific format. You can send any data you want, but it's recommended to use HTML.
# Pauses
Pauses allow you to temporarily halt program execution until a specific condition is met. They work in a two-state system:
- When a pause is created (
POST /pauses
), it starts withstop: false
- The program enters a polling loop, checking the pause status (
GET /pauses/{id}
) - The pause can be released in two ways:
- Stopped (
PATCH /pauses/{id}
) - Setsstop: true
, program should terminate - Deleted (
DELETE /pauses/{id}
) - Removes the pause, program should continue
- Stopped (
# Example pause loop
class PauseException extends Exception {}
function waitForPause(string $id): void
{
while (true) {
$response = http_get("/pauses/{$id}");
if (!$response) {
// Pause was deleted, continue execution
return;
}
if ($response->stop === true) {
// Pause was stopped, terminate execution
throw new PauseException("Execution stopped by debugger");
}
// Wait before next check
sleep(1);
}
}
try {
// Create pause
http_post("/pauses", ["id" => "debug-123"]);
// Wait for pause to be released
waitForPause("debug-123");
// Continue execution if pause was deleted
echo "Continuing...";
} catch (PauseException $e) {
echo "Execution stopped";
exit(1);
}
# Signed requests
Request signing using Ed25519 digital signatures to verify message origin authenticity.
To sign a request, the client must include the X-Signature
header on requests made to the xrDebug server. The signature is a base64 encoded string generated by signing the serialized post fields with the private key. If there's no fields sign an empty string.
# Sign workflow
To sign a request server expect the following data workflow:
- Sort the post fields by key
- Concatenate the key-value pairs
- Sign the concatenated string
- Base64 encode the signature at
X-Signature
header
Example in PHP:
function serialize(array $data): string
{
$result = '';
ksort($data);
foreach ($data as $key => $value) {
$result .= $key . $value;
}
return $result;
}
$serialized = serialize($data);
$signature = $privateKey->sign($serialized);
$signHeader = base64_encode($signature);
Example in Python:
def serialize(data: dict) -> str:
return ''.join(f'{k}{v}' for k, v in sorted(data.items()))
serialized = serialize(data)
signature = private_key.sign(serialized)
signHeader = base64.b64encode(signature).decode()
The X-Signature
header should contain the base64 encoded signature generated by the client.
curl --fail -X POST \
--data "body=My signed message" \
--data "file_path=file" \
--data "file_line=1" \
-H "X-Signature: <signHeader>" \
http://127.0.0.1:27420/messages