[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-5503":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":18,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":35,"readmeContent":36,"aiSummary":37,"trendingCount":16,"starSnapshotCount":16,"syncStatus":38,"lastSyncTime":39,"discoverSource":40},5503,"oha","hatoo\u002Foha","hatoo","Ohayou(おはよう), HTTP load generator, inspired by rakyll\u002Fhey with tui animation.","",null,"Rust",10308,292,29,42,0,3,18,71,42.4,"MIT License",false,"master",true,[26,27,28,29,30,31,32,33,34],"benchmark","cli","command-line","http","http2","load-generator","load-testing","rust","tui","2026-06-12 02:01:11","# oha (おはよう)\n\n[![GitHub Actions](https:\u002F\u002Fgithub.com\u002Fhatoo\u002Foha\u002Fworkflows\u002FCI\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fhatoo\u002Foha\u002Factions?query=workflow%3ACI)\n[![Crates.io](https:\u002F\u002Fimg.shields.io\u002Fcrates\u002Fv\u002Foha.svg)](https:\u002F\u002Fcrates.io\u002Fcrates\u002Foha)\n[![Arch Linux](https:\u002F\u002Fimg.shields.io\u002Farchlinux\u002Fv\u002Fextra\u002Fx86_64\u002Foha)](https:\u002F\u002Farchlinux.org\u002Fpackages\u002Fextra\u002Fx86_64\u002Foha\u002F)\n[![Homebrew](https:\u002F\u002Fimg.shields.io\u002Fhomebrew\u002Fv\u002Foha)](https:\u002F\u002Fformulae.brew.sh\u002Fformula\u002Foha)\n\n[![ko-fi](https:\u002F\u002Fko-fi.com\u002Fimg\u002Fgithubbutton_sm.svg)](https:\u002F\u002Fko-fi.com\u002Fhatoo)\n\noha is a tiny program that sends some load to a web application and show realtime tui inspired by [rakyll\u002Fhey](https:\u002F\u002Fgithub.com\u002Frakyll\u002Fhey).\n\nThis program is written in Rust and powered by [tokio](https:\u002F\u002Fgithub.com\u002Ftokio-rs\u002Ftokio) and beautiful tui by [ratatui](https:\u002F\u002Fgithub.com\u002Fratatui-org\u002Fratatui).\n\n![demo](demo.gif)\n\n# Installation\n\nThis program is built on stable Rust, with both `make` and `cmake` prerequisites to install via cargo.\n\n    cargo install oha\n\nYou can optionally build oha against [native-tls](https:\u002F\u002Fgithub.com\u002Fsfackler\u002Frust-native-tls) instead of [rustls](https:\u002F\u002Fgithub.com\u002Frustls\u002Frustls).\n\n    cargo install --no-default-features --features native-tls oha\n\nYou can enable VSOCK support by enabling `vsock` feature.\n\n    cargo install --features vsock oha\n\nYou can enable experimental HTTP3 support by enabling the `http3` feature. This uses the [H3](https:\u002F\u002Fgithub.com\u002Fhyperium\u002Fh3) library by the developers of Hyper.\nIt will remain experimental as long as H3 is experimental. It currently depends on using `rustls` for TLS.\n\n## Download pre-built binary\n\nYou can download pre-built binary from [Release page](https:\u002F\u002Fgithub.com\u002Fhatoo\u002Foha\u002Freleases) for each version and from [Publish workflow](https:\u002F\u002Fgithub.com\u002Fhatoo\u002Foha\u002Factions\u002Fworkflows\u002Frelease.yml) and [Publish PGO workflow](https:\u002F\u002Fgithub.com\u002Fhatoo\u002Foha\u002Factions\u002Fworkflows\u002Frelease-pgo.yml) for each commit.\n\n## On Arch Linux\n\n    pacman -S oha\n\n## On macOS (Homebrew)\n\n    brew install oha\n\n## On Windows (winget)\n\n    winget install hatoo.oha\n\n## On Debian ([Azlux's repository](http:\u002F\u002Fpackages.azlux.fr\u002F))\n\n    echo \"deb [signed-by=\u002Fusr\u002Fshare\u002Fkeyrings\u002Fazlux-archive-keyring.gpg] http:\u002F\u002Fpackages.azlux.fr\u002Fdebian\u002F stable main\" | sudo tee \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fazlux.list\n    sudo wget -O \u002Fusr\u002Fshare\u002Fkeyrings\u002Fazlux-archive-keyring.gpg https:\u002F\u002Fazlux.fr\u002Frepo.gpg\n    apt update\n    apt install oha\n\n## X-CMD (Linux, macOS, Windows WSL\u002FGitBash)\n\nYou can install with [x-cmd](https:\u002F\u002Fwww.x-cmd.com).\n\n```sh\nx env use oha\n```\n\n## Containerized\n\n### Official Docker image\n\n[ghcr.io\u002Fhatoo\u002Foha](https:\u002F\u002Fgithub.com\u002Fhatoo\u002Foha\u002Fpkgs\u002Fcontainer\u002Foha)\n\n### Build image locally\n\nYou can also build and create a container image including oha\n\n```sh\ndocker build -t hatoo\u002Foha:latest .\n```\n\nThen you can use oha directly through the container\n\n```sh\ndocker run --rm -it --network=host hatoo\u002Foha:latest https:\u002F\u002Fexample.com:3000\n```\n\n## Profile-Guided Optimization (PGO)\n\nYou can build `oha` with PGO by using the following commands:\n\n```sh\nbun run pgo.js\n```\n\nAnd the binary will be available at `target\u002F[target-triple]\u002Fpgo\u002Foha`.\n\n**Note**: Please keep in mind that in order to run the aforementioned command,\nyou need to have installed `cargo-pgo` cargo package.\n\nYou can install it via `cargo install cargo-pgo`.\n\n# Platform\n\n- Linux - Tested on Ubuntu 18.04 gnome-terminal\n- Windows 10 - Tested on Windows Powershell\n- MacOS - Tested on iTerm2\n\n# Usage\n\n`-q` option works different from [rakyll\u002Fhey](https:\u002F\u002Fgithub.com\u002Frakyll\u002Fhey). It's set overall query per second instead of for each workers.\n\n```sh\nOhayou(おはよう), HTTP load generator, inspired by rakyll\u002Fhey with tui animation.\n\nUsage: oha [OPTIONS] \u003CURL>\n\nArguments:\n  \u003CURL>  Target URL or file with multiple URLs.\n\nOptions:\n  -n \u003CN_REQUESTS>\n          Number of requests to run. Accepts plain numbers or suffixes: k = 1,000, m = 1,000,000 (e.g. 10k, 1m). [default: 200]\n  -c \u003CN_CONNECTIONS>\n          Number of connections to run concurrently. You may should increase limit to number of open files for larger `-c`. [default: 50]\n  -p \u003CN_HTTP2_PARALLEL>\n          Number of parallel requests to send on HTTP\u002F2. `oha` will run c * p concurrent workers in total. [default: 1]\n  -z \u003CDURATION>\n          Duration of application to send requests.\n          On HTTP\u002F1, When the duration is reached, ongoing requests are aborted and counted as \"aborted due to deadline\"\n          You can change this behavior with `-w` option.\n          Currently, on HTTP\u002F2, When the duration is reached, ongoing requests are waited. `-w` option is ignored.\n          Examples: -z 10s -z 3m.\n  -w, --wait-ongoing-requests-after-deadline\n          When the duration is reached, ongoing requests are waited\n  -q \u003CQUERY_PER_SECOND>\n          Rate limit for all, in queries per second (QPS)\n      --burst-delay \u003CBURST_DURATION>\n          Introduce delay between a predefined number of requests.\n          Note: If qps is specified, burst will be ignored\n      --burst-rate \u003CBURST_REQUESTS>\n          Rates of requests for burst. Default is 1\n          Note: If qps is specified, burst will be ignored\n      --rand-regex-url\n          Generate URL by rand_regex crate but dot is disabled for each query e.g. http:\u002F\u002F127.0.0.1\u002F[a-z][a-z][0-9]. Currently dynamic scheme, host and port with keep-alive do not work well. See https:\u002F\u002Fdocs.rs\u002Frand_regex\u002Flatest\u002Frand_regex\u002Fstruct.Regex.html for details of syntax.\n      --urls-from-file\n          Read the URLs to query from a file\n      --max-repeat \u003CMAX_REPEAT>\n          A parameter for the '--rand-regex-url'. The max_repeat parameter gives the maximum extra repeat counts the x*, x+ and x{n,} operators will become. [default: 4]\n      --dump-urls \u003CDUMP_URLS>\n          Dump target Urls \u003CDUMP_URLS> times to debug --rand-regex-url\n      --latency-correction\n          Correct latency to avoid coordinated omission problem. It's ignored if -q is not set.\n      --no-tui\n          No realtime tui\n      --fps \u003CFPS>\n          Frame per second for tui. [default: 16]\n  -m, --method \u003CMETHOD>\n          HTTP method [default: GET]\n  -H \u003CHEADERS>\n          Custom HTTP header. Examples: -H \"foo: bar\"\n      --proxy-header \u003CPROXY_HEADERS>\n          Custom Proxy HTTP header. Examples: --proxy-header \"foo: bar\"\n  -t \u003CTIMEOUT>\n          Timeout for each request. Default to infinite.\n      --connect-timeout \u003CCONNECT_TIMEOUT>\n          Timeout for establishing a new connection. Default to 5s. [default: 5s]\n  -A \u003CACCEPT_HEADER>\n          HTTP Accept Header.\n  -d \u003CBODY_STRING>\n          HTTP request body.\n  -D \u003CBODY_PATH>\n          HTTP request body from file.\n  -Z \u003CBODY_PATH_LINES>\n          HTTP request body from file line by line.\n  -F, --form \u003CFORM>\n          Specify HTTP multipart POST data (curl compatible). Examples: -F 'name=value' -F 'file=@path\u002Fto\u002Ffile'\n  -T \u003CCONTENT_TYPE>\n          Content-Type.\n  -a \u003CBASIC_AUTH>\n          Basic authentication (username:password), or AWS credentials (access_key:secret_key)\n      --aws-session \u003CAWS_SESSION>\n          AWS session token\n      --aws-sigv4 \u003CAWS_SIGV4>\n          AWS SigV4 signing params (format: aws:amz:region:service)\n  -x \u003CPROXY>\n          HTTP proxy\n      --proxy-http-version \u003CPROXY_HTTP_VERSION>\n          HTTP version to connect to proxy. Available values 0.9, 1.0, 1.1, 2.\n      --proxy-http2\n          Use HTTP\u002F2 to connect to proxy. Shorthand for --proxy-http-version=2\n      --http-version \u003CHTTP_VERSION>\n          HTTP version. Available values 0.9, 1.0, 1.1, 2, 3\n      --http2\n          Use HTTP\u002F2. Shorthand for --http-version=2\n      --host \u003CHOST>\n          HTTP Host header\n      --disable-compression\n          Disable compression.\n  -r, --redirect \u003CREDIRECT>\n          Limit for number of Redirect. Set 0 for no redirection. Redirection isn't supported for HTTP\u002F2. [default: 10]\n      --disable-keepalive\n          Disable keep-alive, prevents re-use of TCP connections between different HTTP requests. This isn't supported for HTTP\u002F2.\n      --no-pre-lookup\n          *Not* perform a DNS lookup at beginning to cache it\n      --ipv6\n          Lookup only ipv6.\n      --ipv4\n          Lookup only ipv4.\n      --cacert \u003CCACERT>\n          (TLS) Use the specified certificate file to verify the peer. Native certificate store is used even if this argument is specified.\n      --cert \u003CCERT>\n          (TLS) Use the specified client certificate file. --key must be also specified\n      --key \u003CKEY>\n          (TLS) Use the specified client key file. --cert must be also specified\n      --insecure\n          Accept invalid certs.\n      --connect-to \u003CCONNECT_TO>\n          Override DNS resolution and default port numbers with strings like 'example.org:443:localhost:8443'\n          Note: if used several times for the same host:port:target_host:target_port, a random choice is made\n      --no-color\n          Disable the color scheme. [env: NO_COLOR=]\n      --unix-socket \u003CUNIX_SOCKET>\n          Connect to a unix socket instead of the domain in the URL. Only for non-HTTPS URLs.\n      --stats-success-breakdown\n          Include a response status code successful or not successful breakdown for the time histogram and distribution statistics\n      --db-url \u003CDB_URL>\n          Write succeeded requests to sqlite database url E.G test.db\n      --debug\n          Perform a single request and dump the request and response\n  -o, --output \u003COUTPUT>\n          Output file to write the results to. If not specified, results are written to stdout.\n      --output-format \u003COUTPUT_FORMAT>\n          Output format [default: text] [possible values: text, json, csv, quiet]\n  -u, --time-unit \u003CTIME_UNIT>\n          Time unit to be used. If not specified, the time unit is determined automatically. This option affects only text format. [possible values: ns, us, ms, s, m, h]\n  -h, --help\n          Print help\n  -V, --version\n          Print version\n```\n\n# Performance\n\n`oha` uses faster implementation when `--no-tui` option is set and both `-q` and `--burst-delay` are not set because it can avoid overhead to gather data realtime.\n\n# Output\n\nBy default `oha` outputs a text summary of the results.\n\n`oha` prints JSON summary output when `--output-format json` option is set.\nThe schema of JSON output is defined in [schema.json](.\u002Fschema.json).\n\nWhen `--output-format csv` is used result of each request is printed as a line of comma separated values.\n\n# Tips\n\n## Stress test in more realistic condition\n\n`oha` uses default options inherited from [rakyll\u002Fhey](https:\u002F\u002Fgithub.com\u002Frakyll\u002Fhey) but you may need to change options to stress test in more realistic condition.\n\nI suggest to run `oha` with following options.\n\n```sh\noha \u003C-z or -n> -c \u003Cnumber of concurrent connections> -q \u003Cquery per seconds> --latency-correction --disable-keepalive \u003Ctarget-address>\n```\n\n- --disable-keepalive\n\n    In real, user doesn't query same URL using [Keep-Alive](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FHTTP\u002FHeaders\u002FKeep-Alive). You may want to run without `Keep-Alive`.\n- --latency-correction\n\n    You can avoid `Coordinated Omission Problem` by using `--latency-correction`.\n\n## Burst feature\n\nYou can use `--burst-delay` along with `--burst-rate` option to introduce delay between a defined number of requests.\n\n```sh\noha -n 10 --burst-delay 2s --burst-rate 4\n```\n\nIn this particular scenario, every 2 seconds, 4 requests will be processed, and after 6s the total of 10 requests will be processed.\n*NOTE: If you don't set `--burst-rate` option, the amount is default to 1*\n\n## Dynamic url feature\n\nYou can use `--rand-regex-url` option to generate random url for each connection.\n\n```sh\noha --rand-regex-url http:\u002F\u002F127.0.0.1\u002F[a-z][a-z][0-9]\n```\n\nEach Urls are generated by [rand_regex](https:\u002F\u002Fgithub.com\u002Fkennytm\u002Frand_regex) crate but regex's dot is disabled since it's not useful for this purpose and it's very inconvenient if url's dots are interpreted as regex's dot.\n\nOptionally you can set `--max-repeat` option to limit max repeat count for each regex. e.g http:\u002F\u002F127.0.0.1\u002F[a-z]* with `--max-repeat 4` will generate url like http:\u002F\u002F127.0.0.1\u002F[a-z]{0,4}\n\nCurrently dynamic scheme, host and port with keep-alive are not works well.\n\n## URLs from file feature\n\nYou can use `--urls-from-file` to read the target URLs from a file. Each line of this file needs to contain one valid URL as in the example below.\n\n```\nhttp:\u002F\u002Fdomain.tld\u002Ffoo\u002Fbar\nhttp:\u002F\u002Fdomain.tld\u002Fassets\u002Fvendors-node_modules_highlight_js_lib_index_js-node_modules_tanstack_react-query_build_modern-3fdf40-591fb51c8a6e.js\nhttp:\u002F\u002Fdomain.tld\u002Fimages\u002Ftest.png\nhttp:\u002F\u002Fdomain.tld\u002Ffoo\u002Fbar?q=test\nhttp:\u002F\u002Fdomain.tld\u002Ffoo\n```\n\nSuch a file can for example be created from an access log to generate a more realistic load distribution over the different pages of a server. \n\nWhen this type of URL specification is used, every request goes to a random URL given in the file.\n\n# Contribution\n\nFeel free to help us!\n\nHere are some areas which need improving.\n\n- Write tests\n- Improve tui design.\n  - Show more information?\n- Improve speed\n  - I'm new to tokio. I think there are some space to optimize query scheduling.\n","oha 是一个用于对 Web 应用进行负载测试的小工具，能够实时显示 TUI 动画。它使用 Rust 语言编写，并基于 tokio 异步运行时和 ratatui 终端用户界面库构建，支持 HTTP 和 HTTP2 协议，同时提供实验性的 HTTP3 支持。oha 的设计灵感来源于 rakyll\u002Fhey 项目，但通过引入 TUI 提供了更加直观的实时反馈。该工具适用于需要快速评估 Web 服务性能、进行压力测试或基准测试的场景。其简洁的命令行界面及丰富的功能选项使得 oha 成为了开发者和运维人员的理想选择。",2,"2026-06-11 03:03:42","top_language"]