Request Echo — product requirements
Request Echo is an HTTP request and response service for API testing. Its endpoints reflect the arguments, headers, body, form fields and cookies they receive, or produce a requested status code, delay, redirect chain, cookie or authentication challenge. A playground builds requests from method, path, query and header grids and several body types, and keeps saved requests per browser tab.
Problem. People who test HTTP clients need a service that answers exactly what was sent or exactly what was asked for. If an echo drops a value, a status is ignored or an auth check is lax, tests built on it give wrong confidence.
Users
- API tester — Send requests and trust that the response reflects them faithfully.
- Client developer — Get predictable statuses, redirects, delays, cookies and auth challenges to exercise error handling.
Goals
- Every echo endpoint reflects what was sent without loss or change.
- Status, delay, redirect, cookie and auth endpoints behave exactly as requested.
- The playground builds the same request the user sees in its grids.
- Invalid input is caught before sending where possible.
Out of scope
- File uploads
- Streaming and gzip endpoints
Contents
Echo endpoints
Method endpoints and /anything reflect the request.
- GET /get?keval=run-4821 returns 200 with Content-Type application/json and args.keval equal to "run-4821".
- url ends with /api/echo/get?keval=run-4821 and headers contains Host.
- /get?keval=demo-123&tag=a&tag=b returns args.keval "demo-123" and args.tag ["a","b"].
- POST {"item":"Notebook","qty":3,"gift":false} returns json equal to that object.
- The X-Request-Id header sent is echoed in headers; headers["Content-Type"] is application/json; method "POST".
- PUT with city=Lyon and zip=69001 returns form {"city":"Lyon","zip":"69001"}, json null, method "PUT" and Content-Type application/x-www-form-urlencoded.
- DELETE /delete with {"id":7} returns 200, json {"id":7} and method "DELETE".
- PATCH /anything/a/b?x=1 with text "hi" returns data "hi", args {"x":"1"} and a url ending /anything/a/b?x=1.
- GET /post returns 404.
- GET /base64/UmVxdWVzdCBFY2hvIHJvY2tz returns 200 with the text "Request Echo rocks".
Status, redirects and delay
Endpoints produce a chosen status code, a redirect chain or a delayed answer.
- /status/201 shows "201 Created"; /status/404 shows "404 Not Found" with an empty body.
- /status/418 shows "418 I'm a teapot" with ASCII art containing "teapot"; /status/503 shows "503 Service Unavailable".
- /status/abc returns 400 with the message "Invalid status code".
- "Redirect ×3" ends 200 OK with "Redirected → /api/echo/get" and a body url ending /api/echo/get.
- The send button shows "Sending…" for about 2 seconds on a 2 second delay.
- The answer is 200 OK and the displayed time is at least 2000 ms.
Authentication challenges
Basic and Bearer endpoints check the credentials sent.
- Correct credentials return 200 {"authenticated":true,"user":<the path user>}.
- A wrong password returns 401 Unauthorized with an empty body.
- Removing the Authorization header returns 401 Unauthorized.
- Authorization "Bearer <token>" returns 200 {"authenticated":true,"token":<that token>}.
- Authorization "Token abc" returns 401 Unauthorized.
Cookies and response headers
Endpoints set and delete cookies and set response headers from the query.
- /cookies/set?flavor=oat&size=xl answers 200 after a redirect with cookies {"flavor":"oat","size":"xl"}.
- /cookies still lists flavor and size.
- /cookies/delete?flavor leaves cookies {"size":"xl"}.
- /response-headers?x-trace=abc123 answers 200 OK and the Headers tab lists x-trace with value abc123.
Playground
The playground builds requests from grids and body editors and saves them per tab.
- Path /get?color=teal&size=9 shows Params badge 2 with rows color=teal and size=9.
- Unticking size makes the Path /get?color=teal and the badge 1.
- Adding key "note" with value "a b&c" makes the Path /get?color=teal¬e=a%20b%26c; the response args is {"color":"teal","note":"a b&c"}.
- {"a": 1,} shows "Body is not valid JSON:" and no new response.
- {"a": 1} returns 200 OK with json {"a":1}.
- The Body tab shows "GET requests are sent without a body." and the body type radios are disabled.
- Saving "Orders lookup" lists it last among 9 saved requests.
- Saving again as "teapot" shows "A saved request named \"teapot\" already exists".
- After a reload "Orders lookup" is still listed; deleting it leaves 8.
HTML order form and catalogue
A classic HTML order form posts to the echo, and a catalogue lists the endpoints.
- Submitting shows JSON whose form has custname "Rae Kim", size "medium", topping ["bacon","mushroom"], delivery "19:30" and comments "Ring twice".
- 22:00 is blocked with a "must be 21:00 or earlier" style message.
- 19:10 is blocked because it is not on a 15-minute step.
- The page reads "21 endpoints".
- Group "Auth" shows "2 endpoints": /basic-auth/{user}/{passwd} and /bearer.
- All groups with search "cookie" shows "3 endpoints".
Non-functional requirements
- Repeated keys, JSON bodies and form fields round-trip unchanged.
Glossary and rules
| Echo | A response that reflects the request that was received. |
|---|---|
| Saved request | A playground request stored for the current browser tab. |