HTTP File Format
t-req parses .http files — a human-readable format for defining HTTP requests. This reference covers the complete syntax.
Request line
Section titled “Request line”Every request starts with a method and URL:
GET https://api.example.com/usersThe HTTP version is optional:
GET https://api.example.com/users HTTP/1.1Supported methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, TRACE, CONNECT.
Request separators
Section titled “Request separators”Use ### to separate multiple requests in a single file:
GET https://api.example.com/users
###
POST https://api.example.com/usersContent-Type: application/json
{"name": "Alice"}Named requests
Section titled “Named requests”Add a name after the separator to identify the request:
### Get all usersGET https://api.example.com/users
### Create userPOST https://api.example.com/usersContent-Type: application/json
{"name": "Alice"}Run a named request with the CLI:
treq run api.http --name "Create user"Comments
Section titled “Comments”Lines starting with # or // are comments (before the request line):
# This is a comment// This is also a commentGET https://api.example.com/usersHeaders
Section titled “Headers”Headers follow the request line, one per line in Name: Value format:
GET https://api.example.com/usersAuthorization: Bearer my-tokenAccept: application/jsonContent-Type: application/jsonHeader names are case-insensitive per HTTP spec.
Request body
Section titled “Request body”Separate the body from headers with a blank line:
POST https://api.example.com/usersContent-Type: application/json
{ "name": "Alice", "email": "alice@example.com"}The body continues until the end of the request block (next ### or end of file).
File references
Section titled “File references”Load the body from an external file with < ./path:
POST https://api.example.com/usersContent-Type: application/json
< ./fixtures/user.jsonPaths are relative to the .http file location.
Variables
Section titled “Variables”Use {{variableName}} to interpolate variables:
GET {{baseUrl}}/users/{{userId}}Authorization: Bearer {{token}}Variables come from:
treq.jsoncconfiguration- Profile-specific overrides
- CLI
--varflags - Programmatic
client.setVariable()
Nested variables
Section titled “Nested variables”Access nested object properties with dot notation:
GET {{baseUrl}}/usersX-User-Id: {{user.id}}X-User-Name: {{user.profile.name}}Resolvers
Section titled “Resolvers”Resolvers provide dynamic values using {{$name()}} syntax:
POST {{baseUrl}}/eventsContent-Type: application/json
{ "timestamp": "{{$timestamp()}}", "secret": "{{$secret(API_KEY)}}"}Built-in resolvers
Section titled “Built-in resolvers”Configure resolvers in treq.jsonc:
{ "resolvers": { "timestamp": { "type": "command", "command": "date +%s" }, "uuid": { "type": "command", "command": "uuidgen" } }}Resolver arguments
Section titled “Resolver arguments”Pass arguments to resolvers:
{{$random(0, 100)}}{{$env(API_KEY)}}{{$secret(DATABASE_PASSWORD)}}Arguments can include variable references:
{{$secret({{secretName}})}}Meta directives
Section titled “Meta directives”Use # @directive value comments to add metadata:
# @name create-user# @description Creates a new user account# @timeout 5000POST {{baseUrl}}/usersContent-Type: application/json
{"name": "Alice"}| Directive | Description |
|---|---|
@name | Request name (alternative to ### Name syntax) |
@description | Human-readable description |
@timeout | Request timeout in milliseconds |
@assert | Inline assertion expression (via @t-req/plugin-assert) |
@sse | Mark request as Server-Sent Events stream |
@lastEventId | Resume from a specific event ID |
Meta directives must appear before the request line.
Inline Assertions (@t-req/plugin-assert)
Section titled “Inline Assertions (@t-req/plugin-assert)”With the assertion plugin enabled, add one or more @assert directives before the request line:
# @assert status == 200# @assert header Content-Type contains application/json# @assert body contains "token"# @assert jsonpath $.token existsGET https://api.example.com/auth/loginAccept: application/jsonSupported assertion targets:
| Target | Operators | Example |
|---|---|---|
status | == != > >= < <= | # @assert status == 200 |
header <name> | exists == != contains | # @assert header X-Trace-Id exists |
body | contains not-contains | # @assert body not-contains "error" |
jsonpath <expr> | exists == != | # @assert jsonpath $.count == 2 |
Invalid or failing assertions cause treq run to exit with code 1.
Server-Sent Events (SSE)
Section titled “Server-Sent Events (SSE)”Mark a request as an SSE stream with the @sse directive:
# @sseGET https://api.example.com/events/streamAuthorization: Bearer {{token}}SSE is also auto-detected from the Accept header:
GET https://api.example.com/events/streamAccept: text/event-streamSSE directives
Section titled “SSE directives”| Directive | Description |
|---|---|
@sse | Mark request as SSE (enables streaming response) |
@timeout | Connection timeout in ms (default: 30000) |
@lastEventId | Resume from event ID (sets Last-Event-ID header) |
Example with all options
Section titled “Example with all options”# @name stockPrices# @sse# @timeout 60000# @lastEventId event-42GET https://api.example.com/prices/streamAuthorization: Bearer {{token}}WebSocket (protocol v1.1)
Section titled “WebSocket (protocol v1.1)”WebSocket request blocks define connection metadata only. Message interaction is runtime-driven through API/SDK clients.
# @ws# @ws-subprotocols graphql-ws,json# @ws-connect-timeout 30000GET wss://api.example.com/graphqlAuthorization: Bearer {{token}}WebSocket is detected by:
@wsdirective, orws:///wss://URL scheme
WebSocket directives
Section titled “WebSocket directives”| Directive | Description |
|---|---|
@ws | Mark request as WebSocket |
@ws-subprotocols | Comma-separated requested subprotocols |
@ws-connect-timeout | Connect timeout in milliseconds |
v1.1 body restriction
Section titled “v1.1 body restriction”WebSocket definitions cannot include:
- inline request body
- body file references (
< ./file) - form-data blocks
The parser still captures raw blocks, but server execution (POST /execute/ws) rejects these with validation errors in protocol 1.1.
Form data
Section titled “Form data”t-req supports a friendly form syntax with name = value on separate lines:
POST {{baseUrl}}/loginContent-Type: application/x-www-form-urlencoded
username = alicepassword = secret123This is automatically detected when all body lines match the name = value pattern.
File uploads
Section titled “File uploads”Upload files in form data with @./path:
POST {{baseUrl}}/uploadContent-Type: multipart/form-data
title = My Documentfile = @./documents/report.pdfCustom filenames
Section titled “Custom filenames”Specify a custom filename with | filename:
POST {{baseUrl}}/uploadContent-Type: multipart/form-data
document = @./report.pdf | annual-report-2024.pdfVariable paths
Section titled “Variable paths”File paths can include variables:
POST {{baseUrl}}/uploadContent-Type: multipart/form-data
file = @{{uploadPath}}URL features
Section titled “URL features”Query parameters
Section titled “Query parameters”Include query parameters directly in the URL:
GET {{baseUrl}}/users?page=1&limit=10&sort=nameOr use variables:
GET {{baseUrl}}/users?page={{page}}&limit={{limit}}Fragments
Section titled “Fragments”URL fragments are preserved:
GET {{baseUrl}}/docs#section-2Specify custom ports:
GET http://localhost:3000/api/usersGET https://api.example.com:8443/secureBasic auth in URL
Section titled “Basic auth in URL”Include credentials in the URL (not recommended for production):
GET https://user:password@api.example.com/privateIPv6 addresses
Section titled “IPv6 addresses”IPv6 addresses use bracket notation:
GET http://[::1]:3000/api/usersGET http://[2001:db8::1]/resourceComplete example
Section titled “Complete example”# User API requests# These requests demonstrate the full .http syntax
### List users# @description Get paginated list of usersGET {{baseUrl}}/users?page={{page}}&limit=10Authorization: Bearer {{token}}Accept: application/json
### Get user by IDGET {{baseUrl}}/users/{{userId}}Authorization: Bearer {{token}}
### Create user# @name create-user# @timeout 5000POST {{baseUrl}}/usersAuthorization: Bearer {{token}}Content-Type: application/json
{ "name": "{{user.name}}", "email": "{{user.email}}", "createdAt": "{{$timestamp()}}"}
### Upload avatarPOST {{baseUrl}}/users/{{userId}}/avatarAuthorization: Bearer {{token}}Content-Type: multipart/form-data
avatar = @./fixtures/avatar.png | profile.png
### Delete userDELETE {{baseUrl}}/users/{{userId}}Authorization: Bearer {{token}}
### Stream events# @sse# @timeout 60000GET {{baseUrl}}/events/streamAuthorization: Bearer {{token}}