# HTTP with ASPL 0.5.0

[العربية](guide.ar.md) · [API, limits and errors](reference.en.md) · [Installation and deployment](deployment.en.md) · [C interoperability](../c-interop/guide.en.md)

These examples run on x86-64 Linux with glibc 2.34 or later. HTTP is supplied
with the native tool. The online playground and private embedding profile reject
it before execution. ASPL 0.5.0 is a local release candidate; the published
0.4.0 download does not provide this API. Start with the
[installation guide](deployment.en.md), then return here.

## A text service and explicit state

Download the whole [English source directory](../examples/http/en/service.aspl)
from the repository, including [settings.aspl](../examples/http/en/settings.aspl),
[handlers.لبات](../examples/http/en/handlers.لبات) and
[requests.لبات](../examples/http/en/requests.لبات). Keep their exact filenames
and relative paths. From the repository root, use the selected 0.5.0 tool on PATH:

```sh
aspl --version
aspl check docs/examples/http/en/service.aspl
aspl run docs/examples/http/en/service.aspl
```

The version must be `aspl 0.5.0`. The service stays in the foreground on
`127.0.0.1:8080`. In another terminal run the checked client:

```sh
aspl check docs/examples/http/en/client.aspl
aspl run docs/examples/http/en/client.aspl
```

It prints `checked text, JSON, 00 FF 41, and 404` and exits with status 0.
GET `/hello` returns `مرحبا من ASPL` with `text/plain; charset=utf-8`.
POST `/submit` receives the explicit JSON text `{"message":"مرحبا"}` with
`application/json; charset=utf-8`. The service checks UTF-8 and echoes the text;
it does not parse JSON. Applications must validate their own JSON structure.

POST `/bytes` echoes its input bytes. GET `/download` returns exactly `00 FF 41`.
The client compares all three bytes and demonstrates that decoding this body
fails with `http.invalid_utf8`. A complete `/missing` reply has status 404 in a
successful `result`, so its status and body remain available.

Each source file imports the libraries and modules it uses. `import core::http;`
activates the short prefix `http`; `استورد أساسي::ويب.` activates `ويب`.
Only the written prefix is available, while members such as `request` / `اطلب`
are exact aliases. Paths, user identifiers, and string contents stay unchanged.
Both `.aspl` and `.لبات` are valid root and imported source suffixes.

`handlers::handle` is a named top-level function, with no captures. Its
`Context<app::Config, app::State>` matches the router's configuration/state
identities. `read_state` returns a snapshot; `replace_state` publishes a whole
new value. GET `/count` reports the count before that request increments it.
A read, outbound wait, then replacement is not atomic. Reread the state after a
wait when the update depends on changes another handler may have made.

Stop from another terminal:

```sh
curl --http1.1 --request POST http://127.0.0.1:8080/stop
```

`stop(ctx)` requests drain and is idempotent. The current response can finish;
`serve` returns only after its owned work is released. Ctrl+C instead requests
execution cancellation. The first signal drains, and a second skips the rest
of drain. See the reference for deadlines and terminal outcomes.

## Verified HTTPS and a handler calling upstream

The paired [direct-TLS root](../examples/http/en/direct-tls.لبات) uses the same
handlers on port 8443. Follow the deployment guide to supply `server.pem` and
`server.key` in the process working directory. Start it, then run the
[HTTPS client](../examples/http/en/client-tls.لبات) in another terminal:

```sh
aspl check docs/examples/http/en/direct-tls.aspl
aspl run docs/examples/http/en/direct-tls.aspl
aspl check docs/examples/http/en/client-tls.aspl
aspl run docs/examples/http/en/client-tls.aspl
```

The client explicitly trusts `server.pem` as its private CA file. Its URL uses
`localhost`, which must match a DNS SAN. This private file replaces system
trust; verification remains required. Stop the direct-TLS service with:

```sh
curl --http1.1 --cacert server.pem --request POST https://localhost:8443/stop
```

GET `/upstream` in either service makes a verified request to
`https://localhost:9443/hello`, with the CA file held in `app::Config`. For a local
upstream, copy the example directory to `build/http-upstream/`, change the TLS
port in its `settings.aspl` from 8443 to 9443, and run its `direct-tls.لبات` root
in another terminal. Use the same local certificate for this exercise:

```sh
mkdir -p build/http-upstream
cp docs/examples/http/en/* build/http-upstream/
sed -i 's/8443/9443/g' build/http-upstream/settings.aspl
aspl check build/http-upstream/direct-tls.لبات
aspl run build/http-upstream/direct-tls.لبات
```

While the plain service is running, `curl --http1.1
http://127.0.0.1:8080/upstream` returns the Arabic text. Other admitted handlers
can progress while this handler waits. ASPL execution itself stays serialized.
A failed child call becomes a 502 containing its stable error code while the
parent is live. Parent cancellation discards the child completion and does not
resume the cancelled handler. Stop the upstream with the same verified curl
command, using port 9443.

[default-trust.aspl](../examples/http/en/default-trust.aspl) calls that upstream
with system trust. It reports `http.tls_verify_failed` for a local certificate
outside that trust. The automated check installs the fixture CA only in its
controlled test filesystem and proves successful default verification. For a
real upstream, change the URL to your service's HTTPS URL and use the host's
trusted CA store, or explicitly select your private CA as above.

```sh
aspl check docs/examples/http/en/default-trust.aspl
aspl run docs/examples/http/en/default-trust.aspl
aspl check docs/examples/http/en/refusal.aspl
aspl run docs/examples/http/en/refusal.aspl
```

With no listener on port 9, `refusal.aspl` prints `http.connect_failed` and
returns 0 after checking the expected recoverable result. A live listener on
that port changes the example's assumptions. The test reserves a closed local
port instead. Error text is diagnostic; branch on `error::code`.

## Generate and relocate a native program

```sh
mkdir -p build/http-guide
aspl build -o build/http-guide/service docs/examples/http/en/service.aspl
aspl build -o build/http-guide/client docs/examples/http/en/client.aspl
./build/http-guide/service --aspl-diagnostic-language=en --aspl-color=never
```

Run `./build/http-guide/client` in the other terminal, then POST `/stop`.
Copy the executables to another supported Linux host. They contain the checked
module graph and VM and need neither ASPL nor source files nor a C compiler.
TLS files and any ordinary declared C shared libraries remain deployment inputs.
`build` without `-o` removes the recognized source suffix to name its output.
A generated program accepts only the reserved diagnostic/color options, not
ASPL's `run`, `--help`, or application arguments.

## Check the documentation

From a contributor checkout:

```sh
make test-http-documentation
```

The focused check compiles all roots in both vocabularies, runs the text/JSON/
binary/client/TLS/state/stop/upstream cases, checks recoverable refusals, and
runs generated programs after removing their source modules. It reuses the
existing local peers and TLS certificate fixture, selecting ephemeral ports.
It also checks links and the catalog-derived numeric/API tables. This is guide
verification; final aggregate release verification belongs to ticket 18.
