xh is a friendly and fast tool for sending HTTP requests. It reimplements as much as possible of HTTPie's excellent design, with a focus on improved performance.

Overview

xh

Version info Packaging status

xh is a friendly and fast tool for sending HTTP requests. It reimplements as much as possible of HTTPie's excellent design, with a focus on improved performance.

asciicast

Installation

via cURL (Linux & macOS)

curl -sfL https://raw.githubusercontent.com/ducaale/xh/master/install.sh | sh

via a package manager

OS Method Command
Any Cargo* cargo install xh
Any Huber huber install xh
Arch Linux Pacman pacman -S xh
Debian & Ubuntu Apt** sudo apt install xh
FreeBSD FreshPorts pkg install xh
Linux & macOS Nixpkgs nix-env -iA nixpkgs.xh
Linux & macOS Homebrew brew install xh
macOS MacPorts sudo port install xh
Windows Scoop scoop install xh

* Make sure that you have Rust 1.46 or later installed

** You will need to add the apt repository from https://apt.cli.rs/

via pre-built binaries

The release page contains prebuilt binaries for Linux, macOS and Windows.

Usage

Use a client side certificate for SSL --cert-key A private key file to use with --cert --ssl Force a particular TLS version [possible values: auto, ssl2.3, tls1, tls1.1, tls1.2, tls1.3] --native-tls Use the system TLS library instead of rustls (if enabled at compile time) --https Make HTTPS requests if not specified in the URL --http-version HTTP version to use [possible values: 1, 1.0, 1.1, 2] -I, --ignore-stdin Do not attempt to read stdin --curl Print a translation to a `curl` command --curl-long Use the long versions of curl's flags --help Prints help information -V, --version Prints version information ARGS: <[METHOD] URL> The request URL, preceded by an optional HTTP method ... Optional key-value pairs to be included in the request Each option can be reset with a --no-OPTION argument.">
USAGE:
    xh [OPTIONS] <[METHOD] URL> [--] [REQUEST_ITEM]...

OPTIONS:
    -j, --json                           (default) Serialize data items from the command line as a JSON object
    -f, --form                           Serialize data items from the command line as form fields
    -m, --multipart                      Like --form, but force a multipart/form-data request even without files
        --pretty 
Comments
  • Downloading is slow

    Downloading is slow

    Hey, cool tool. :)

    I noticed that downloading is pretty slow as compared to wget. For instance, on downloading a random large file, using ht -d I get 7-13MB/s on repeated tests while using wget I get a good 60MB/s (my full connection speed). Any idea?

    Sorry I can't be more specific but literally all I do is a multi-run test of a 2-5GB-sized file between wget and ht -d.

    opened by svenstaro 19
  • Rename this project

    Rename this project

    I was made aware [1] the name Yahc might be confused with a rust community member who goes by the name Yaahc. Therefore I am planning to rename this project using one of the following:

    • ht: This would have been the best pick, but it is already being used by a similar project https://github.com/mark-burnett/ht
    • rq: This name is being used by a popular python job queue library. Although it is possible to append -rs at the end to avoid a name clash.
    • htyr: Not sure what it means but for some reason I like it.

    [1] https://www.reddit.com/r/rust/comments/k0aika/yahc_yet_another_httpie_clone_in_rust/gdgza01?utm_source=share&utm_medium=web2x&context=3

    opened by ducaale 17
  • Add HTTPS relevant supports: host's SSL certificate verification, client side SSL certificate, etc.

    Add HTTPS relevant supports: host's SSL certificate verification, client side SSL certificate, etc.

    Description

    This PR attempts to implement same/similar functionalities of HTTPS of HTTPie:

    • [x] --verify To skip the host’s SSL certificate verification.
    • [x] --cert/cert-key To use a client side certificate for the SSL communication.

    @otaconix have contributed a lot of work on this PR, thank you.

    opened by jihchi 13
  • aarch64 / arm64 support

    aarch64 / arm64 support

    Hi,

    I was using xh on a Raspberry Pi 4 which was recently switched to the Raspberry Pi OS arm64 release. After that, the arm-unknown-linux-gnueabihf release doesn't work anymore:

    $ uname -a
    Linux raspberrypi 5.10.63-v8+ #1488 SMP PREEMPT Thu Nov 18 16:16:16 GMT 2021 aarch64 GNU/Linux
    $ cd xh-v0.14.1-arm-unknown-linux-gnueabihf/
    $ ls -lh
    total 6.1M
    drwxr-xr-x 2 pi pi 4.0K Nov 26 20:35 completions
    drwxr-xr-x 2 pi pi 4.0K Nov 26 20:35 doc
    -rw-r--r-- 1 pi pi 1.1K Nov 26 20:35 LICENSE
    -rw-r--r-- 1 pi pi 9.7K Nov 26 20:35 README.md
    -rwxr-xr-x 1 pi pi 6.1M Nov 26 20:35 xh
    $ ./xh
    bash: ./xh: No such file or directory
    

    Would it be possible to also release aarch64/arm64 binaries?

    Regards, Tiago.

    opened by myhro 12
  • Support for bearer auth in .netrc

    Support for bearer auth in .netrc

    Previously the .netrc only handled authorization that contains both a username and password.

    This is a divergence from the behavior of httpie.

    This only activates when --auth-type bearer is specified without the --auth flag, so I believe it should be a compatible change. (I believe previously using it like this would have always reported an error?)

    opened by porglezomp 9
  • [Feature] One-line binary install improvement

    [Feature] One-line binary install improvement

    I have a plethora of great statically linked binary installs in Linux (Ubuntu). These include ripgrep, exa, bat, fd etc. None shines as well as chezmoi when it comes to the one-line installer.

    I recommend to implement a one-line binary installer to follow that of chezmoi. See this documentation: https://github.com/twpayne/chezmoi/blob/master/docs/INSTALL.md#one-line-binary-install

    In effect, what it does, is to download the latest statically linked binary for your operating system and architecture into ./bin This means I can put myself in whatever dir I want and just call the installer and it will be installed into the bin path of my choosing. Be that ~/bin or .local/bin or whatever I prefer.

    opened by thernstig 9
  • Allow forcing HTTP version

    Allow forcing HTTP version

    Hey, I really like this tool and use it quite a bit for debugging. As such, I sometimes need to specifically request a certain version of HTTP from a server. Could you add a mode to force the HTTP version? Curl has --http1.0, --http1.1, --http2, --http3 and I think that makes sense.

    Please consider adding those flags.

    opened by svenstaro 9
  • dns error: failed to lookup address information: Temporary failure in name resolution

    dns error: failed to lookup address information: Temporary failure in name resolution

    Hello.

    Trying to move httpie example:

    http GET <url> param1=value1 param2=value2 'Authorization: Bearer <supersecrettoken>' --verify no
    HTTP/1.1 200 OK
    Connection: keep-alive
    Content-Length: 122
    Content-Type: application/json
    Date: Wed, 14 Jul 2021 19:01:23 GMT
    Server: nginx/1.12.2
    Strict-Transport-Security: max-age=31536000;
    
    {
        "code": 200,
        "result": {
            <some_data>
        },
        "status": "ok"
    }
    

    to xh:

    xh --bearer <supersecrettoken> --verify no <url> param1=value1 param2=value2
    Error: error sending request for url (<url>): error trying to connect: dns error: failed to lookup address information: Temporary failure in name resolution
    
    Caused by:
        0: error trying to connect: dns error: failed to lookup address information: Temporary failure in name resolution
        1: dns error: failed to lookup address information: Temporary failure in name resolution
        2: failed to lookup address information: Temporary failure in name resolution
    

    What am I doing wrong?

    opened by horseinthesky 8
  • xh lowercases all headers

    xh lowercases all headers

    What I expect

    Xh copies case of user-specified headers.

    What actually happens

    Xh treats all headers as case-insensitive and lowercases them.

    Why is this a problem?

    1. It's a difference from httpie.
    2. It has a negative net effect when interacting with non-compliant servers.

    To explain 2...

    Some services treat headers as case-sensitive (e.g with X-* headers, especially for auth). The HTTP specification does specify that headers are case-insensitive, however, consider the following matrix. If headers are treated as case insensitive, this will break servers that (incorrectly) treat them as case-sensitive, while not having a negative effect on compliant servers. If headers are treated as case sensitive, this will work with the non-compliant servers, while not having a negative effect on compliant servers.

    It would also be ok to auto-capitalize headers (e.g foO-baR-baZ could become Foo-Bar-Baz), since that's what standard industry practice anyway, but this is not what HTTPie does.

    How to test compliance

    xh --print=H localhost My-OdDlY-Capitalized-Header:Here compare to http --print=H localhost My-OdDlY-Capitalized-Header:Here

    opened by CosmicToast 7
  • [Example] File upload

    [Example] File upload

    Dear @ducaale, could you be so kind to tell what is the xh equivalent of the following curl command to upload a file?

    $ curl.exe -F [email protected] https://transfer.sh/
    
    opened by sergeevabc 7
  • Support the --proxy option

    Support the --proxy option

    The reqwest crate does all the heavy lifting (including using the http_proxy and https_proxy environment variables when the --proxy option isn't present). As noted, it's possible to use different proxies for different protocols.

    The "socks" configuration for the reqwest crate was enabled to allow users to use a socks proxy.

    opened by otaconix 7
  • Feature request: Ignore PROXY ENVIRONMENT on Windows

    Feature request: Ignore PROXY ENVIRONMENT on Windows

    xh behaves differently from curl considering PROXY environment variables. On Windows xh reads proxy settings form the registry (that's unexpected from curl).

    Need an option to force --NO-PROXY.

    opened by oryon-dominik 1
  • Add --preserve-encoding option to keep response body encoding

    Add --preserve-encoding option to keep response body encoding

    Changes

    Add a --download-encoding flag to choose an Accept-Encoding header other than "identity" during a download request. During the download, the "decompress" function that reads the response and writes it to the output will passthrough data in whatever Content-Encoding was received if --download-encoding was specified.

    Motivation

    When downloading a large file, I want to be able to transfer it compressed and leave it compressed. For example, stream download a 500MiB CSV file in the gzip encoding, saving it to a data.csv.gz file.

    jwtrueb@jmbp xh % cargo run --release -- get http://localhost:3000/download/csv/asdf -d --download-encoding gzip
    HTTP/1.1 200 OK
    Content-Encoding: gzip
    Content-Type: application/csv
    Date: Tue, 29 Nov 2022 23:17:12 GMT
    Transfer-Encoding: chunked
    Vary: accept-encoding
    
    Downloading to "asdf"
    Done. 147B in 0.00177s (80.92KiB/s)
    jwtrueb@jmbp xh % gzcat asdf
    ts,user_id,device_id,source,pressure,temperature,humidity
    2022-11-28T20:13:12.704030+00:00,2,5,1,99999.0,25.3,16.4
    2022-11-28T20:14:02.446438+00:00,2,5,1,99699.0,25.1,16.2
    
    opened by trueb2 5
  • Better TLS error messages

    Better TLS error messages

    When a TLS certificate has the wrong hostnames it would be helpful to print which hostnames it does have.

    HTTPie happens to do this, but we don't:

    $ http https://wrong.host.badssl.com

    http: error: SSLError: HTTPSConnectionPool(host='wrong.host.badssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(CertificateError("hostname 'wrong.host.badssl.com' doesn't match either of '*.badssl.com', 'badssl.com'"))) while doing a GET request to URL: https://wrong.host.badssl.com/

    $ xh https://wrong.host.badssl.com xh: error: error sending request for url (https://wrong.host.badssl.com/): error trying to connect: invalid peer certificate contents: invalid peer certificate: CertNotValidForName

    Caused by: 0: error trying to connect: invalid peer certificate contents: invalid peer certificate: CertNotValidForName 1: invalid peer certificate contents: invalid peer certificate: CertNotValidForName

    $ xh --native-tls https://wrong.host.badssl.com xh: error: error sending request for url (https://wrong.host.badssl.com/): error trying to connect: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:../ssl/statem/statem_clnt.c:1914: (Hostname mismatch)

    Caused by: 0: error trying to connect: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:../ssl/statem/statem_clnt.c:1914: (Hostname mismatch) 1: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:../ssl/statem/statem_clnt.c:1914: (Hostname mismatch) 2: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:../ssl/statem/statem_clnt.c:1914:

    (The above --native-tls error message is with OpenSSL on Linux, maybe Windows or macOS already includes this information.)

    When a certificate is expired it's also useful to see for how long it's been expired, but that's less important. (HTTPie doesn't do this.)

    I don't know how to implement this, or if we can implement it at all. It might involve library changes, and it might involve bespoke error handling in main(). It might involve messy extraction of the certificate before we drop the reqwest client. It might be really hard.

    opened by blyxxyz 1
  • Feature request: add something similar to cURL's `--cert-status`

    Feature request: add something similar to cURL's `--cert-status`

    cURL has the ability to require and verify OCSP stapled responses with the --cert-status option. Having this feature available in xh would make it great for testing both the HTTPS and TLS setup of a server with a single request.

    A similar but far more cumbersome option is the --crlfile option; stapling is a much simpler approach, IMO.

    opened by Seirdy 1
  • Add support for OAuth 2.0 authentication flows

    Add support for OAuth 2.0 authentication flows

    Can you please consider adding support for OAuth 2.0, at least the client_credentials grant?

    Example:

    xh --auth-type oauth2 --auth <client_id>:<client_secret> --oauth-grant client_credentials --oauth-token-url https://example.org/oauth/token GET example.org/api/v1/hello
    
    opened by jirutka 4
Releases(v0.17.0)
Owner
Mohamed Daahir
Mohamed Daahir
Multi-stream HTTP downloader using range requests

chooch - An Amazing Project Downloads files faster than wget/curl (in theory) using multiple connections. Chooch recycles the slowest connection and r

null 13 Sep 14, 2022
Fast and friendly HTTP server framework for async Rust

Tide Serve the web API Docs | Contributing | Chat Tide is a minimal and pragmatic Rust web application framework built for rapid development. It comes

http-rs 4.1k Jan 2, 2023
HTTPie: human-friendly CLI HTTP client for the API era

HTTPie: human-friendly CLI HTTP client for the API era HTTPie (pronounced aitch-tee-tee-pie) is a command-line HTTP client. Its goal is to make CLI in

null 25.4k Dec 30, 2022
rh: user-friendly command-line HTTP client

Rust HTTP Cli The command name in your terminal is rh. rh: user-friendly command-line HTTP client rh is a user-friendly, lightweight and performant co

null 8 Nov 30, 2022
Typed, correct GraphQL requests and responses in Rust

graphql_client A typed GraphQL client library for Rust. Features Precise types for query variables and responses. Supports GraphQL fragments, objects,

GraphQL Rust 914 Dec 27, 2022
Pyre - A fast python HTTP server inspired by japronto written in rust.

Pyre - A fast python HTTP server inspired by japronto written in rust.

null 135 Nov 26, 2022
An easy and powerful Rust HTTP Client

reqwest An ergonomic, batteries-included HTTP Client for Rust. Plain bodies, JSON, urlencoded, multipart Customizable redirect policy HTTP Proxies HTT

Sean McArthur 6.8k Dec 31, 2022
Minimal Rust HTTP client for both native and WASM

ehttp: a minimal Rust HTTP client for both native and WASM If you want to do HTTP requests and are targetting both native and web (WASM), then this is

Emil Ernerfeldt 105 Dec 25, 2022
An HTTP library for Rust

hyper A fast and correct HTTP implementation for Rust. HTTP/1 and HTTP/2 Asynchronous design Leading in performance Tested and correct Extensive produ

null 11k Jan 8, 2023
FeignHttp is a declarative HTTP client. Based on rust macros.

FeignHttp is a declarative HTTP client. Based on rust macros. Features Easy to use Asynchronous request Configurable timeout settings Suppor

null 46 Nov 30, 2022
Pretend is a macros-based declarative Rust HTTP client

pretend is a modular, Feign-inspired HTTP, client based on macros. It's goal is to decouple the definition of a REST API from it's implementation.

null 24 Aug 3, 2022
🐱‍👤 Drop-in HTTP replacement module for Garry's Mod

??‍?? gmsv_reqwest This module is a drop-in replacement for Garry's Mod's HTTP function, inspired by gmsv_chttp created by timschumi. The module uses

William 38 Dec 12, 2022
ratpack: a simpleton's HTTP framework (for rust-lang)

ratpack: a simpleton's HTTP framework (for rust-lang) ratpack is idealized in the simplicity of the sinatra (ruby) framework in its goal, and attempts

ZeroTier, Inc. 5 Jun 29, 2022
A backend providing a HTTP REST like interface for uploading files written in rust.

UploadServer A backend providing a HTTP REST like interface for uploading files written in rust. API Documentation License This project is licensed un

null 4 Nov 20, 2022
🕵️Scrape multiple media providers on a cron job and dispatch webhooks when changes are detected.

Jiu is a multi-threaded media scraper capable of juggling thousands of endpoints from different providers with unique restrictions/requirements.

Xetera 47 Dec 6, 2022
Designed as successor to Pretty-Good-Video for improved codec structure, API design & performance

Pretty Fast Video Minimal video codec designed as a successor to Pretty Good Video Goals are to improve: Quality API design Codec structure (Hopefully

Hazel Stagner 36 Jun 5, 2023
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
Allow DataFusion to resolve queries across remote query engines while pushing down as much compute as possible down.

DataFusion Federation The goal of this repo is to allow DataFusion to resolve queries across remote query engines while pushing down as much compute a

null 15 Mar 11, 2024
CLI program for sending one-off requests to the VTube Studio API

vtubestudio-cli (vts) CLI program for sending one-off requests to the VTube Studio API. It connects to the websocket, authenticates, performs one or t

null 2 Nov 24, 2021
Design token framework — adopt a unified design language across platforms, codebases, and teams

Palette Design tokens framework with atomic classes for React and Master CSS. Deliver a consistent visual identity across your apps with design tokens

Foretag 4 Aug 23, 2022