PHPackages                             lumetas/ht - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. lumetas/ht

ActiveLibrary[HTTP &amp; Networking](/categories/http)

lumetas/ht
==========

HTTP tool for executing requests from .ht files

v0.0.8(3w ago)013↓100%MITPHPPHP &gt;=8.0

Since Feb 28Pushed 3w agoCompare

[ Source](https://github.com/Lumetas/ht)[ Packagist](https://packagist.org/packages/lumetas/ht)[ RSS](/packages/lumetas-ht/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (1)Versions (9)Used By (0)

ht - HTTP Testing Tool
======================

[](#ht---http-testing-tool)

A command-line HTTP client for testing APIs, written in PHP. Inspired by [ht.nvim](https://github.com/lima1909/ht.nvim) (HTTP Toolkit for Neovim).

Features
--------

[](#features)

- Define multiple HTTP requests in a single `.ht` file
- Support for global and local variables
- Variable substitution with `{{variable}}` syntax
- Environment variables support (`$VAR`)
- Command execution in variables (`>command`, `>>command` for cached)
- Pre and Post scripts (full PHP)
- Request chaining with `$api->send()`
- Output control with `$output->write()` and `$output->append()`
- JSON body support
- Headers and query parameters
- Configurable timeout, insecure SSL, proxy
- Script-only requests (requests without URL)
- Immediate request chaining in loops

Installation
------------

[](#installation)

```
chmod +x ht
./ht --help
```

Usage
-----

[](#usage)

```
ht  [requestName]      # Run specific request (body only)
ht -a  [requestName]   # Run with all info (headers, status, etc.)
ht --all  [requestName] # Same as -a
```

If `requestName` is omitted, defaults to `main`.

Output Modes
------------

[](#output-modes)

**Default** (body only):

```
$ ht file.ht myRequest
{"success":true,"data":{"id":1}}
```

**With `-a` flag** (all information):

```
$ ht -a file.ht myRequest
[INFO] Executing: GET https://api.example.com/data

=== Request ===
GET https://api.example.com/data

Headers:
  Content-Type: application/json

Body:
{"key":"value"}
===============

=== Response ===
Status: 200

Headers:
  HTTP/1.1 200 OK
  Content-Type: application/json

Body:
{"success":true,"data":{"id":1}}
===============
```

File Format
-----------

[](#file-format)

### Basic Structure

[](#basic-structure)

```
### #requestName
METHOD https://api.example.com/endpoint
Header-Name: header-value

{
    "body": "json"
}
```

### Comments

[](#comments)

Lines starting with `#` are comments:

```
# This is a comment
### #myRequest
GET https://api.example.com
# Another comment
```

### Variables

[](#variables)

**Global variables** (available to all requests):

```
@baseUrl = https://api.example.com
@apiKey = secret-key

### #main
GET {{baseUrl}}/users
Authorization: Bearer {{apiKey}}
```

**Local variables** (available only in current request, override global):

```
### #getUser
@userId = 123
GET https://api.example.com/users/{{userId}}
```

**Variable types**:

SyntaxDescription`{{variable}}`Regular variable`{{$ENV_VAR}}`Environment variable`{{>command}}`Execute command and use output`{{>>command}}`Execute command, cache result### Configuration

[](#configuration)

Variables starting with `@cfg.` configure the request:

```
@cfg.timeout = 5000      # Timeout in milliseconds
@cfg.insecure = true     # Skip SSL verification
@cfg.dry_run = true      # Don't send request
@cfg.proxy = http://proxy:8080
```

### Headers

[](#headers)

```
### #apiRequest
GET https://api.example.com/data
Content-Type: application/json
Accept: application/json
X-Custom-Header: value
```

### Query Parameters

[](#query-parameters)

```
### #search
GET https://api.example.com/search
name=John
age=30
```

### Request Body

[](#request-body)

```
### #create
POST https://api.example.com/users
Content-Type: application/json

{
    "name": "John",
    "email": "john@example.com"
}
```

Scripts
-------

[](#scripts)

Scripts are written in PHP and executed before or after the request.

### Post-Script (after request)

[](#post-script-after-request)

```
### #login
POST https://api.example.com/login
Content-Type: application/json

{
    "username": "admin",
    "password": "secret"
}

### #loop
GET https://api.example.com/data?count={{counter}}
```

### Script API

[](#script-api)

**$response** (post-script only):

Property/MethodDescription`$response->body`Response body as string`$response->status_code`HTTP status code`$response->headers`Headers as associative array`$response->json_body()`Parse JSON body (cached)**$request** (pre-script only):

Property/MethodDescription`$request->url`Request URL`$request->method`Request method (GET, POST, etc.)`$request->headers`Headers as associative array`$request->body`Request body`$request->query`Query parameters as associative array**$api**:

MethodDescription`$api->set(key, value)`Set global variable`$api->get(key)`Get variable (global or local)`$api->send(name)`Execute another request immediately**$output**:

MethodDescription`$output->write(text)`Replace response body with custom text`$output->append(text)`Add text after response body**Output behavior**:

Mode`write()``append()`No output callWithout `-a`Custom text onlyBody + customBody onlyWith `-a`Full info + customFull info + customFull info**Global functions**:

- `var_dump($var)` - Dump variable
- `print_r($var)` - Print readable
- `json_decode($json, true)` - Parse JSON
- `json_encode($data)` - Encode to JSON

### Request Chaining

[](#request-chaining)

```
### #first
GET https://api.example.com/step1

### #loop
GET https://api.example.com/count?value={{i}}
```

Examples
--------

[](#examples)

### Simple GET

[](#simple-get)

```
@host = jsonplaceholder.org

### #main
GET https://{{host}}/users/1
```

### POST with JSON

[](#post-with-json)

```
### #create
POST https://api.example.com/users
Content-Type: application/json

{
    "name": "John Doe",
    "email": "john@example.com"
}
```

### Authentication Flow

[](#authentication-flow)

```
@host = api.example.com

### #login
POST https://{{host}}/auth/login
Content-Type: application/json

{
    "username": "admin",
    "password": "secret"
}
