HTTP
The HTTP screen is a request inspector and a load tool in one:
- send a single request and see the status, the time it took, the headers and the body;
- authenticate with Basic, a Bearer token or Digest;
- keep the cookies a server sets, as a browser does;
- send the same request many times at once — a Load burst — and read the throughput and the latency percentiles.
Sending a request
- Open HTTP.
- Choose the method and type the URL, for example
http://127.0.0.1:8080/health. - Add Headers if the server needs them; + header adds a row, ✕ removes one. A row without a name is not sent.
- For a method other than GET and HEAD, write the Body. The text stays in the field while you switch to GET or HEAD and comes back with the other method, but is not sent meanwhile.
- Press Send.
The line under the buttons gives the verdict at once — status, time and size, or why there was no response — and the Response panel shows the rest. The request (method, URL, headers, body, timeout and Keep cookies) is kept when you switch screens and when you restart the app; credentials are not.
| Key | Where | Does |
|---|---|---|
| Enter | the URL, a header, a credential, the timeout | sends |
| Ctrl+Enter | any field of the request, the body included | sends |
| Ctrl+S | any field of the request | saves it as a signal (below) |
Request fields
| Field | What | Default |
|---|---|---|
| Method | GET, POST, PUT, PATCH, DELETE, HEAD or OPTIONS | GET |
| URL | An http:// or https:// URL | http://127.0.0.1:8080/ |
| Headers | Name and value pairs, sent as written. Without a User-Agent of your own, Signal Lab sends SignalLab/0.1. | Accept: application/json |
| Authentication | How the request authenticates (below) | None |
| Keep cookies | Send back the cookies servers set (below) | on |
| Body | Sent exactly as written; no Content-Type is added, so add the header that matches. An empty body is not sent. The field is not shown for GET and HEAD, and then the request carries no body at all — not in the send, not in a saved signal, not in Add to experiment — even if you typed one under another method. | empty |
| Timeout (ms) | How long the whole exchange may take, answer and body included | 10 000 |
Authentication
| Authentication | Fields | What is sent |
|---|---|---|
| None | — | no Authorization header |
| Basic | User name, Password | Authorization: Basic …, the name and password in base64, with the first request |
| Bearer token | Token | Authorization: Bearer <token> |
| Digest | User name, Password | nothing at first; the answer to the server's challenge (below) |
Switching between Basic and Digest keeps the name and password.
Digest
With Digest, Signal Lab sends the request without credentials. When the server answers 401 with a Digest challenge, Signal Lab works out the answer from the challenge and your password and sends the request again. The response you see is the one to that second request, marked Digest: challenge answered, and the latency counts both exchanges — what a client waits.
- Algorithms: MD5 and SHA-256, and their
-sessvariants. When a server offers both, SHA-256 is used. - Quality of protection:
authandauth-int, and the older answer withoutqop. - When the server says the nonce ran out (
stale), or asks again with a new one, the request is answered again, up to 3 more times. When it refuses the answer to the nonce it gave last, the401stands: the name or the password is wrong. - Redirects are followed by Signal Lab itself, so the URL that asks is the one answered. A challenge from another origin is not answered: credentials typed for one host go to no other. Moving from
http://tohttps://on the same host and default ports counts as the same host.
When the challenge cannot be answered, the 401 stands and the panel says why:
| Message | Meaning |
|---|---|
| The server answered 401 without asking for Digest | The server wants another scheme; try Basic or Bearer. |
| The server asked for Digest with … | An algorithm Signal Lab does not speak; it speaks MD5 and SHA-256. |
| The server asked for Digest without a realm or nonce | The server's challenge is incomplete. |
| The request was sent on to …, which asked for Digest | A redirect led to another origin, whose challenge is not answered. |
Where the credentials go
Credentials go only into the request's Authorization header as it is sent. The Inspector, the console and experiment reports never show that header. On this screen they are kept in memory only and are gone after a restart — unless the request is tied to a saved signal, which brings them back.
WARNING
A request saved as a signal keeps its credentials in the library file, signals.json, as plain text. In an experiment, write a password as {{secret.NAME}} instead; see Data and templates.
Cookies
With Keep cookies on, what a server sets with Set-Cookie is kept in the screen's cookie jar and sent back with later requests to that server, following the browser rules (domain, path, Secure, expiry). The jar is used by this screen's requests, its burst and the HTTP signals you fire from the library. Turn it off to send requests with no cookies and keep none.
The cookies panel under the request and the response lists what the jar holds: Name, Value, Domain and path (a domain starting with . also covers its subdomains), Expires (with the session for a cookie with no expiry) and Flags (Secure, HttpOnly, SameSite). Expired cookies are not listed. Clear empties the jar.
The jar lives as long as the app: a restart starts with an empty one. On a server, there is one jar for every page signed in to it. An experiment run has a jar of its own (see Experiments), and signallab send http uses none.
The response
| Part | What |
|---|---|
| Status | The status code and its reason; ERR when no response came |
| Latency | From sending to the last byte of the body, in milliseconds |
| Size | The size of the body |
| Response headers | Click the line with their count to show or hide them |
| Body | Formatted when it is JSON; Show raw and Format JSON switch. Up to 256 KiB is shown, then … (truncated). |
When there is no response, the panel says why, in the same words as everywhere in Signal Lab: refused, no answer in time, the name does not resolve, a certificate problem and so on. The technical detail from the system is folded under it.
Redirects
Redirects (301, 302, 303, 307, 308) are followed, up to 10; the response shown is the last one. After 301, 302 and 303 the request goes on as GET without a body (HEAD stays HEAD); after 307 and 308 as it was. Authorization and cookies typed for one host are not sent on to another.
Secure connections
An https:// server's certificate is checked against the certificates this system trusts. A self-signed or expired certificate is refused with "A secure connection to … could not be made"; there is no setting to skip the check. To test a server with your own certificate, add it to the system's trusted certificates.
Load burst
The Load burst sends the request on screen — with its authentication and, while Keep cookies is on, the cookie jar — many times, and measures it.
- Set Concurrency, Total, Duration, s and Rate, req/s.
- Press Start burst. The burst is a job: Stop burst, or stopping it in the console strip, ends it.
| Field | What | Default |
|---|---|---|
| Concurrency | Requests in flight at once, 1–512 | 20 |
| Total | Requests to send; 0 — keep sending until the duration ends | 500 |
| Duration, s | Seconds to run; 0 — stop when the total is sent | 0 |
| Rate, req/s | Requests started per second, 0.1–100 000; 0 — as fast as the workers go | 0 |
With both Total and Duration, s at 0, the burst runs until you stop it.
There are two ways to send:
- Rate, req/s 0. Each of the workers sends again as soon as it has an answer. This finds how much the server takes, but a slow server also slows the burst down.
- A rate. The requests start on a fixed schedule — at 10 per second, one every 100 ms from the start — however slow the answers. A request whose moment comes while every worker is busy waits at most 50 ms for one; after that it is skipped and counted as Missed, never sent late. Missed requests mean the concurrency is too low for this rate, or the server is slower than the rate needs.
| Number | What |
|---|---|
| Sent | Requests that have had an answer or failed |
| OK | Answered with a 2xx status |
| Failed | No answer, or any status outside 200–299 |
| Missed | Skipped, as above (only with a rate) |
| RPS | Requests per second over the last tenth of a second; when the burst has ended, over the whole burst. With a rate, the label names the rate asked for. |
| p50, p90, p95, p99 | The time within which that share of the requests finished, failures included; accurate to within 0.5 % |
| Avg, Min, Max | The mean, fastest and slowest |
The numbers are updated about 10 times a second. The chart beside them draws the requests per second over the last 24 seconds or so.
With Digest, the first request's challenge is answered once and that answer serves every request of the burst.
WARNING
A burst is real load. Aim it only at servers you own or are allowed to test.
For ramps, steps, spikes and pass/fail thresholds, run the request under load in an experiment.
In the Inspector
With capture armed, each exchange appears as one frame with the protocol http and the source http: the method, URL, status and time in the summary, the response headers and the start of the body (2000 characters) in its detail, the status as its verdict (failed when no response came, · digest after 401 when a challenge was answered). The frame records the size of the body, not its bytes. The request's Authorization header is never in it. A burst puts at most one exchange every 100 ms into the capture. See Inspector.
Saving and reusing
- Save as a signal. Save… keeps the request — method, URL, headers, body, timeout and authentication — in the signal library. The screen stays tied to it: Save (Ctrl+S) updates it, Save as… copies it, the chip opens it in Signals. Opening an HTTP signal from the library loads it back here, credentials included. See Signals.
- Add to an experiment. Add to experiment adds an HTTP request step with the same request to the open experiment, right before End or after the selected step, and opens it.
- Mock this. Below a response, Mock this makes an emulator route that answers this method and path with this status, headers and body. Choose an HTTP emulator in Add to, or A new emulator, and press Add the route; the route goes first in that emulator, and the Emulators screen opens on it. See Emulators.
In experiments
| Step | What it does |
|---|---|
| HTTP request | Sends a request; its URL, headers, body and credentials take {{templates}}. It can run under load. Details |
| HTTP status, Response text, Response header, Response time | Check the latest response. Details |
| Extract value | Keeps a JSON field, a header, the status, the body or a regular expression's match as a variable. Details |
| Status branch | Goes on through Yes or No by the status. Details |
| Wait for HTTP request | Waits for a request to arrive — from the system you test — at the run's own listener or emulator. Details |
| Emulator | An HTTP API that answers by routes for the whole run. Details |
From the command line
signallab send http sends one request, as this screen does:
signallab send http GET http://127.0.0.1:8080/health --expect-status 200
signallab send http POST http://127.0.0.1:8080/api/items \
-H 'Content-Type: application/json' --body '{"name":"lamp"}'
signallab send http GET http://127.0.0.1:8080/private -u admin:secret --digestThe status line goes to standard error and the body to standard output:
HTTP 200 OK · 3 ms · 15 B
{"status":"ok"}| Option | What | Default |
|---|---|---|
-H, --header 'Name: value' | A header; repeat for more | — |
--body TEXT, --body @FILE | The body, or a file's contents | — |
--expect-status N | Exit 1 unless the status is N | — |
--timeout MS | How long to wait for the response | 10 000 |
-u, --user NAME:PASSWORD | Basic authentication | — |
--digest | With --user: answer the server's Digest challenge instead | — |
--bearer TOKEN | Authorization: Bearer TOKEN | — |
--json | Print the whole response as JSON on standard output | — |
It exits with 0 when a response came (and had the expected status), 1 when none came, the status was not the one expected or a Digest challenge could not be answered, and 2 when an option is invalid. It keeps no cookies. See Command line.
Problems
| What you see | Usual cause |
|---|---|
… refused the connection — nothing is listening on that port | The server is not running, or listens on another port or address. |
No answer from … in time | The server is slow or unreachable; check the address, or raise Timeout (ms). |
Cannot resolve … | The host name does not resolve on this machine — a typo, or a name only another network knows. |
A secure connection to … could not be made | The certificate is not trusted here (self-signed, expired, another name), or TLS failed. See Secure connections. |
… is not a valid address | The URL is malformed or does not start with http:// or https://. |
| The server says the body is missing or of the wrong type | No Content-Type header that matches the body, or an empty body. |
401 with Digest | Read the message under the status: see Digest. |
| Missed above 0 | Raise Concurrency, or lower the rate: the server answers slower than the rate needs. |
| Failed high though the server answers | Every status outside 200–299 counts as failed, 404 and 500 included. |
On a server, requests go out from the server: 127.0.0.1 is the server itself. See Server.
Every error message is listed in Error messages.