Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions docs/packages/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,29 @@ The default is also exported as a barrel-level constant for consumers that want
import {DEFAULT_TIMEOUT_MS} from '@script-development/fs-http';
```

## Authentication & XSRF

`withXSRFToken` defaults to `false` because the factory does not know what authentication shape it sits in front of — Laravel Sanctum SPA, stateless API tokens, OIDC backends, and third-party API gateways all want different answers. Consumers must opt in explicitly when their backend plants an XSRF cookie.

### Laravel Sanctum SPA

Laravel's Sanctum stateful middleware plants an `XSRF-TOKEN` cookie on the SPA's domain during the `/sanctum/csrf-cookie` handshake. axios 1.x will only read that cookie and forward it as the `X-XSRF-TOKEN` header when `withXSRFToken: true` is passed explicitly. Without that flag every state-changing request (POST / PUT / PATCH / DELETE) returns **HTTP 419 (CSRF token mismatch)** from Sanctum's middleware.

```typescript
const http = createHttpService(`${location.origin}/api`, {
withXSRFToken: true, // Laravel Sanctum SPA — read XSRF-TOKEN cookie
withCredentials: true, // send session cookie (default true)
});
```

::: warning Mocked transports hide this failure mode
Page-integration test suites that mock `@script-development/fs-http` (per ADR-0017) bypass axios entirely — the XSRF cookie / `X-XSRF-TOKEN` header round-trip never executes, so a missing `withXSRFToken: true` does not surface in test output. The first signal arrives in production: every state-changing request to a Sanctum SPA backend returns 419. Set `withXSRFToken: true` at instantiation in any Sanctum SPA consumer.
:::

### Stateless / token / non-Sanctum stacks

Stateless API token stacks (Bearer tokens, OAuth2 access tokens), OIDC backends that do not plant an `XSRF-TOKEN` cookie, and third-party API gateways should leave `withXSRFToken` at the default `false`. Enabling it is a no-op when no `XSRF-TOKEN` cookie exists on the request origin, but the explicit `false` documents the consumer's authentication shape and prevents drift if a Sanctum-shaped middleware is added to the same domain later.

## Middleware

The middleware system lets you intercept requests at three points in the lifecycle. Every registration returns an unregister function:
Expand Down Expand Up @@ -199,14 +222,14 @@ try {

### `createHttpService(baseURL, options?)`

| Parameter | Type | Description |
| -------------------------- | ------------------------ | ----------------------------------------------------------------------- |
| `baseURL` | `string` | Base URL for all requests |
| `options.timeout` | `number \| undefined` | Request timeout in milliseconds (default: `30000`; pass `0` to disable) |
| `options.headers` | `Record<string, string>` | Default headers |
| `options.withCredentials` | `boolean` | Send cookies cross-origin (default: `true`) |
| `options.withXSRFToken` | `boolean` | Include XSRF token (default: `false`) |
| `options.smartCredentials` | `boolean` | Auto-toggle credentials by origin (default: `false`) |
| Parameter | Type | Description |
| -------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `baseURL` | `string` | Base URL for all requests |
| `options.timeout` | `number \| undefined` | Request timeout in milliseconds (default: `30000`; pass `0` to disable) |
| `options.headers` | `Record<string, string>` | Default headers |
| `options.withCredentials` | `boolean` | Send cookies cross-origin (default: `true`) |
| `options.withXSRFToken` | `boolean` | Forward `XSRF-TOKEN` cookie as `X-XSRF-TOKEN` header (default: `false`). Set `true` for Laravel Sanctum SPA; leave `false` for stateless / token / non-Sanctum stacks. See [Authentication & XSRF](#authentication-xsrf). |
| `options.smartCredentials` | `boolean` | Auto-toggle credentials by origin (default: `false`) |

### Constants

Expand Down
4 changes: 4 additions & 0 deletions packages/http/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Creates a new HTTP service instance.

Per **Doctrine #8 library-author extension** (war-room CLAUDE.md, 2026-04-22), the factory applies a **30000ms default timeout** with `timeout: 0` opt-out and per-request override. See [the docs site Timeout section](https://packages.script.nl/packages/http#timeout) for the full surface contract.

### Authentication & XSRF

For Laravel Sanctum SPA consumers, `withXSRFToken: true` is required to avoid HTTP 419 (CSRF mismatch) on state-changing requests; mocked transports do not surface this. See [the docs site Authentication & XSRF section](https://packages.script.nl/packages/http#authentication-xsrf) for the full discussion (including stateless / non-Sanctum guidance).

### Request Methods

- `getRequest<T>(endpoint, options?)` — GET request
Expand Down