# HTTP Protocol Reference

This reference is derived from this repo implementation in:

- `src/serverless.ts`
- `src/index.ts`

## Endpoint

- Method: `POST`
- URL: `https://http-<host>/v1beta/sql`

## Credential source

- Required: `DATABASE_URL`
- Format: `mysql://<username>:<password>@<host>/<database>`
- Source priority used by script:
  1. `DATABASE_URL` from environment
  2. `DATABASE_URL` from `.env` in current working directory

## Request body

```json
{"query":"select * from t where id = 1"}
```

`query` is plain SQL string (driver formats placeholders before sending).

## Required headers

- `Content-Type: application/json`
- `Authorization: Basic <base64(username:password)>`
- `TiDB-Database: <database or empty string>`
- `TiDB-Session: <session or empty string>`
- `X-Debug-Trace-Id: <generated request id>`
- `Accept-Encoding: gzip`

## Optional headers

- `TiDB-Isolation-Level: READ COMMITTED|REPEATABLE READ`
  - Set on `BEGIN` when tx isolation is requested.
- `TiDB-Stateful-Action: open|close`
  - `open`: create a stateful session
  - `close`: release a stateful session

## Client-side binary decode

- Default behavior: decode is automatic in one request.
- Flow: send SQL once -> inspect response `types` -> decode matching fields in returned `rows`.
- Binary-like field types:
  - `BLOB`, `TINYBLOB`, `MEDIUMBLOB`, `LONGBLOB`, `BINARY`, `VARBINARY`, `BIT`
- Input is TiDB HTTP hex text (for example `74696e79`), output is byte array JSON (for example `[116,105,110,121]`).

## Response success shape

```json
{
  "types": [
    {"name":"id","type":"INT","nullable":false}
  ],
  "rows": [["1"]],
  "rowsAffected": null,
  "sLastInsertID": null,
  "session": "<from TiDB-Session response header>"
}
```

Important behavior in driver:

- Session token comes from response header `TiDB-Session`.
- If session is empty after a call, driver throws:
  - `empty session, please try again`

## Error handling

When `response.ok` is false:

- If body is JSON with `message`, expose as database error message.
- Otherwise use HTTP status text.

## Session model

Session header parsing notes for this skill script:

- Response header name matching is case-insensitive (`TiDB-Session` and `tidb-session` are both accepted).
- If response includes `TiDB-Session`, script replaces local session with that value.
- Session replacement also happens on non-2xx responses (for example, `invalid session`).
- On `invalid session` (`code=49900001` or message contains `invalid session`), script removes the same local session file and retries once with empty session.
- If response omits `TiDB-Session`, script keeps existing local session.
- For `stateful close`, script clears local session even when response has no session header.

The driver stores session after every request and re-sends it on next request:

1. send request with `TiDB-Session: <current>`
2. read `TiDB-Session` from response headers
3. replace local session

This applies to stateless, stateful, and transaction code paths.

In stateless mode, server may still return a token-like session header. The script persists and reuses it, but this still does not imply a stateful lifecycle.

All session files are stored under `.session/` (any path portion from `--session-file` is ignored).
