{"id":13514998,"url":"https://github.com/issmirnov/zap","last_synced_at":"2025-04-10T08:30:46.372Z","repository":{"id":17813319,"uuid":"82765221","full_name":"issmirnov/zap","owner":"issmirnov","description":"Blazing fast web shortcuts.","archived":false,"fork":false,"pushed_at":"2024-03-07T17:41:55.000Z","size":2532,"stargazers_count":77,"open_issues_count":2,"forks_count":7,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-06T11:04:45.009Z","etag":null,"topics":["app","go","shortcut"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/issmirnov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-22T05:38:33.000Z","updated_at":"2024-03-29T19:00:12.000Z","dependencies_parsed_at":"2024-03-07T18:54:54.916Z","dependency_job_id":null,"html_url":"https://github.com/issmirnov/zap","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/issmirnov%2Fzap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/issmirnov%2Fzap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/issmirnov%2Fzap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/issmirnov%2Fzap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/issmirnov","download_url":"https://codeload.github.com/issmirnov/zap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248185218,"owners_count":21061474,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["app","go","shortcut"],"created_at":"2024-08-01T05:01:05.163Z","updated_at":"2025-04-10T08:30:46.070Z","avatar_url":"https://github.com/issmirnov.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Zap\n\n[![CircleCI](https://circleci.com/gh/issmirnov/zap.svg?style=svg)](https://circleci.com/gh/issmirnov/zap)\n[![Release](https://img.shields.io/github/release/issmirnov/zap.svg?style=flat-square)](https://github.com/issmirnov/zap/releases/latest)\n![Total Downloads](https://img.shields.io/github/downloads/issmirnov/zap/total.svg)\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)\n[![Go Report Card](https://goreportcard.com/badge/github.com/issmirnov/zap?style=flat-square)](https://goreportcard.com/report/github.com/issmirnov/zap)\n[![Powered By: GoReleaser](https://img.shields.io/badge/powered%20by-goreleaser-green.svg?style=flat-square)](https://github.com/goreleaser)\n\nZap is a powerful tool that allows you to define universal web shortcuts in a simple config file. Faster than bookmarks, and works in any app!\n\n![zap demo gif](zap_demo.gif)\n\n## Overview\n\nZAP is fast golang app that sends 302 redirects. It's insanely fast, maxing out at over 150k qps. It helps people be more efficient by providing simple shortcuts for common pages.\n\nIt can help save keystrokes on any level of the URL. In the example above, the user types `gh/z` and zap expands `gh` into `github.com` and `z` into `issmirnov/zap`. There is no limit to how deep you can go. Zap can be useful for shortening common paths. If your or your company has many projects at `company.com/long/and/annoying/path/name_here` zap can turn this into `c/name_here`, or `c/p/name_here` - it's all in your hands.\n\nZap runs as an HTTP service, and can live on the standard web ports or behind a proxy. It features hot reloading of the config, super low memory footprint and amazing durability under heavy loads.\n\n## Installation\n\n### Ansible\n\nIf you know how to use ansible, head over to the [ansible galaxy](https://galaxy.ansible.com/issmirnov/zap/) and install this role as `issmirnov.zap`. I've done the heavy lifting for you. If you want to do this by hand, read on.\n\n### OSX: brew install\n\n1. `brew install issmirnov/apps/zap`\n2. `sudo brew services start zap`\n3. Add shortcuts to `/usr/local/etc/zap/c.yml`\n3. Enjoy!\n\nIf you already have port 80 in use, you can run zap behind a reverse proxy.\n\n1. Change the port in the zap plist config: `sed -i '' 's/8927/80/'  /usr/local/Cellar/zap/*/homebrew.mxcl.zap.plist`\n2. Start zap as user service: `brew services start zap`\n3. Configure your web server to act as a reverse proxy. Here's an example for nginx:\n\n```nginx\n# File: /usr/local/etc/nginx/servers/zap.conf\nserver {\n    listen 80; # Keep as 80, make sure nginx listens on 80 too\n    server_name e g; # Put all of your top level shortcuts here - so just the first children in the config.\nlocation / {\n        proxy_http_version 1.1;\n        proxy_pass http://localhost:8927;\n        proxy_set_header X-Forwarded-Host $host;\n        #proxy_set_header Host $host;\n    }\n}\n```\n\nRestart your web server and test the result: `curl -I -L -H 'Host: g' localhost/z`\n\n### Ubuntu\n\nNote: This section applies to systemd installations only (Ubuntu, Redhat, Fedora). If you are running ubuntu 14.10 or below, you'll have to use [upstart](https://www.digitalocean.com/community/tutorials/the-upstart-event-system-what-it-is-and-how-to-use-it).\n\n1. Add the zap user: `sudo adduser --system --no-create-home --group zap`\n\n2. Create the service definition at `/etc/systemd/system/zap.service`. If you are running zap behind a web server, use the following config:\n\n```ini\n[Unit]\nDescription=Zap (URL text expander)\nAfter=syslog.target\nAfter=network.target\n\n[Service]\nType=simple\nUser=zap\nGroup=zap\nWorkingDirectory=/etc/zap\nExecStart=/usr/local/bin/zap -port 8927 -config c.yml\nRestart=always\nRestartSec=2s\n\n[Install]\nWantedBy=multi-user.target\n```\n\nIf you are running standalone:\n```ini\n[Unit]\nDescription=Zap (URL text expander)\nAfter=syslog.target\nAfter=network.target\n\n[Service]\nType=simple\nUser=root\nGroup=zap\nWorkingDirectory=/etc/zap\nExecStart=/usr/local/bin/zap -port 80 -config c.yml\nRestart=always\nRestartSec=2s\n\n[Install]\nWantedBy=multi-user.target\n```\n\nYou'll notice the difference is that we have to run as `root` in order to bind to port 80. *If you know of a way to launch a go app under setuid and then drop privileges, please send a PR*\n\n3. Start your new service: `sudo systemctl start zap` and make sure it's running: `sudo systemctl status zap`\n\n\n### Configuration\n\nThe config file is located at `/usr/local/etc/zap/c.yml` on OSX. For ubuntu, you will have to create `/etc/zap/c.yml` by hand.\n\nOpen up `c.yml` and update the mappings you would like. You can nest arbitrarily deep. Expansions work on strings and ints. Notice that we have three reserved keywords available: `expand`, `query`, and `port`.\n\n- `expand` - takes a short token and expands it to the specified string. Turns `z` into `zap/`,\n- `query` - acts almost like the `expand` option, but drops the separating slash between query expansion and search term (`example.com?q=foo` instead of `example.com?q=/foo`).\n- `port` - only valid as the first child under a host. Takes an int and appends it as `:$INT` to the host defined. See the usage in the [sample config](c.yml)\n\nAdditionally, you can use `\"*\"` to capture a path element that should be retained as-is while also allowing for expansion of later elements to take place.\n\nImportant gotcha: yaml has [reserved types](http://yaml.org/type/bool.html) and thus `n`, `y`, `no` and the like need to be quoted. See the sample config.\n\nWhen you add a new shortcut, you need to indicate to your web browser that it's not a search term. You can do this by typing it in once with just a slash. For example, if you add a shortcut `g/z` -\u003e `github.com/issmirnov/zap`, if you try `g/z` right away you will get taken to the search page. Instead, try `g/` once, and then `g/z`. This initial step only needs to be taken once per new shortcut.\n\nZap supports hot reloading, so simply save the file when you are done and test out your new shortcut. Note: If the shortcut does not work, make sure your YAML is correct and that zap is not printing any errors. You can test this by stopping zap and starting it manually - it should print any issues to stdout. You can also view the parsed config with `curl localhost:$ZAP_PORT/varz` - this will print the JSON representation of the config. If you see unexpected values, check your [YAML syntax](https://learnxinyminutes.com/docs/yaml/).\n\nFor the advanced users: remember to reload your webserver and `dnsmasq`, depending on your setup.\n\n#### Examples\n\nYou can configure your `c.yml` file endlessly. Here are some examples to get inspire your creativity:\n\n```yaml\ne:\n  expand: example.com\n  ssl_off: yes\nf:\n  expand: facebook.com\n  g:\n    expand: groups\n    s:\n      expand: BerkeleyFreeAndForSale\n    p:\n      expand: \"2204685680\"\n  php:\n    expand: groups/2204685680/\ng:\n  expand: github.com\n  d:\n    expand: issmirnov/dotfiles\n  s:\n    query: search?q=\n    ak:\n      expand: apache/kafka\n  z:\n    expand: issmirnov/zap\nr:\n  expand: reddit.com/r\nl:\n  expand: localhost\n  ssl_off: yes\n  p:\n    port: 8080\n  \"n\":\n    port: 9001\nak:\n  expand: kafka.apache.org\n    hi:\n      expand: contact\n    \"*\":\n      j:\n        expand: javadoc/index.html?overview-summary.html\n      d:\n        expand: documentation.html\n```\n\nWith this config, you can use the following queries:\n\n  - `g/z` -\u003e github.com/issmirnov/zap\n  - `f/zuck` -\u003e facebook.com/zuck\n  - `f/php` -\u003e facebook.com/groups/2204685680/\n  - `r/catsstandingup` -\u003e reddit.com/r/catsstandingup\n  - `ak/hi` -\u003e kafka.apache.org/contact\n  - `ak/23/j` -\u003e kafka.apache.org/23/javadoc/index.html?overview-summary.html\n\n### Troubleshooting\n\n- If you zap doesn't appear to be running, try `sudo brew services restart zap`. If you are running the standalone version you need sudo access for port 80.\n- If you are using Safari, you will get Google searches instead. If you know of a workaround, please let me know.\n\n### Additional Information\n\n\n#### Zap flags:\n\n- `-config` - path to config file. Default is `./c.yml`\n- `-port` - port to bind to. Default is 8927. Use 80 in standalone mode.\n- `-host` - default is 127.0.0.1. Use 0.0.0.0 for a public server.\n- `-advertise` - which address to use when populating `/etc/hosts`.\n  This is useful when running zap behind `dnsmasq`, so that the host bind and advertised address can differ.\n\n\n### DNS management via /etc/hosts\n\nZap will attempt to keep the `/etc/hosts` file in sync with the configuration specified. This is assumed to be a reasonable default. If you wish to disable this behavior, run zap under a user that does not have write permissions to that file.\n\nAs long as you don't touch the delimiters used by zap (`### Zap Shortcuts :start ##` and `### Zap Shortcuts :end ##`) you can edit the hosts file as you wish. If those delimiters are missing, zap will append them to the file. You shouldn't have problems if you manage your hosts file in a reasonable manner.\n\nFor the advanced users running zap on a server on an internal network, I suggest looking into `dnsmasqd` - this will allow all your clients to utilize these shortcuts globally.\n\n\n## Benchmarks\n\nBenchmarked with [wrk2](https://github.com/giltene/wrk2) on Ubuntu 16.04 using an i5 4590 CPU.\n```bash\n# Maxing out QPS.\n$ wrk -t2 -c10 -d30s -R500000  http://127.0.0.1:8989/h\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency     3.40s     1.96s    6.79s    57.82%\n    Req/Sec    80.22k   320.00    80.57k    50.00%\nRequests/sec: 161077.54\n\n# Getting max users while longest request under 15ms\n$ ./wrk -t2 -c10 -d20s -R120000 http://127.0.0.1:8989/h\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency     1.15ms    0.93ms  14.38ms   81.79%\n    Req/Sec    63.24k     7.18k  110.89k    76.92%\nRequests/sec: 119932.12\n\n```\nAs you can see, zap peaks at around ~160k qps, and can sustain ~120k qps with an average response under 15ms.\n\nNote: The config used was:\n\n```yaml\ne:\n  expand: example.com\n  a:\n    expand: apples\n  b:\n    expand: bananas\ng:\n  expand: github.com\n  d:\n    expand: issmirnov/dotfiles\n  s:\n    query: search?q=\n  z:\n    expand: issmirnov/zap\n'127.0.0.1:8989':\n  expand: '127.0.0.1:8989'\n  h:\n    expand: healthz\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n\n## Contributors\n\n- [Ivan Smirnov](http://ivansmirnov.name)\n- [Chris Egerton](https://github.com/C0urante)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fissmirnov%2Fzap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fissmirnov%2Fzap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fissmirnov%2Fzap/lists"}