{"id":13869742,"url":"https://github.com/lewoudar/httpcli","last_synced_at":"2026-01-19T22:30:52.730Z","repository":{"id":46240380,"uuid":"405357756","full_name":"lewoudar/httpcli","owner":"lewoudar","description":"A Proof of concept of a modern python CLI with click, pydantic, rich and anyio","archived":false,"fork":false,"pushed_at":"2024-01-13T18:30:37.000Z","size":186,"stargazers_count":20,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-16T11:35:37.070Z","etag":null,"topics":["anyio","asyncclick","asyncio","click","httpx","rich","trio"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lewoudar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-09-11T11:11:54.000Z","updated_at":"2025-03-28T03:25:25.000Z","dependencies_parsed_at":"2024-01-16T07:22:52.300Z","dependency_job_id":"fb38764f-919e-43ec-af4f-d6b357560b11","html_url":"https://github.com/lewoudar/httpcli","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lewoudar/httpcli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lewoudar%2Fhttpcli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lewoudar%2Fhttpcli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lewoudar%2Fhttpcli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lewoudar%2Fhttpcli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lewoudar","download_url":"https://codeload.github.com/lewoudar/httpcli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lewoudar%2Fhttpcli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28587238,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-19T20:45:59.482Z","status":"ssl_error","status_checked_at":"2026-01-19T20:45:41.500Z","response_time":67,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anyio","asyncclick","asyncio","click","httpx","rich","trio"],"created_at":"2024-08-05T20:01:14.787Z","updated_at":"2026-01-19T22:30:52.712Z","avatar_url":"https://github.com/lewoudar.png","language":"Python","readme":"# httpcli\n\nThis project is a proof of concept of a modern python networking cli which can be *simple* and *easy* to maintain using\nsome of the best packages in the python ecosystem:\n\n- [click](https://click.palletsprojects.com/) for the foundation of a CLI application. There is also\n  [asyncclick](https://github.com/python-trio/asyncclick) that I used in this project which is a tiny wrapper around\n  click to provide asynchronous support.\n- [rich](https://github.com/willmcgugan/rich) for pretty printing in the terminal.\n- [httpx](https://www.python-httpx.org/) for HTTP protocol stuff.\n- [anyio](https://anyio.readthedocs.io/en/stable/) for concurrency.\n- [pytest](https://docs.pytest.org/en/latest/contents.html)\n  and [pytest-trio](https://pytest-trio.readthedocs.io/en/stable/)\n  for easy testing.\n\nThis is not a complete and mature project like [httpie](https://httpie.io/) but I want to implement some features not\npresent in this beautiful package like:\n\n- [HTTP2](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol/2) support\n- more authentication scheme support like digest and oauth2\n- easy cookies support\n- support of posix signals like SIGINT and SIGTERM\n- completion feature\n- git \"did you mean\" like feature\n- [sse](https://fr.wikipedia.org/wiki/Server-sent_events) support\n\n## Evolution\n\nI'm not quite sure if I will continue improving it without any motivation (sponsoring?) but it is already useful if you\nwant to test it, you just need to have [poetry](https://python-poetry.org/docs/) dependency manager and install the\nproject locally (`poetry install`). This will install two commands:\n\n- `http` useful when you don't want the cli to verify server certificate.\n- `https` when you need to verify server certificate.\n\n## Usage\n\nHopefully subcommand usage should be straightforward, but I will point some specific cases.\n\n```shell\nUsage: http [OPTIONS] COMMAND [ARGS]...\n\n  HTTP CLI\n\nOptions:\n  --config-file FILENAME          A configuration file with options used to\n                                  set the cli. Note that the file takes\n                                  precedence over the other options.\n  -t, --timeout FLOAT             Time for request to complete, a negative\n                                  value means there is no timeout.\n  --follow-redirects / -N, --no-follow-redirects\n                                  flag to decide if http redirections must be\n                                  followed\n  --auth JSON_AUTH                A json string representing authentication\n                                  information.\n  --http-version [h1|h2]          Version of http used to make the request.\n  --proxy URL                     Proxy url.\n  --version                       Show the version and exit.\n  --help                          Show this message and exit.\n\nCommands:\n  delete              Performs http DELETE request.\n  download            Process download of urls given as arguments.\n  get                 Performs http GET request.\n  head                Performs http HEAD request.\n  install-completion  Install completion script for bash, zsh and fish...\n  options             Performs http OPTIONS request.\n  patch               Performs http PATCH request.\n  post                Performs http POST request.\n  put                 Performs http PUT request.\n  sse                 Reads and print SSE events on a given url.\n```\n\n### Global cli configuration\n\nThere are some options that can be configured on the root command. These options can be read from a `yaml` file using\noption `--config-file`. The config file looks lie the following:\n\n```yaml\n# all options have default values, no need to specify them all\nhttpcli:\n  http_version: h2\n  follow_redirects: true\n  proxy: https://proxy.com\n  # timeout may be null to specify that you don't want a timeout\n  timeout: 5.0\n  auth:\n    type: oauth2\n    flow: password\n    username: user\n    password: pass\n  # for https you also have the verify option to pass a custom certificate used to authenticate the server\n  verify: /path/to/certificate\n```\n\nThose options can also be configured via environment variables. They are all prefixed with `HTTP_CLI_` and they can be\nin lowercase or uppercase. Here is the same configuration as above but using environment variables:\n\n```shell\nHTTP_CLI_HTTP_VERSION=h2\nHTTP_CLI_FOLLOW_REDIRECTS=true\nHTTP_CLI_PROXY=https://proxy.com\nHTTP_CLI_TIMEOUT=5.0\n# here value is passed as json\nHTTP_CLI_AUTH={\"type\": \"oauth2\", \"flow\": \"password\", \"username\": \"user\", \"password\": \"pass\"}\nHTTP_CLI_VERIFY=/path/to/certificate\n```\n\n### Commands\n\n#### install-completion\n\nThis is obviously the first command you will want to use to have subcommand and option autocompletion. You don't need to\ndo that for the two cli `http` and `https`. Doing it with one will install the other. The current shells supported\nare `bash`, `zsh` and `fish`. To use autocompletion for subcommands, just enter the first letter and use `TAB` key\ntwice. For option autocompletion, enter the first dash and use `TAB` twice.\n\n#### get, head, option, delete\n\nThe usage should be pretty straightforward for these commands.\n\n```shell\nhttp get --help\nUsage: http get [OPTIONS] URL\n\n  Performs http GET request.\n\n  URL is the target url.\n\nOptions:\n  -c, --cookie COOKIE  Cookie passed to the request, can by passed multiple\n                       times.\n  -H, --header HEADER  Header passed to the request, can by passed multiple\n                       times.\n  -q, --query QUERY    Querystring argument passed to the request, can by\n                       passed multiple times.\n  --help               Show this message and exit.\n```\n\nYou can play with it using https://pie.dev. Here is a simple example:\n\n```shell\nhttp get https://pie.dev/get -c my:cookie -q my:query -H X-MY:HEADER\n```\n\n#### post, put, patch\n\nThere are some subtleties with these commands. I will use `post` in the following examples but the same apply to `put`\nand `patch`.\n\n**json data**\n\nIf you play with json, in case you only have string values, you can do this:\n\n```shell\n# here we are sending {\"foo\": \"bar\", \"hello\": \"world\"} to https://pie.dev/post\nhttp post https://pie.dev/post -j foo:bar -j hello:world\n```\n\nIf you need to send other values than strings, you will need to pass the json encoded value with a slightly different\nsyntax, `:=` instead of `=`.\n\n```shell\nhttp post https://pie.dev/post -j number:='2' -j boolean:='true' -j fruits:='[\"apple\", \"pineapple\"]'\n```\n\nIf you have a deeply nested structure you can't write simple in the terminal, you can use of json file instead.\nConsidering we have a file *fruits.json* with the following content:\n\n```json\n[\n  \"apple\",\n  \"pineapple\"\n]\n```\n\nYou can use the file like it:\n\n```shell\nhttp post https://pie.dev/post -j fruits:@fruits.json\n```\n\n**form data**\n\nFirst you need to know that you can't pass **form data and json data in the same request**. You must choose between the\ntwo methods. The basic usage is the following:\n\n```shell\nhttps post https://pie.dev/post -f foo:bar -f number:2\n```\n\nIf you need to send files, here is what you can do:\n\n```shell\n# this will send the key \"foo\" with the value \"bar\" and the key \"photo\" with the file photo.jpg\nhttps post https://pie.dev/post -f foo:bar -f photo:@photo.jpg\n```\n\nIf you want to send raw data, use the following form:\n\n```shell\nhttps post https://pie.dev/post --raw 'raw content'\n```\n\nYou can also pass the raw content in a file:\n\n```shell\n# you can put what you want in your file, just be sure to set the correct content-type\nhttps post https://pie.dev/post --raw @hello.txt\n```\n\n#### download\n\nYou can pass urls as arguments. Files will be downloaded in the current directory. If you wish to change the directory\nwhere files should be put, pass the `-d` option with the path of the desired destination folder.\n\n```shell\n# this will downloads two files and put them in the downloads directory of the current user\nhttps download https://pie.dev/image/jpeg https://pie.dev/image/png -d ~/downloads\n```\n\nYou can use a file to specify all the resources to download. There should be **one url per line**. Consider a file\n`urls.txt` having the following content:\n\n```text\nhttps://pie.dev/image/svg\nhttps://pie.def/image/webp\n```\n\nYou can download urls from the file and urls from the command line at the same time:\n\n```shell\nhttps download https://pie.dev/image/jpeg -f urls.txt\n```\n\n#### sse\n\nIf you want to listen sse events from an endpoint, you can simply do this:\n\n```shell\n# The sse command will not stop if the data are sent without interruption, which is almost always the case\n# with sse, so if you want to stop it, just Ctrl + C ;)\nhttps sse https://endpoint.com/sse\n```\n\n## What needs to be improved?\n\nIf I were to continue the development of the project, here are the points to review/enhance:\n\n- adapt code to support httpx 1.0 . At the moment of writing it is still in beta, but there is at least one breaking\n  change concerning `allow_redirects` option.\n- add more authentication schemes, mainly all the oauth2 flows, but may be some others like\n  [macaroon](https://neilmadden.blog/2020/07/29/least-privilege-with-less-effort-macaroon-access-tokens-in-am-7-0/)...\n- support multiple proxy values\n- session support\n- add CI/CD\n- improve code coverage (not 100% yet)\n- refactor a bit the code, currently I don't like the structure of my helpers modules. Also auth support can be\n  refactored using this [technique](https://www.python-httpx.org/advanced/#customizing-authentication) I was not aware\n  of when starting this project.\n- add autocompletion featurefor other shells like ksh, powershell or powercore\n- and probably more... :)","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flewoudar%2Fhttpcli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flewoudar%2Fhttpcli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flewoudar%2Fhttpcli/lists"}