Skip to content

Commit 85c2491

Browse files
committed
update dev
1 parent 2591445 commit 85c2491

File tree

1 file changed

+89
-43
lines changed

1 file changed

+89
-43
lines changed

developer/README.md

Lines changed: 89 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,66 +6,112 @@ sidebar: false
66

77
A client library for xrDebug is easy to implement as any HTTP API. Client libraries are HTTP wrappers for interacting with xrDebug, making the configuration and usage trivial to end-users.
88

9+
## Design considerations
10+
11+
- The client software is responsible for formatting the debug information.
12+
- The "ID" field is used to identify messages and pauses. It should be unique for each message or pause, and it's up to the client to generate it.
13+
914
## Message
1015

11-
To send messages is required to `POST /messages`. Code below outlines a `sendMessage` function.
16+
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.
1217

13-
```php
14-
function sendMessage($data): void
15-
{
16-
// POST /messages
17-
$curl = new Curl(/** on data **/);
18-
$curl->exec();
19-
// ...
20-
}
21-
```
18+
## Pauses
19+
20+
Pauses allow you to temporarily halt program execution until a specific condition is met. They work in a two-state system:
2221

23-
## Pause
22+
1. When a pause is created (`POST /pauses`), it starts with `stop: false`
23+
2. The program enters a polling loop, checking the pause status (`GET /pauses/{id}`)
24+
3. The pause can be released in two ways:
25+
- Stopped (`PATCH /pauses/{id}`) - Sets `stop: true`, program should terminate
26+
- Deleted (`DELETE /pauses/{id}`) - Removes the pause, program should continue
2427

25-
To implement pause is required to `POST /pauses` and sleep/wait while the `id` is paused. Code below outlines a `sendPause` and `isPaused` functions used on the PHP client.
28+
### Example pause loop
2629

2730
```php
28-
function sendPause(...$args): void
31+
class PauseException extends Exception {}
32+
33+
function waitForPause(string $id): void
2934
{
30-
// POST /pauses
31-
$curl = new Curl(/** on id **/);
32-
$curl->exec();
33-
$curlError = $curl->error();
34-
// Ignore on error
35-
if ($curlError !== '') {
36-
return;
37-
}
38-
// Sleep while id is paused
39-
do {
35+
while (true) {
36+
$response = http_get("/pauses/{$id}");
37+
if (!$response) {
38+
// Pause was deleted, continue execution
39+
return;
40+
}
41+
if ($response->stop === true) {
42+
// Pause was stopped, terminate execution
43+
throw new PauseException("Execution stopped by debugger");
44+
}
45+
// Wait before next check
4046
sleep(1);
41-
} while (isPaused($id));
47+
}
4248
}
4349

44-
function isPaused($id): bool
50+
try {
51+
// Create pause
52+
http_post("/pauses", ["id" => "debug-123"]);
53+
// Wait for pause to be released
54+
waitForPause("debug-123");
55+
// Continue execution if pause was deleted
56+
echo "Continuing...";
57+
} catch (PauseException $e) {
58+
echo "Execution stopped";
59+
exit(1);
60+
}
61+
```
62+
63+
## Signed requests
64+
65+
Request signing using Ed25519 digital signatures to verify message origin authenticity.
66+
67+
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.
68+
69+
### Sign workflow
70+
71+
To sign a request server expect the following data workflow:
72+
73+
1. Sort the post fields by key
74+
2. Concatenate the key-value pairs
75+
3. Sign the concatenated string
76+
4. Base64 encode the signature at `X-Signature` header
77+
78+
Example in PHP:
79+
80+
```php
81+
function serialize(array $data): string
4582
{
46-
// POST /pauses/$id
47-
$curl = new Curl(/** on id **/);
48-
$curlExec = $curl->exec();
49-
// Free pause on error
50-
if (! $curlExec || $curl->error() !== '') {
51-
return false;
52-
}
53-
// Read response {stop: true|false}
54-
$response = json_decode($curlExec);
55-
$stop = $response->stop ?? false;
56-
// Stop execution on stop: true
57-
if ($stop) {
58-
throw new Exception();
83+
$result = '';
84+
ksort($data);
85+
foreach ($data as $key => $value) {
86+
$result .= $key . $value;
5987
}
6088

61-
return true;
89+
return $result;
6290
}
91+
92+
$serialized = serialize($data);
93+
$signature = $privateKey->sign($serialized);
94+
$signHeader = base64_encode($signature);
6395
```
6496

65-
## Singing requests
97+
Example in Python:
6698

67-
`🚧 Work in progress`
99+
```python
100+
def serialize(data: dict) -> str:
101+
return ''.join(f'{k}{v}' for k, v in sorted(data.items()))
68102

69-
## End-to-end encryption
103+
serialized = serialize(data)
104+
signature = private_key.sign(serialized)
105+
signHeader = base64.b64encode(signature).decode()
106+
```
107+
108+
The `X-Signature` header should contain the base64 encoded signature generated by the client.
70109

71-
`🚧 Work in progress`
110+
```sh
111+
curl --fail -X POST \
112+
--data "body=My signed message" \
113+
--data "file_path=file" \
114+
--data "file_line=1" \
115+
-H "X-Signature: <signHeader>" \
116+
http://127.0.0.1:27420/messages
117+
```

0 commit comments

Comments
 (0)