github unkn0wn-root/resterm v1.13.0

4 hours ago

v1.13.0

This release adds Digest auth and support for custom Host headers. It also fixes several problems with closing SSE and WebSocket sessions.

Digest auth

You can now use Digest auth with HTTP and SSE requests. Add @auth digest with your username and password:

### Reports
# @auth digest {{api.user}} {{api.password}}
GET {{base.url}}/reports

Resterm handles the server's 401 challenge and retries once with an Authorization: Digest header. The editor suggests digest after @auth, and Explain shows that the header is sent after the challenge.

See the Digest auth docs for supported algorithms and how Digest works with cookies, redirects and existing headers.

If you used @auth Digest for a custom header

digest is now reserved for authentication. If you used # @auth Digest sha-256=abc in 1.12.1 to send a custom header, write the header directly:

### Upload
POST https://api.example.com/upload
Digest: sha-256=abc

The old form now fails with:

error[parse]: @auth requires a valid auth spec

With two or more values, @auth Digest treats the first as the username and the rest as the password.

Custom Host headers

Resterm now sends the Host header you set on a request, including in WebSocket handshakes. You can use it to reach a virtual host through a gateway:

### Internal API through the gateway
GET http://10.0.0.12:8080/health
Host: api.internal

If you already set Host, check its value: it had no effect in 1.12.1. The connection and TLS server name still use the URL's host.

Redirects that change Host now drop credentials, even when the address stays the same. The Headers tab, Explain, and resterm run --headers show the value sent.

See the HTTP settings docs for cookie and redirect behavior.

WebSocket

Compression

To turn off compression for every WebSocket request in a file, put this before the first request:

# @setting ws-compression false

For an environment, set "settings.ws-compression": "false" in resterm.env.json. Per-request compression= still takes precedence, and compression is on by default. The editor suggests the new setting.

Pings and pongs from the server

The transcript and receivedCount now include server pings and pongs, including replies to @ws ping. Check any assertions that expect an exact count. Resterm still answers pings, but incoming pings and pongs don't reset idle-timeout.

Message size errors

When a message exceeds the size limit, the error now tells you which option to change:

websocket message exceeds 32768 bytes, raise it with @websocket max-message-bytes

See the streaming docs for more on WebSocket settings and transcripts.

CLI exit codes

With detailed exit codes, resterm run now returns 26 (protocol) instead of 21 (network) for malformed HTTP responses. This includes invalid status lines, headers, Content-Length, and Transfer-Encoding. JSON reports use protocol for the failure code and category.

Connection failures and replies cut short still return 21. If your scripts check exit codes, review those checks against the exit code reference.

Fixed

  • Canceling an SSE stream closes its connection immediately, even if the server is silent. Switching workspaces no longer leaves the old stream open.
  • Closing or canceling a WebSocket session while a send is in progress no longer reports a send error in place of the close or cancellation.
  • A WebSocket send that fails before reaching the socket now fails only that send, rather than ending the whole session.
  • # @ws close 4001 "client done" now sends client done, without the surrounding quotes. Quotes inside the reason are preserved.

OAuth documentation

Resterm sends OAuth client IDs and secrets as written in the Basic header. The OAuth docs now explain how to handle providers that expect URL-encoded credentials, such as secrets containing + or % or client IDs containing ::

# @const oauth.id {{= url.encode(env.get("oauth.clientId")) }}
# @const oauth.secret {{= url.encode(env.get("oauth.clientSecret")) }}

### Resource
# @auth oauth2 token_url={{oauth.tokenUrl}} client_id={{oauth.id}} client_secret={{oauth.secret}}
GET {{base.url}}/resource

If your provider accepts form fields, client_auth=body works too. Don't combine it with url.encode; the form body is already encoded.

Don't miss a new resterm release

NewReleases is sending notifications on new releases.