pyhttp-app 2.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyhttp/__init__.py +9 -0
- pyhttp/__main__.py +222 -0
- pyhttp/app.py +1333 -0
- pyhttp/assertions.py +289 -0
- pyhttp/cli.py +364 -0
- pyhttp/console.py +82 -0
- pyhttp/curl.py +151 -0
- pyhttp/db.py +1483 -0
- pyhttp/jsengine.py +224 -0
- pyhttp/jsonc.py +54 -0
- pyhttp/mcp.py +316 -0
- pyhttp/mock.py +204 -0
- pyhttp/monitors.py +116 -0
- pyhttp/oauth2.py +153 -0
- pyhttp/openapi.py +365 -0
- pyhttp/pm.js +496 -0
- pyhttp/postman.py +412 -0
- pyhttp/runner.py +1089 -0
- pyhttp/scripts.py +352 -0
- pyhttp/static/app.js +2739 -0
- pyhttp/static/codegen.js +134 -0
- pyhttp/static/editor.js +421 -0
- pyhttp/static/features.css +630 -0
- pyhttp/static/features.js +2396 -0
- pyhttp/static/index.html +372 -0
- pyhttp/static/logo.svg +13 -0
- pyhttp/static/style.css +585 -0
- pyhttp/static/vendor/codemirror.js +28 -0
- pyhttp/static/vendor/fonts/Inter-OFL.txt +93 -0
- pyhttp/static/vendor/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
- pyhttp/static/vendor/fonts/inter-latin-wght-normal.woff2 +0 -0
- pyhttp/static/viewer.js +434 -0
- pyhttp/templating.py +155 -0
- pyhttp/updater.py +387 -0
- pyhttp_app-2.0.1.dist-info/METADATA +654 -0
- pyhttp_app-2.0.1.dist-info/RECORD +40 -0
- pyhttp_app-2.0.1.dist-info/WHEEL +5 -0
- pyhttp_app-2.0.1.dist-info/entry_points.txt +2 -0
- pyhttp_app-2.0.1.dist-info/licenses/LICENSE.md +121 -0
- pyhttp_app-2.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,654 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyhttp-app
|
|
3
|
+
Version: 2.0.1
|
|
4
|
+
Summary: A local, Postman-like HTTP client with a collection runner, scripts and an MCP server
|
|
5
|
+
Author-email: pyhttp Dev Team <dev@pyhttp.com>
|
|
6
|
+
License: # pyhttp Free License 1.1
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 pyhttp Dev Team. All rights reserved.
|
|
9
|
+
|
|
10
|
+
**In short** (this summary is for orientation; the numbered sections are the
|
|
11
|
+
license): pyhttp is free for everyone, at home and at work, at a company of any
|
|
12
|
+
size, for any purpose including commercial use. No fees, no seats, no
|
|
13
|
+
registration, no time limit. You may copy the official release files inside
|
|
14
|
+
your organization and share them unchanged. The source code is published (on
|
|
15
|
+
PyPI as `pyhttp-app`) so You can inspect and install it; You may modify Your
|
|
16
|
+
own copy, but You may not sell pyhttp, distribute a changed version, or present
|
|
17
|
+
a changed version as pyhttp.
|
|
18
|
+
|
|
19
|
+
## 1. Definitions
|
|
20
|
+
|
|
21
|
+
"Licensor" is the pyhttp Dev Team (dev@pyhttp.com), the copyright owner.
|
|
22
|
+
|
|
23
|
+
"Software" is pyhttp as distributed by the Licensor: the Windows installer and
|
|
24
|
+
portable `.exe`, the macOS `.dmg` and Homebrew cask, the Linux `.deb`, the
|
|
25
|
+
Python package the Licensor publishes on PyPI as `pyhttp-app` and the
|
|
26
|
+
Homebrew formula that installs it, the `pyhttp run` command-line runner inside
|
|
27
|
+
them, and every update the Licensor publishes under this license. The PyPI
|
|
28
|
+
package contains the Software's source code, which the Licensor publishes so
|
|
29
|
+
You can inspect and install the Software; that source code is part of the
|
|
30
|
+
Software and covered by this license.
|
|
31
|
+
|
|
32
|
+
"You" is the individual or organization using the Software. For an
|
|
33
|
+
organization, "You" includes its employees and contractors acting on its
|
|
34
|
+
behalf.
|
|
35
|
+
|
|
36
|
+
## 2. License grant
|
|
37
|
+
|
|
38
|
+
Subject to this license, the Licensor grants You a perpetual, worldwide,
|
|
39
|
+
non-exclusive, royalty-free license to install and use any number of copies of
|
|
40
|
+
the Software, on any number of computers, for any purpose, including
|
|
41
|
+
commercial, governmental, educational and nonprofit use.
|
|
42
|
+
|
|
43
|
+
## 3. Sharing the Software
|
|
44
|
+
|
|
45
|
+
You may copy and share **unmodified** official release files free of charge:
|
|
46
|
+
inside your organization (for example through a software catalog or device
|
|
47
|
+
management), with other people, and through package managers and download
|
|
48
|
+
sites, as long as You keep this license and all notices with the files and do
|
|
49
|
+
not present the Software as your own work. You may not charge for the Software,
|
|
50
|
+
bundle it in a product or service that is sold, or offer it to third parties as
|
|
51
|
+
a hosted service.
|
|
52
|
+
|
|
53
|
+
## 4. Restrictions
|
|
54
|
+
|
|
55
|
+
Except where applicable law expressly allows it despite this term, You may not:
|
|
56
|
+
|
|
57
|
+
- distribute a modified version of the Software, or present a modified version
|
|
58
|
+
as pyhttp (You may modify Your own copy of the published source code for
|
|
59
|
+
Your own use; distributing or publishing those changes is not allowed);
|
|
60
|
+
- decompile, disassemble or reverse engineer the compiled builds of the
|
|
61
|
+
Software (the source code is published on PyPI, so there is no need to);
|
|
62
|
+
- remove or alter copyright, trademark or license notices;
|
|
63
|
+
- rent, lease, sell or sublicense the Software; or
|
|
64
|
+
- use the pyhttp name or logo for anything other than the unmodified Software
|
|
65
|
+
(for example for a modified build or a different product).
|
|
66
|
+
|
|
67
|
+
Interacting with the Software through its documented HTTP API, command line,
|
|
68
|
+
import/export formats and scripting hooks is allowed and encouraged.
|
|
69
|
+
|
|
70
|
+
## 5. Third-party components
|
|
71
|
+
|
|
72
|
+
The Software bundles open-source components listed in
|
|
73
|
+
THIRD-PARTY-NOTICES.md. Those components remain under their own licenses, which
|
|
74
|
+
take precedence over this license for those components.
|
|
75
|
+
|
|
76
|
+
## 6. Updates, add-ons and future editions
|
|
77
|
+
|
|
78
|
+
Updates the Licensor publishes for the Software are covered by this license.
|
|
79
|
+
The Licensor may offer optional paid add-ons, services or editions under
|
|
80
|
+
separate terms; buying them is never required to keep using the Software under
|
|
81
|
+
this license.
|
|
82
|
+
|
|
83
|
+
## 7. Your data
|
|
84
|
+
|
|
85
|
+
The Software runs on your computer and stores your data there. It does not
|
|
86
|
+
collect telemetry. Its only network traffic is the requests You send with it,
|
|
87
|
+
plus a check of the public releases page for new versions, which You can turn
|
|
88
|
+
off in Settings.
|
|
89
|
+
|
|
90
|
+
## 8. Ownership
|
|
91
|
+
|
|
92
|
+
The Software is licensed, not sold. The Licensor keeps all rights not expressly
|
|
93
|
+
granted here, including all copyright, trademark and other intellectual
|
|
94
|
+
property rights in the Software.
|
|
95
|
+
|
|
96
|
+
## 9. Term and termination
|
|
97
|
+
|
|
98
|
+
This license lasts until terminated. It ends automatically if You breach it;
|
|
99
|
+
You may also end it at any time by deleting all copies. When it ends You must
|
|
100
|
+
stop using the Software and delete your copies. Sections 5, 8, 10, 11 and 12
|
|
101
|
+
survive termination.
|
|
102
|
+
|
|
103
|
+
## 10. No warranty
|
|
104
|
+
|
|
105
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
106
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
107
|
+
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. The Licensor does
|
|
108
|
+
not promise that the Software is error-free or will be maintained.
|
|
109
|
+
|
|
110
|
+
## 11. Limitation of liability
|
|
111
|
+
|
|
112
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE LICENSOR IS NOT LIABLE FOR ANY
|
|
113
|
+
INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR PUNITIVE DAMAGES, OR FOR LOSS
|
|
114
|
+
OF DATA, PROFITS OR BUSINESS, ARISING FROM THE SOFTWARE OR THIS LICENSE, EVEN IF
|
|
115
|
+
ADVISED OF THE POSSIBILITY. THE LICENSOR'S TOTAL LIABILITY UNDER THIS LICENSE IS
|
|
116
|
+
LIMITED TO USD 10. Some jurisdictions do not allow these limits; there, they
|
|
117
|
+
apply to the fullest extent permitted.
|
|
118
|
+
|
|
119
|
+
## 12. General
|
|
120
|
+
|
|
121
|
+
This license is governed by the laws of India, and disputes go to the courts
|
|
122
|
+
there, unless the law of your place of residence gives You rights that cannot
|
|
123
|
+
be waived. If any part of this license is unenforceable, the rest remains in
|
|
124
|
+
effect. This license is the entire agreement about the Software and replaces
|
|
125
|
+
every earlier pyhttp license for the releases that ship with it. Questions:
|
|
126
|
+
dev@pyhttp.com.
|
|
127
|
+
|
|
128
|
+
Project-URL: Homepage, https://pyhttp.com
|
|
129
|
+
Keywords: http,api,client,postman,rest,testing,mcp
|
|
130
|
+
Classifier: Development Status :: 4 - Beta
|
|
131
|
+
Classifier: Environment :: Web Environment
|
|
132
|
+
Classifier: Intended Audience :: Developers
|
|
133
|
+
Classifier: Operating System :: OS Independent
|
|
134
|
+
Classifier: Programming Language :: Python :: 3
|
|
135
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
136
|
+
Classifier: Topic :: Software Development :: Testing
|
|
137
|
+
Requires-Python: >=3.10
|
|
138
|
+
Description-Content-Type: text/markdown
|
|
139
|
+
License-File: LICENSE.md
|
|
140
|
+
Requires-Dist: fastapi>=0.110
|
|
141
|
+
Requires-Dist: uvicorn>=0.27
|
|
142
|
+
Requires-Dist: httpx>=0.27
|
|
143
|
+
Requires-Dist: pywebview>=5.0
|
|
144
|
+
Requires-Dist: quickjs>=1.19; python_version < "3.13"
|
|
145
|
+
Requires-Dist: mini-racer>=0.12; python_version >= "3.13"
|
|
146
|
+
Requires-Dist: pyyaml>=6.0
|
|
147
|
+
Requires-Dist: mcp>=2
|
|
148
|
+
Dynamic: license-file
|
|
149
|
+
|
|
150
|
+
cd C:\Users\vishv\Documents\www\pyhttp\
|
|
151
|
+
C:\Users\vishv\Documents\www\pyhttp\pyhttp\
|
|
152
|
+
claude --dangerously-skip-permissions
|
|
153
|
+
# todo
|
|
154
|
+
- kill port
|
|
155
|
+
lsof -t -i:8765 | xargs kill -9
|
|
156
|
+
|
|
157
|
+
<!-- - both show waiting while running in parallel -->
|
|
158
|
+
<!-- - pretty/ raw bar with response must not scroll with response - fix that
|
|
159
|
+
- in headers give select all/unselect all button or checkbox
|
|
160
|
+
- auto dropdown in Token from env/global variables
|
|
161
|
+
- if get method gives error show prompt or Tip: that use post or any other method method
|
|
162
|
+
- observed a weird bug that body 1 somehow was doing conflict with body 2, when only sending body 2 getting same error that i must see in body 1 for the response in body 2 can you check this and fix if any such issue can happen -->
|
|
163
|
+
|
|
164
|
+
<!-- - automatic api tester with a timer, where it will send an report of times and alert if failed api api -->
|
|
165
|
+
<!-- - give mcp so this tool data like api body and etc can be filled and managed by ai , make this fully manageable tool by using ai -->
|
|
166
|
+
- Later build feedback form in www /Users/vishvendra/Documents/www/pyhttp.com and app /Users/vishvendra/Documents/www/pyhttp/
|
|
167
|
+
- seo
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
<!-- - update www with all the updates we just made -->
|
|
171
|
+
<!-- - delete all older releases with my name vishvendra singh if possible but keep the release 1.9 and after -->
|
|
172
|
+
<!-- - if response is pushed to bottom by down button to view body the body and and list of bodies component must stretch to the bottm will the response window right now it remains sname, also when click the button to bring the response from bottom to the right it hides body and if i try to click the separator and drag it shows weird behaviour and does not work properly fix these issues and make it better -->
|
|
173
|
+
<!-- - dependent api - like token triggered automatically when any api is sent a call, so fetch token from using token api, where it will have a pm.environment.set(token) something like this - so it will set token in environment automatically and then call the pi - if put in as dependent api in any other api and set a time after which it must trigger automatically - like token has expired time - implement intelligently in a flow -->
|
|
174
|
+
<!-- - remove my name and keep something like - "pyhttp Dev team - From the unknown to the unowned" like this - in tagline and owner etc at all the palces in website and tool in current or next releases -->
|
|
175
|
+
<!-- - lets say if there are multiple bodies in api then in scripts i want to give an option to select from - perform test and Pre-request based on bodies 1 or 2 or 3 etc (name of body) so user can select if same test are to be perfomed for all bodies or different - pre-request and test - for each body - i told you to do this before but not able to see or find this change -->
|
|
176
|
+
<!-- - run with csv - give sample file, also show multiple or single responses in api beside/below api definition or body for each run automatically -->
|
|
177
|
+
<!-- - in current run on right hand side - write name of files in pop when clicked the tab - with little description, right now it is confusing - as user not understanding difference between api.json and api.body.json - do this change quickly and dont spend too much testing on it or build or relese there are more chaning i will be sending then test or do any other process afterward when i tell you -->
|
|
178
|
+
<!-- - highly parallel request without sequence or allow to set in while trying to run on run name and confirmation screen also give button to skip and run directly without giving name -->
|
|
179
|
+
<!-- - make default useragent - pyhttp and version -->
|
|
180
|
+
<!-- - vertical partition compresses the search input box and "run selected" button which does not look good fix that on left hand side - fix ui/ux -->
|
|
181
|
+
<!-- - settings menu seems like falling over each other give spacing and make better ui/ux -->
|
|
182
|
+
<!-- - below button in bottom movies response window, can make this clearer so one can easily know what that button does or any other why make it easy ui/ux -->
|
|
183
|
+
<!-- - put a hamburger menu on left hand side to show hide left hand sidebar -->
|
|
184
|
+
<!-- - when there is an long error from api shown above the json response it adds horizontal scroller, i think you must text wrap that and must not add horizontal scroll in any case -->
|
|
185
|
+
<!-- - tabs like api or body have very little vertical scroll, i think you must not show scroll anywhere instead put tabs above or below - and/or give this setting to set for user -->
|
|
186
|
+
<!-- - rename Tests to scripts and there must be option to select body and apply test to that specific body or all body and separate test can be applied to separate bodies -->
|
|
187
|
+
<!-- work on all of above intelligently and in such a way must be best decision from your research i want to make best http tool as per ui/ux and ease of use point of view -->
|
|
188
|
+
<!-- - also i am thinking to make it free in license for everyone - what do you think - -->
|
|
189
|
+
<!-- - if i click on any other tab it selects all the bodies, but it must save the state like selected body only even when tabs are changes or this app is opened or closed -->
|
|
190
|
+
<!-- - give cancel button in place of sending when sending api call to cancel running call/calls -->
|
|
191
|
+
<!-- - give select and enclose/open javascript with arrow in left beside line numbers -->
|
|
192
|
+
<!-- - ctrl+enter in windows and command+enter must send it api call -->
|
|
193
|
+
<!-- - clicking tabs must not change the box/card size in settings -->
|
|
194
|
+
<!-- - close icon/button foer current/history right side bar -->
|
|
195
|
+
<!-- - open/cose button for response bar, i mean hide it so one can view entire body similar for response there must option to maximize it to view entire response -->
|
|
196
|
+
<!-- - must be able to move tabs left and right -->
|
|
197
|
+
<!-- - check now must show loading icon and show status beside that only -->
|
|
198
|
+
<!-- - current run and history not showing in mac/windows -->
|
|
199
|
+
<!-- - auto release not working -->
|
|
200
|
+
<!-- - instead of pm.test make it ph or py.test which you feel is good, i feel py. is good in Tests
|
|
201
|
+
- pretty is showing too much space after each line in response of json
|
|
202
|
+
- in tests i keep getting error - invalid systax ("<test script>", line 1) and failing in setting any variables -->
|
|
203
|
+
# pyhttp
|
|
204
|
+
|
|
205
|
+
A local, Postman-like HTTP client with a built-in collection runner, in its
|
|
206
|
+
own desktop window. Everything stays on your machine: requests live in a SQLite
|
|
207
|
+
file, every run writes its responses to plain files, and the backend listens
|
|
208
|
+
only on `127.0.0.1`.
|
|
209
|
+
|
|
210
|
+
## Features
|
|
211
|
+
|
|
212
|
+
- Save requests with **name, description, tags**, method, URL, query params,
|
|
213
|
+
headers, body (JSON / text / XML / form), timeout and SSL verification.
|
|
214
|
+
- **Autosave**: every edit, new body or pasted JSON is saved half a second after
|
|
215
|
+
you stop typing. The header shows *Saving… / Saved*; Ctrl/Cmd+S saves at once.
|
|
216
|
+
- **Bulk edit** for headers, params and variables: one `key: value` per line,
|
|
217
|
+
`//` at the start of a line disables it, and a pasted `?a=1&b=2` query string
|
|
218
|
+
becomes separate params.
|
|
219
|
+
- Each request in the sidebar has a **⋯ menu** (or right-click) with Duplicate
|
|
220
|
+
and Delete.
|
|
221
|
+
- Compact editor: method, URL and Send sit at the top. Tags and description
|
|
222
|
+
live behind **Details** and show as small chips when collapsed.
|
|
223
|
+
- **Named bodies**: a request can hold many bodies, each with its own name
|
|
224
|
+
(for example `valid user`, `missing email`). Search bodies by name or content,
|
|
225
|
+
and tick the ones to send. **Send** hits the request once per checked body and
|
|
226
|
+
saves every output to a run folder, with the body name in the file names.
|
|
227
|
+
- **Search** across name, description, URL, tags and body names; filter by tag chips.
|
|
228
|
+
- **Monitors** (topbar → Monitors): picked requests are sent again every N
|
|
229
|
+
minutes while the app is open. A check fails when a request errors, answers
|
|
230
|
+
4xx/5xx or fails a test; failing monitors show in the status bar and can POST
|
|
231
|
+
to a webhook. "Run now" sends a check at once.
|
|
232
|
+
- **Mock servers** (topbar → Mocks): fake endpoints answered by pyhttp itself,
|
|
233
|
+
**on the port it already runs on** — `http://127.0.0.1:8765/mock/<name>/…`, with
|
|
234
|
+
no second process to start. Give a route a method, a path (`/users/:id`), a
|
|
235
|
+
status and a body, and point your front end, a test or another request at it.
|
|
236
|
+
See *Mock servers* below.
|
|
237
|
+
- **Streamed responses**: tick *Stream the response live* in a request's
|
|
238
|
+
Settings tab for Server-Sent Events, chunked and AI-style streaming endpoints —
|
|
239
|
+
the body shows as it arrives, and Cancel stops the stream but keeps what came.
|
|
240
|
+
- **Keyboard first**: ↑/↓ move through the sidebar, Enter opens, Space ticks for
|
|
241
|
+
a run, Delete removes. Deleting a request or body is **undoable** for a few
|
|
242
|
+
seconds from the toast.
|
|
243
|
+
- **Folders**: organise requests in nested folders (for example `QA`, `Prod`,
|
|
244
|
+
`QA / Users`). Drag requests or folders onto a folder, or use the ⋯ menu:
|
|
245
|
+
Add request, Add folder, Run folder, Rename, Move, Delete. Ticking a folder
|
|
246
|
+
selects every request inside it for a run.
|
|
247
|
+
- **Environments**: create Dev, QA, Staging, Prod (one click each) or your own.
|
|
248
|
+
Each has its own variables, which override the global ones while it is active.
|
|
249
|
+
Switch from the selector in the top bar; Prod is highlighted in red. Runs
|
|
250
|
+
record which environment they used. Mark a variable **secret** (🔒) and its
|
|
251
|
+
value is masked on screen and replaced by `••••••` in the saved history and run
|
|
252
|
+
files (Postman's `secret` type is kept on import and export).
|
|
253
|
+
- In-app dialogs for every confirmation (no browser pop-ups); Escape cancels,
|
|
254
|
+
Enter confirms.
|
|
255
|
+
- **Select many** requests, reorder them, and **run them one by one**.
|
|
256
|
+
Progress shows live; each response is stored in the run's output folder.
|
|
257
|
+
- **Variables**: `{{base_url}}` anywhere in URL, params, headers or body.
|
|
258
|
+
Global variables apply everywhere; the active environment overrides them.
|
|
259
|
+
- **Chaining**: inside a run, `{{prev.json.token}}`, `{{prev.status}}`,
|
|
260
|
+
`{{prev.body}}` and `{{prev.headers.content-type}}` read the previous response.
|
|
261
|
+
- Run history, cancel, stop-on-failure, delay between requests.
|
|
262
|
+
- Import / export the whole collection as JSON, including folders and
|
|
263
|
+
environments. Import asks whether to add to or replace your collection.
|
|
264
|
+
- **Body editor** (CodeMirror): line numbers, code folding, bracket matching,
|
|
265
|
+
syntax colours, `Ctrl+/` comments a line out (removed before the request is
|
|
266
|
+
sent, like Postman), Tab indents, `Ctrl+B` beautifies and keeps your comments,
|
|
267
|
+
and a live status line says "Valid JSON" or points at the broken line.
|
|
268
|
+
- **Response viewer**: a collapsible, colour-coded JSON tree (click a key to copy
|
|
269
|
+
its path), Raw and Preview (HTML, images, PDF) views, wrap toggle, a path filter
|
|
270
|
+
(`data.items[*].id`) and `Ctrl+F` search with match count. Save the body to a file.
|
|
271
|
+
- **Auth tab**: Basic, Bearer, API key (header or query), Digest, **OAuth 2.0**
|
|
272
|
+
(client credentials or password grant: the token is fetched on the first send,
|
|
273
|
+
cached until it expires, refreshed with the refresh token, and fetched again
|
|
274
|
+
after a `401`; *Get new token* shows its status), or inherit from the folder. Folders have their own settings (auth, headers, variables) that
|
|
275
|
+
every request inside inherits.
|
|
276
|
+
- **Body types**: JSON, text, XML, HTML, JavaScript, form (key/value rows),
|
|
277
|
+
form-data with file fields, binary file, GraphQL (query + variables).
|
|
278
|
+
- **Scripts tab** (Pre-request and Post-response, like Postman): **tests without
|
|
279
|
+
code** (status, header, body, JSON path and response-time assertions; results in
|
|
280
|
+
the response's Tests tab and in run reports), each for all bodies or for one named
|
|
281
|
+
body; **extract** values from a response into environment or global variables
|
|
282
|
+
(`{{token}}` in the next request); **pre-request variables**; and **scripts** in
|
|
283
|
+
JavaScript with Postman's `pm` API (`pm.test`, `pm.expect`, `pm.response`,
|
|
284
|
+
`pm.environment.set`…) so Postman scripts run unchanged, or in Python with a `py`
|
|
285
|
+
object. `{{body_name}}` (also `body_name` in scripts) tells which body is being sent.
|
|
286
|
+
With several bodies, each script editor has a **for** picker: write a script for
|
|
287
|
+
*All bodies* or for one named body; a body's own pre-request / test script runs
|
|
288
|
+
after the all-bodies one, only when that body is sent.
|
|
289
|
+
- **Dependent requests**: in a request's Settings tab, pick another request to
|
|
290
|
+
send first (typically one that fetches a token and saves it with an
|
|
291
|
+
extraction or `pm.environment.set`), and how long its result stays valid.
|
|
292
|
+
The token request runs before the first send, is reused until it expires,
|
|
293
|
+
is fetched once even for parallel sends, and is refreshed automatically with
|
|
294
|
+
one retry when the dependent request comes back 401 or 403.
|
|
295
|
+
- **Dynamic variables**: `{{$guid}}`, `{{$timestamp}}`, `{{$isoTimestamp}}`,
|
|
296
|
+
`{{$randomInt 1 100}}`, `{{$randomEmail}}`, `{{$date}}` and more. Path
|
|
297
|
+
variables (`/users/:id`) get their value from a Params row. Unresolved
|
|
298
|
+
variables are flagged before sending.
|
|
299
|
+
- **Code snippets** (`</>`): cURL, Python (requests, httpx), JavaScript fetch,
|
|
300
|
+
Node axios, PowerShell, raw HTTP, Go, with variables and auth resolved.
|
|
301
|
+
- **Import** Postman Collection v2.1 files and Postman environments, **OpenAPI 3 /
|
|
302
|
+
Swagger 2** specs (JSON or YAML: one folder per tag, `{{baseUrl}}` from the
|
|
303
|
+
servers, bodies from examples and schemas, auth from the security schemes),
|
|
304
|
+
browser **HAR** files, or paste a `curl` command. **Export** as a Postman
|
|
305
|
+
collection (whole collection or one folder).
|
|
306
|
+
- **Tabs** for open requests (Ctrl+W closes) and drag to **reorder** requests
|
|
307
|
+
and folders.
|
|
308
|
+
- **History** in the right-hand panel: **Run history** lists collection runs,
|
|
309
|
+
**Request history** every single request sent. Filter it by text or by status
|
|
310
|
+
(2xx, 3xx, 4xx, 5xx, errors), send an entry again with one click (↻), reopen
|
|
311
|
+
its response, open a copy as a new request, or **compare** two entries (status,
|
|
312
|
+
time, size, and a line diff of body, headers and request; JSON keys are sorted
|
|
313
|
+
so only real changes show).
|
|
314
|
+
- **Split panes**: the request editor and the response are two panes that scroll
|
|
315
|
+
on their own, so the URL, the tabs and the response status always stay in view.
|
|
316
|
+
Drag the edge between them (and the edges of the sidebar and the right-hand panel)
|
|
317
|
+
to resize; double-click an edge to reset. The response goes **below** the request
|
|
318
|
+
or to its **right**: switch in the status bar ("Response: below | right"), with the
|
|
319
|
+
button in the response header, or in Settings. The sidebar hides behind the
|
|
320
|
+
**☰** button (Ctrl/Cmd+\). Errors wrap instead of scrolling sideways.
|
|
321
|
+
- **Cookie jar** like a browser: cookies are stored per domain, sent on later
|
|
322
|
+
requests, listed in a Cookies response tab and editable in a manager.
|
|
323
|
+
- **Runner options**: iterations, a CSV/JSON **variables file** (one row of
|
|
324
|
+
variable values per iteration, columns as `{{variables}}`; the run dialog
|
|
325
|
+
offers a sample file with a column for each variable your requests use, to
|
|
326
|
+
download or to run with), failing
|
|
327
|
+
tests fail the run, "failed only" filter, HTML/JSON run report. While a run
|
|
328
|
+
goes, every request it sends shows its responses beside the request: one tab
|
|
329
|
+
per body and iteration, so you can compare them without opening the report.
|
|
330
|
+
- **Settings**: follow redirects, max redirects, proxy with bypass list, client
|
|
331
|
+
certificates per host, default timeout, User-Agent (default `pyhttp/<version>`), editor font size, response
|
|
332
|
+
below or beside the request, and in-app updates (the Windows builds and Homebrew installs update themselves, see *Updates* below).
|
|
333
|
+
- Native desktop window using the OS webview (WebView2 / WKWebView / WebKitGTK),
|
|
334
|
+
with native save/open dialogs for export and import.
|
|
335
|
+
- No Node, no Electron, no build step to run it. Python 3.10+ only (the editor is a
|
|
336
|
+
prebuilt CodeMirror bundle checked into the repo).
|
|
337
|
+
|
|
338
|
+
## Mock servers
|
|
339
|
+
|
|
340
|
+
An API you need does not exist yet, or you want it to fail on demand. Open
|
|
341
|
+
**Mocks** in the top bar, add a mock server, and give it routes. They are
|
|
342
|
+
answered by pyhttp itself on the port it already listens on, so there is no
|
|
343
|
+
second server to start and no second port to remember:
|
|
344
|
+
|
|
345
|
+
```
|
|
346
|
+
http://127.0.0.1:8765 + /mock + /payments-api + /users/42
|
|
347
|
+
└ wherever pyhttp runs ┘ └ the mock ┘ └ the route ┘
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
- **Routes** are a method, a path, a status, headers and a body. A path may hold
|
|
351
|
+
parameters written either way (`/users/:id` or `/users/{id}`); `*` matches one
|
|
352
|
+
segment and `**` the rest of the path. `ANY` answers every method. Exact paths
|
|
353
|
+
win over parameter ones, so `/users/me` and `/users/:id` can live side by side.
|
|
354
|
+
- **The body is a template**, so a route can answer differently every time and can
|
|
355
|
+
read the call it is answering:
|
|
356
|
+
`{{req.params.id}}` (a path parameter), `{{req.query.limit}}`,
|
|
357
|
+
`{{req.headers.x-key}}`, `{{req.body}}`, `{{req.json.user.name}}`,
|
|
358
|
+
`{{req.method}}`, `{{req.path}}` — plus your own `{{variables}}` and the
|
|
359
|
+
dynamic ones (`{{$guid}}`, `{{$randomEmail}}`…).
|
|
360
|
+
- **One path, several answers**: give a route a query condition (`fail=1`) and it
|
|
361
|
+
only answers calls that carry it, so the happy path and the 500 can share
|
|
362
|
+
`/payments/:id`. A route with a condition wins over one without.
|
|
363
|
+
- **Delays** per server and per route, to see how your app behaves on a slow API.
|
|
364
|
+
- **CORS** headers and preflight (`OPTIONS`) answers are sent by default, so a
|
|
365
|
+
browser app on another origin can call the mock.
|
|
366
|
+
- **Calls**: every request a mock answered, newest first, with the headers and
|
|
367
|
+
body it arrived with and which route matched — the quickest way to see what
|
|
368
|
+
your app is really sending. Unmatched calls are flagged, and a 404 from a mock
|
|
369
|
+
lists the routes it does know.
|
|
370
|
+
- **From requests…** builds one route per request you already have, answering
|
|
371
|
+
with the response that request last gave.
|
|
372
|
+
- **Try** opens a route as a normal request, with the URL written as
|
|
373
|
+
`{{mock_url}}/<name>/…`. `{{mock_url}}` is this app's own `/mock` base, so such
|
|
374
|
+
requests keep working whichever port the app got.
|
|
375
|
+
- `GET /mock` lists what is being mocked on this port, for a quick look from
|
|
376
|
+
`curl` or a browser.
|
|
377
|
+
|
|
378
|
+
Mocks live in the same SQLite file as everything else, and are not part of the
|
|
379
|
+
collection export.
|
|
380
|
+
|
|
381
|
+
## Run it
|
|
382
|
+
|
|
383
|
+
Requires Python 3.10 or newer.
|
|
384
|
+
|
|
385
|
+
**Any OS, with pip** (the PyPI name is `pyhttp-app`; the command stays `pyhttp`):
|
|
386
|
+
|
|
387
|
+
```sh
|
|
388
|
+
pip install pyhttp-app # or: pipx install pyhttp-app
|
|
389
|
+
pyhttp
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
On Linux, install the GTK webview bindings first (see *Linux* below) or use
|
|
393
|
+
`pyhttp --browser`. `brew install pyhttp2/pyhttp/pyhttp-app` installs the
|
|
394
|
+
same package through Homebrew (macOS and Linux, Intel and ARM).
|
|
395
|
+
|
|
396
|
+
**Windows**: double-click `run.bat`. The window opens without a console.
|
|
397
|
+
WebView2 ships with Windows 10/11.
|
|
398
|
+
|
|
399
|
+
**macOS**:
|
|
400
|
+
|
|
401
|
+
```sh
|
|
402
|
+
chmod +x run.sh
|
|
403
|
+
./run.sh
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
**Linux**: Ubuntu/Debian users can install the `.deb` instead (see *Desktop apps*).
|
|
407
|
+
From source, install the GTK webview bindings once, then use `run.sh`.
|
|
408
|
+
|
|
409
|
+
```sh
|
|
410
|
+
sudo apt install python3-gi gir1.2-webkit2-4.1 # Debian / Ubuntu
|
|
411
|
+
sudo dnf install python3-gobject webkit2gtk4.1 # Fedora
|
|
412
|
+
chmod +x run.sh
|
|
413
|
+
./run.sh
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
The scripts create a `.venv` on first start and reinstall dependencies
|
|
417
|
+
whenever `requirements.txt` changes.
|
|
418
|
+
|
|
419
|
+
### Modes
|
|
420
|
+
|
|
421
|
+
```sh
|
|
422
|
+
python -m pyhttp # native window (default)
|
|
423
|
+
python -m pyhttp --browser # open in your web browser at http://127.0.0.1:8765/
|
|
424
|
+
python -m pyhttp --server # API only, for scripting
|
|
425
|
+
python -m pyhttp --debug # native window with devtools
|
|
426
|
+
python -m pyhttp --data-dir PATH # keep data somewhere else
|
|
427
|
+
python -m pyhttp mcp # MCP server on stdio, so AI tools can drive pyhttp
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
If no native webview is available, pyhttp prints why and falls back to the
|
|
431
|
+
browser automatically.
|
|
432
|
+
|
|
433
|
+
### Headless runs for CI
|
|
434
|
+
|
|
435
|
+
`pyhttp run` runs requests without the UI, prints each result, writes reports and
|
|
436
|
+
exits with `0` when everything passed, `1` when something failed and `2` for usage
|
|
437
|
+
errors, like Postman's newman.
|
|
438
|
+
|
|
439
|
+
```sh
|
|
440
|
+
python -m pyhttp run # every request in your collection
|
|
441
|
+
python -m pyhttp run "API/Users" Login --env QA # folders (name or path) and requests (name or id)
|
|
442
|
+
python -m pyhttp run collection.json --env-file qa.postman_environment.json
|
|
443
|
+
python -m pyhttp run openapi.yaml --var baseUrl=http://localhost:8000 --list
|
|
444
|
+
python -m pyhttp run --tag smoke -n 3 --data users.csv --bail \
|
|
445
|
+
--junit out/junit.xml --html out/report.html --json out/results.json
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
A collection file (Postman v2.1, pyhttp export, OpenAPI, HAR) is run from a
|
|
449
|
+
throwaway data folder, so your own collection is not touched. Other options:
|
|
450
|
+
`--delay MS`, `--insecure`, `--timeout S`, `--no-fail-on-http-error`,
|
|
451
|
+
`--no-fail-on-tests`, `-q`, `--no-color`. Runs started from the command line also
|
|
452
|
+
appear in the app's Run history. See `python -m pyhttp run --help`.
|
|
453
|
+
|
|
454
|
+
### MCP server (AI tools drive pyhttp)
|
|
455
|
+
|
|
456
|
+
`python -m pyhttp mcp` serves the collection over the
|
|
457
|
+
[Model Context Protocol](https://modelcontextprotocol.io) on stdio: an AI tool
|
|
458
|
+
can list, create and edit requests, send them, run folders or tags like the
|
|
459
|
+
collection runner, read history, switch environments and set variables. Every
|
|
460
|
+
tool goes through the same code path as the UI, and the data folder is shared
|
|
461
|
+
with the app, so both can be open at the same time.
|
|
462
|
+
|
|
463
|
+
```sh
|
|
464
|
+
claude mcp add pyhttp -- python -m pyhttp mcp # Claude Code
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
```json
|
|
468
|
+
{ "mcpServers": { "pyhttp": { "command": "python", "args": ["-m", "pyhttp", "mcp"] } } }
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
## Where data goes
|
|
472
|
+
|
|
473
|
+
```
|
|
474
|
+
data/
|
|
475
|
+
pyhttp.db # requests, folders, environments, variables, run history (SQLite)
|
|
476
|
+
outputs/
|
|
477
|
+
2026-10-07_18-30-00_smoke/ # one folder per run
|
|
478
|
+
summary.json # run status + one line per request
|
|
479
|
+
01_login.json # full detail: resolved request, headers, body, timing
|
|
480
|
+
01_login.body.json # raw response body (extension follows content-type)
|
|
481
|
+
02_create-user__valid-user.json # one pair per named body
|
|
482
|
+
02_create-user__valid-user.body.json
|
|
483
|
+
02_list-users.json
|
|
484
|
+
02_list-users.body.json
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
Use `--data-dir` to put this somewhere else.
|
|
488
|
+
|
|
489
|
+
Sending with a single checked body shows the response immediately and does not
|
|
490
|
+
write files. Sending with two or more checked bodies, or using **Run selected**,
|
|
491
|
+
always saves outputs.
|
|
492
|
+
|
|
493
|
+
## Desktop apps (installer, .exe, .dmg and .deb)
|
|
494
|
+
|
|
495
|
+
Packaged builds bundle Python and every dependency, so users just double-click.
|
|
496
|
+
|
|
497
|
+
| OS | File | Data folder |
|
|
498
|
+
|---|---|---|
|
|
499
|
+
| Windows 10/11 | `pyhttp-<version>-windows-x64-setup.exe`: installer (per user, no admin rights, into `%LOCALAPPDATA%\Programs\pyhttp`, Start menu entry, optional desktop icon, uninstaller in *Apps*) | `%APPDATA%\pyhttp` |
|
|
500
|
+
| Windows 10/11 | `pyhttp-<version>-windows-x64.exe`: portable, one file, no install | `%APPDATA%\pyhttp` |
|
|
501
|
+
| macOS 11+ | `brew tap pyhttp2/pyhttp https://github.com/pyhttp2/pyhttp-releases && brew install --cask pyhttp2/pyhttp/pyhttp`, or `pyhttp-<version>-macos-arm64.dmg` (drag pyhttp to Applications) | `~/Library/Application Support/pyhttp` |
|
|
502
|
+
| Ubuntu 22.04+, Debian 12+ | `sudo apt install ./pyhttp-<version>-linux-amd64.deb`: installs to `/usr/lib/pyhttp`, adds `pyhttp` to the PATH and an app-menu entry; uses the distro's GTK and WebKitGTK (pulled in as dependencies) | `~/.local/share/pyhttp` |
|
|
503
|
+
|
|
504
|
+
Running from source keeps using `./data`. In the packaged app, output that would
|
|
505
|
+
go to a console is written to `pyhttp.log` in the data folder. Every release also
|
|
506
|
+
ships `SHA256SUMS.txt` with the checksums of the files above.
|
|
507
|
+
|
|
508
|
+
### Updates
|
|
509
|
+
|
|
510
|
+
pyhttp looks up the latest release at start (Settings → About: once an hour, or
|
|
511
|
+
*Check now*) and shows an **⬆ Update** button in the top bar when a newer version
|
|
512
|
+
exists. What the button does depends on how pyhttp was installed:
|
|
513
|
+
|
|
514
|
+
| Installed as | Update button |
|
|
515
|
+
|---|---|
|
|
516
|
+
| Windows installer | **Install and restart**: downloads the new installer, verifies it against `SHA256SUMS.txt`, runs it quietly (`/VERYSILENT`) after pyhttp has closed, and the installer starts pyhttp again. |
|
|
517
|
+
| Windows portable `.exe` | **Install and restart**: downloads and verifies the new `.exe`, then a small helper (`updates/apply-update.cmd` in the data folder) waits for pyhttp to exit, swaps the file in place (same name, same folder) and starts it again. |
|
|
518
|
+
| macOS, installed with Homebrew | **Update with Homebrew**: runs `brew update` and `brew upgrade --cask pyhttp` with the output shown in the dialog, removes the quarantine flag and restarts pyhttp. |
|
|
519
|
+
| macOS `.dmg` | Download of the new `.dmg`, plus the Homebrew commands to switch (after that, updates install themselves). |
|
|
520
|
+
| Linux `.deb` | Download of the new `.deb` plus the `sudo apt install ./pyhttp-<version>-linux-amd64.deb` command to run. |
|
|
521
|
+
| From source | Download links and `git pull`. |
|
|
522
|
+
|
|
523
|
+
Requests, settings and history are kept: they live in the data folder, which no
|
|
524
|
+
update touches. The backend is `pyhttp/updater.py` (`POST /api/update/install`,
|
|
525
|
+
`GET /api/update/status`); the UI polls the status and shows a progress bar.
|
|
526
|
+
|
|
527
|
+
### Build on your machine
|
|
528
|
+
|
|
529
|
+
PyInstaller does not cross-compile: build the `.exe` on Windows and the `.dmg` on a Mac.
|
|
530
|
+
|
|
531
|
+
```sh
|
|
532
|
+
pip install -r requirements.txt -r requirements-build.txt
|
|
533
|
+
python packaging/build.py # result goes to dist/
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
On Windows you can use the project venv: `.venv\Scripts\python packaging\build.py`.
|
|
537
|
+
The Windows build produces the portable `.exe` and, when [Inno Setup](https://jrsoftware.org/isdl.php)
|
|
538
|
+
6.3+ or 7 is installed, the installer from `packaging/pyhttp.iss` (ISCC.exe is found on
|
|
539
|
+
PATH, in Program Files or through the `ISCC` environment variable; without it the
|
|
540
|
+
installer is skipped with a note).
|
|
541
|
+
A `.dmg` built on an Apple Silicon Mac runs on Apple Silicon; build on an Intel Mac for Intel.
|
|
542
|
+
|
|
543
|
+
On Ubuntu/Debian the same command builds the `.deb`. Install the GTK bindings and
|
|
544
|
+
packaging tools first (`sudo apt install libgirepository1.0-dev libcairo2-dev pkg-config
|
|
545
|
+
gir1.2-gtk-3.0 gir1.2-webkit2-4.1 dpkg-dev`, then `pip install "PyGObject<3.51" pycairo`
|
|
546
|
+
in the venv). The package leaves GTK, WebKitGTK and the other system libraries to the
|
|
547
|
+
distro and declares them as dependencies (`packaging/build.py` works them out from the
|
|
548
|
+
bundle, like `dpkg-shlibdeps`). Build on the oldest release you want to support: a
|
|
549
|
+
`.deb` built on Ubuntu 22.04 runs on 22.04, 24.04 and Debian 12+.
|
|
550
|
+
|
|
551
|
+
### Build both on GitHub (no Mac needed)
|
|
552
|
+
|
|
553
|
+
`.github/workflows/build.yml` builds the Windows `.exe` and the macOS `.dmg` on
|
|
554
|
+
GitHub's machines. Every push to `main` tests and builds (files appear under the
|
|
555
|
+
run's *Artifacts*); nothing is published. To release:
|
|
556
|
+
|
|
557
|
+
```sh
|
|
558
|
+
python packaging/bump.py 0.1.2
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
That sets `__version__`, commits, creates the tag `v0.1.2` and pushes both. The
|
|
562
|
+
tag run publishes the installer, the portable `.exe`, the `.dmg`, `SHA256SUMS.txt`,
|
|
563
|
+
the license files and the Homebrew cask to the public
|
|
564
|
+
[pyhttp-releases](https://github.com/pyhttp2/pyhttp-releases) repository (needs the
|
|
565
|
+
`RELEASE_TOKEN` secret). The Windows runner installs Inno Setup with Chocolatey when
|
|
566
|
+
it is not already there. The in-app updater refuses a release without `SHA256SUMS.txt`,
|
|
567
|
+
so keep that step in the workflow. A tag whose version differs from `__version__` is refused,
|
|
568
|
+
because the release name, file names and the in-app update check all come from
|
|
569
|
+
`__version__`. Alternatively run the workflow by hand from the Actions tab with
|
|
570
|
+
"publish" ticked.
|
|
571
|
+
|
|
572
|
+
### First launch: unsigned app warnings
|
|
573
|
+
|
|
574
|
+
The builds are not code-signed, so the operating system warns the first time:
|
|
575
|
+
|
|
576
|
+
- **Windows** shows "Windows protected your PC" (SmartScreen): click **More info → Run anyway**.
|
|
577
|
+
- **macOS** says the app is from an unidentified developer: right-click pyhttp in
|
|
578
|
+
Applications → **Open** → **Open**, or allow it in System Settings → Privacy & Security.
|
|
579
|
+
If macOS says the app "is damaged", run `xattr -dr com.apple.quarantine /Applications/pyhttp.app`.
|
|
580
|
+
|
|
581
|
+
Removing these warnings needs a Windows code-signing certificate and an Apple
|
|
582
|
+
Developer ID (with notarization).
|
|
583
|
+
|
|
584
|
+
## Architecture
|
|
585
|
+
|
|
586
|
+
```
|
|
587
|
+
pyhttp/
|
|
588
|
+
__main__.py entry point: native window (pywebview) or browser/server mode
|
|
589
|
+
app.py FastAPI routes (/api/...) + static UI
|
|
590
|
+
db.py SQLite access (requests, folders, environments, cookies, history, runs)
|
|
591
|
+
runner.py httpx execution (auth, cookies, redirects, proxy, body types), RunManager, file output
|
|
592
|
+
mock.py mock servers: route matching and templated answers under /mock/<name>/
|
|
593
|
+
templating.py {{variable}}, {{prev.*}}, {{data.*}} and {{$dynamic}} substitution
|
|
594
|
+
jsonc.py strips // and /* */ comments from JSON bodies
|
|
595
|
+
assertions.py code-free tests and value extraction
|
|
596
|
+
jsengine.py JavaScript scripts (Postman-compatible pm API) in QuickJS or V8; pm.js is the runtime
|
|
597
|
+
scripts.py optional Python pre-request / test scripts (py object)
|
|
598
|
+
postman.py Postman Collection v2.1 and environment import/export
|
|
599
|
+
curl.py curl command line -> request
|
|
600
|
+
updater.py in-app updates: download + verify + helper script (Windows), brew upgrade (macOS)
|
|
601
|
+
static/ index.html, style.css, features.css, app.js, editor.js (CodeMirror editors),
|
|
602
|
+
viewer.js (response viewer), codegen.js (snippets), features.js,
|
|
603
|
+
vendor/codemirror.js (prebuilt CodeMirror 6 bundle, see packaging/editor)
|
|
604
|
+
packaging/ build.py, pyhttp.spec, pyhttp.iss (Windows installer), make_icons.py (desktop builds)
|
|
605
|
+
tests/ test_backend.py (API), test_ui.py (Playwright, headless Edge/Chromium)
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
Run the tests with `pip install -r requirements-dev.txt` and `python -m pytest tests -q`.
|
|
609
|
+
|
|
610
|
+
In `--browser` or `--server` mode the API is documented at
|
|
611
|
+
<http://127.0.0.1:8765/api/docs>, so you can drive runs from scripts
|
|
612
|
+
(`POST /api/runs`). Window mode uses the same default port when it is free and
|
|
613
|
+
falls back to any free one, printing it on start — so mock server URLs stay the
|
|
614
|
+
same from launch to launch.
|
|
615
|
+
|
|
616
|
+
## License
|
|
617
|
+
|
|
618
|
+
Copyright (c) 2026 pyhttp Dev Team — *From the unknown to the unowned*. pyhttp is **free for everyone** under the
|
|
619
|
+
[pyhttp Free License 1.1](LICENSE.md): at home or at work, at a company of any
|
|
620
|
+
size, for any purpose including commercial use, with no fees, no seats and no
|
|
621
|
+
registration. Unmodified release files may be shared freely, inside a company
|
|
622
|
+
or through package managers; selling pyhttp or distributing modified versions
|
|
623
|
+
is not allowed, and the name and logo stay with the project. The source code is
|
|
624
|
+
published on PyPI as [`pyhttp-app`](https://pypi.org/project/pyhttp-app/)
|
|
625
|
+
so it can be inspected and installed with pip; you may modify your own copy but
|
|
626
|
+
not distribute the changes. The packaged installer, `.exe`, `.dmg` and `.deb`
|
|
627
|
+
builds are published from the public
|
|
628
|
+
[pyhttp-releases](https://github.com/pyhttp2/pyhttp-releases) repository.
|
|
629
|
+
Bundled open-source components are listed in
|
|
630
|
+
[THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md).
|
|
631
|
+
|
|
632
|
+
The app itself stays free. If paid extras ever appear, they will be optional
|
|
633
|
+
add-ons, services or support under their own terms, never a restriction on who
|
|
634
|
+
may use pyhttp.
|
|
635
|
+
|
|
636
|
+
## Keyboard shortcuts
|
|
637
|
+
|
|
638
|
+
| Keys | Action |
|
|
639
|
+
|-----------------|---------------|
|
|
640
|
+
| Ctrl/Cmd+Enter | Send request |
|
|
641
|
+
| Ctrl/Cmd+S | Save now (autosave is always on) |
|
|
642
|
+
| Ctrl/Cmd+N | New request |
|
|
643
|
+
| Ctrl/Cmd+D | Duplicate the request |
|
|
644
|
+
| Ctrl/Cmd+W | Close the current tab |
|
|
645
|
+
| Ctrl/Cmd+K | Search the collection |
|
|
646
|
+
| Ctrl/Cmd+/ | Comment / uncomment the line(s) in the body |
|
|
647
|
+
| Ctrl/Cmd+B | Beautify the body |
|
|
648
|
+
| Tab / Shift+Tab | Indent / outdent in the body |
|
|
649
|
+
| Ctrl/Cmd+F | Search in the response body |
|
|
650
|
+
| Ctrl/Cmd+Shift+C | Code snippet |
|
|
651
|
+
| Ctrl/Cmd+Alt+C | Toggle the console |
|
|
652
|
+
| Ctrl/Cmd+\ | Show or hide the sidebar |
|
|
653
|
+
| ? | Shortcut help |
|
|
654
|
+
| Esc | Close dialog |
|