A Go library for executing HTTP requests from .http files and validating responses. Write once, use everywhere - for both manual testing and automated E2E tests.
Problem: I wanted to use the same .http files for both manual testing (JetBrains HTTP Client, VS Code REST Client) and automated E2E testing in Go. No existing library offered full compatibility with both environments.
Solution: This library parses .http files exactly like popular IDE extensions, enabling seamless workflow between manual and automated testing.
- Full JetBrains/VS Code compatibility - Same
.httpsyntax, variables, and behaviors - Variable substitution - Custom variables, environment variables, system variables (
{{$guid}},{{$randomInt}}, etc.) - Response chaining - Reference responses from other requests:
{{name.response.body.field}} - Response validation - Compare responses against
.hrespfiles with placeholders ({{$any}},{{$regexp}},{{$anyGuid}}) - Multiple requests per file - Separated by
### - E2E testing ready - Perfect for automated integration tests
.http files are plain text files for defining HTTP requests. They were popularized by JetBrains IDEs (IntelliJ, PyCharm, GoLand) and are now supported by VS Code (REST Client extension) and other tools.
### Request Name
METHOD URL
Header1: value1
Header2: value2
body content@baseUrl = https://api.example.com
@userId = 123
### Get user profile
GET {{baseUrl}}/users/{{userId}}
Authorization: Bearer {{authToken}}
X-Request-ID: {{$guid}}
### Create new user
POST {{baseUrl}}/users
Content-Type: application/json
{
"id": "{{$randomInt 1000 9999}}",
"name": "Test User",
"createdAt": "{{$timestamp}}"
}@baseUrl = https://api.example.com
@userId = 123
### Get User
GET {{baseUrl}}/users/{{userId}}
Authorization: Bearer {{$dotenv TOKEN}}{{$guid}}- UUID (e.g.,123e4567-e89b-12d3-a456-426614174000){{$randomInt}}or{{$randomInt 1 100}}- Random integer{{$timestamp}}- Unix timestamp{{$datetime}}or{{$datetime "2006-01-02"}}- Current datetime{{$processEnv VAR_NAME}}- Environment variable{{$dotenv VAR_NAME}}- From.envfile
{{$randomFirstName}},{{$randomLastName}}{{$randomPhoneNumber}},{{$randomStreetAddress}}{{$randomUrl}},{{$randomUserAgent}}
Reference responses from other requests in the same file:
### Authenticate
POST https://api.example.com/auth
Content-Type: application/json
{"user":"admin","pass":"secret"}
### Get Protected
GET https://api.example.com/protected
Authorization: Bearer {{authenticate.response.body.token}}Go library
go get github.com/bmcszk/go-restclientpackage main
import (
"context"
"log"
"github.com/bmcszk/go-restclient"
)
func main() {
client, _ := restclient.NewClient(
restclient.WithVars(map[string]interface{}{
"authToken": "your-token-here",
}),
)
responses, _ := client.ExecuteFile(context.Background(), "requests.http")
for i, resp := range responses {
if resp.Error != nil {
log.Printf("Request %d failed: %v", i+1, resp.Error)
} else {
log.Printf("Request %d: %d %s", i+1, resp.StatusCode, resp.Status)
}
}
}client, _ := restclient.NewClient(
restclient.WithVars(map[string]interface{}{
"userId": "override-value",
"authToken": "secret-token",
}),
)The restclient CLI runs .http files from the command line.
Install the restclient CLI to run .http files from command line:
go install github.com/bmcszk/go-restclient/cmd/restclient@latestrestclient -f requests.http --all
restclient -f requests.http -n "get user"
restclient -f requests.http -i 0Note: Without -n, -i, or --all, the CLI exits with an error.
restclient -f requests.http --listBy name (case-insensitive):
restclient -f requests.http -n "create user"By 0-based index:
restclient -f requests.http -i 0Override variables from the command line:
restclient -f requests.http -D token=abc123 -D env=prodRun a request before the target (for auth token chaining):
restclient -f requests.http -n "get protected" -A authenticateExit with code 1 on HTTP 4xx/5xx responses:
restclient -f requests.http -E# Body only
restclient -f requests.http -o body
# JSON path extraction
restclient -f requests.http -o jsonpath "data.users[0].name"
# Environment variable format
restclient -f requests.http -o env "token"| Short | Long | Description |
|---|---|---|
-f |
--file |
Request file path (required) |
-n |
--name |
Run request by name |
-i |
--index |
Run request by index |
--all |
Run all requests in file | |
-e |
--expected |
Expected response file |
--e-name |
Expected response name | |
--e-index |
Expected response index | |
-l |
--list |
List requests |
-E |
--fail-on-error |
Fail on 4xx/5xx |
-o |
--output |
Output format |
-A |
--after |
Prerequisite request |
-D |
--define |
Define variable (repeatable) |
Create .hresp files to validate responses:
responses.hresp:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "{{$anyGuid}}",
"name": "{{$any}}",
"createdAt": "{{$anyTimestamp}}"
}
###
HTTP/1.1 201 Created
Content-Type: application/json
{
"id": "{{$regexp `\d{4}`}}",
"status": "created"
}Validate in Go:
err := client.ValidateResponses("responses.hresp", responses...)
if err != nil {
log.Fatal("Validation failed:", err)
}{{$any}}- Matches any text{{$regexp ``pattern``}}- Regex pattern (in backticks){{$anyGuid}}- UUID format{{$anyTimestamp}}- Unix timestamp{{$anyDatetime 'format'}}- Datetime (rfc1123, iso8601, or custom)
client, err := restclient.NewClient(
restclient.WithBaseURL("https://api.example.com"),
restclient.WithDefaultHeader("X-API-Key", "secret"),
restclient.WithHTTPClient(customHTTPClient),
restclient.WithVars(variables),
)Works with files created for:
📚 Complete HTTP Syntax Reference - Comprehensive documentation of all supported HTTP request syntax, variables, and features.
Use your favorite IDE extension to test APIs during development.
func TestUserAPI(t *testing.T) {
client, _ := restclient.NewClient(
restclient.WithBaseURL(testServer.URL),
)
responses, err := client.ExecuteFile(context.Background(), "user_tests.http")
require.NoError(t, err)
err = client.ValidateResponses("user_expected.hresp", responses...)
require.NoError(t, err)
}- Go 1.21+
make check # Run all checks (lint, test, build)MIT License