Metadata-Version: 2.4
Name: openapi2httpie
Version: 0.1.0
Summary: Convert an OpenAPI/Swagger spec into ready-to-run HTTPie commands or a Postman collection you can import into HTTPie Desktop.
Author: Alessandro
License: MIT
Project-URL: Homepage, https://github.com/AlexDevFlow/openapi2httpie
Project-URL: Issues, https://github.com/AlexDevFlow/openapi2httpie/issues
Keywords: openapi,swagger,httpie,rest,api,cli,postman,codegen
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Code Generators
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: PyYAML>=5.4
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: httpie>=3.2; extra == "dev"
Dynamic: license-file

# openapi2httpie

**Turn an OpenAPI / Swagger spec into ready-to-run [HTTPie](https://httpie.io) commands — or a Postman collection you can import into HTTPie Desktop.**

Point it at a spec, get back a runnable `.sh` file where every endpoint is a clean, copy-pasteable `http` command with real example data, correct auth, and environment-variable placeholders for your secrets.

```console
$ openapi2httpie petstore.yaml
```
```bash
#!/usr/bin/env bash
# Swagger Petstore 1.2.0
# Generated by openapi2httpie
#
# Edit the variables below (or export them beforehand), then run this file.
: "${BASE_URL:=https://api.example.com/v1}"  # API base URL
: "${TOKEN:=REPLACE_ME}"                     # bearer token
: "${X_API_KEY:=REPLACE_ME}"                 # API key (X-API-Key in header)

# GET /users/{id}
# Fetch a user
http --ignore-stdin -A bearer -a "$TOKEN" GET "$BASE_URL/users/0" verbose==true

# POST /users
# Create a user
http --ignore-stdin POST "$BASE_URL/users" "X-API-Key:$X_API_KEY" 'name=Ada Lovelace' age:=0
```

## Why

HTTPie is a joy to use by hand, but nobody wants to hand-write a request for every endpoint of a 200-operation API. Existing generators target the `.http` file format used by IDE REST clients — not HTTPie, and not the terminal. `openapi2httpie` fills that gap, and does the parts those tools skip:

- **Real authentication.** It reads your spec's `securitySchemes` / `securityDefinitions` and per-operation `security`, and emits the *correct* HTTPie form — `-A bearer -a "$TOKEN"`, `-a "$USER:$PASS"`, `X-API-Key:$KEY`, query keys, or cookies.
- **Useful example bodies.** It uses the spec's own `example` / `examples` / `default` / `enum` values, falling back to type- and format-aware placeholders (`user@example.com`, `2024-01-01T00:00:00Z`, a real-looking UUID) — not hollow zeros.
- **Both spec dialects.** Swagger 2.0 **and** OpenAPI 3.0 / 3.1, normalised into one model.
- **Safe by construction.** Every value from the spec is shell-quoted, so example data can never break out of its argument. Generated scripts pass `bash -n`, even with multi-line bodies.

## Install

```bash
pip install openapi2httpie      # or: pipx install openapi2httpie
```

Requires Python 3.9+. The only runtime dependency is PyYAML. (HTTPie itself is only needed to *run* the generated commands.)

## Usage

```console
$ openapi2httpie SPEC [options]
```

`SPEC` can be a file path, an `http(s)://` URL, or `-` for stdin. JSON or YAML.

| Option | Description |
|---|---|
| `-f, --format {httpie,postman}` | Output format (default `httpie`). |
| `-o, --output PATH` | Write to a file (default: stdout). With `--split`, a directory. |
| `--split` | HTTPie only: one script per operation, into the output directory. |
| `--base-url URL` | Override the base URL from the spec. |
| `--offline` | Emit `http --offline` commands (build & print the request, don't send). |
| `--command {http,https}` | HTTPie executable to emit (default `http`). |
| `--all-optional` | Include optional parameters and body properties in the examples. |
| `--no-auth` | Don't emit authentication. |
| `--no-multiline` | Keep each command on one line. |
| `--tag TAG` | Only include operations with this tag (repeatable). |
| `--operation ID` | Only include this `operationId` (repeatable). |

### Examples

```bash
# Whole API to a runnable script
openapi2httpie api.yaml -o api.sh && bash api.sh

# Just the "Pets" tag, previewing requests without sending them
openapi2httpie api.yaml --tag Pets --offline

# One script per endpoint
openapi2httpie api.yaml --split -o ./requests/

# From a live URL, straight into HTTPie
openapi2httpie https://api.example.com/openapi.json | bash
```

### Running the output

The generated script declares its variables with shell defaults, so you can either edit the file or export them first:

```bash
export BASE_URL=https://api.example.com TOKEN=eyJhbGc... 
bash api.sh
```

## HTTPie Desktop / Postman

`--format postman` emits a **Postman Collection v2.1** with native `auth` objects, structured URLs (query params + path variables), tag folders, and JSON bodies:

```bash
openapi2httpie api.yaml -f postman -o api.postman.json
```

HTTPie Desktop can import Postman collections (**File → Import**), so this is the path to get an OpenAPI spec into the Desktop app today. The collection is also a valid Postman/Insomnia import.

> **Note:** HTTPie Desktop's importer is closed-source; this output is built to its published import-compatibility contract. It drops file-upload bodies, folder nesting (flattened to `Folder / Request` names), scripts, and cookies on import — by design. Round-trip a sample through your Desktop version to confirm before relying on it.

## Python API

```python
from openapi2httpie import to_httpie, to_postman, build_model

script = to_httpie("api.yaml")
collection = to_postman("api.yaml", base_url="https://api.example.com")

model = build_model("api.yaml")           # the normalised IR
for req in model.requests:
    print(req.method, req.path, req.label)
```

## How it works

```
spec ──▶ loader ──▶ resolver ──▶ extractor ──▶ ApiModel (IR) ──┬──▶ HTTPie emitter
      (json/yaml,   ($ref,       (normalises 2.0 & 3.x:        │
       dialect      cycle-safe)   params, bodies, auth,        └──▶ Postman emitter
       detect)                    servers, examples)
```

One intermediate model, two emitters. Swagger 2.0 and OpenAPI 3.x differences are absorbed in the extractor, so the emitters never branch on dialect.

## Limitations

- **Array/scalar query params** are emitted as a single example value; HTTPie has no native repeated-key syntax, so multi-value arrays are approximate.
- **Remote `$ref`s** (`$ref` to another URL/file) are not resolved — only local `#/...` references. Bundle your spec first if it uses remote refs.
- **File uploads** in `multipart/form-data` become `field@./path/to/field` placeholders — point them at a real file before running.
- Example bodies are **plausible, not validated** — they satisfy shape and format, not business rules.

## Development

```bash
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest                # 83 tests incl. a real-HTTPie end-to-end suite
```

The test suite includes an end-to-end test that generates a script and runs it with the **real `http` binary** against an in-process mock server, asserting the requests land with the right method, path, query, auth header, and JSON body.

## License

MIT
