{"id":15097183,"url":"https://github.com/adhocore/go-urlsh","last_synced_at":"2026-03-17T23:35:00.532Z","repository":{"id":37256632,"uuid":"300478933","full_name":"adhocore/go-urlsh","owner":"adhocore","description":"Golang URL shortener and bookmarker service with UI, API, Cache, Hits Counter and forwarder using postgres and redis in backend, bulma in frontend. Think of it as self hosting ready url shortener.","archived":false,"fork":false,"pushed_at":"2025-04-15T00:00:00.000Z","size":539,"stargazers_count":149,"open_issues_count":1,"forks_count":21,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-24T10:46:39.456Z","etag":null,"topics":["adhocore","go","go-url-shortener","golang","postgres","self-hosted","url-shortener","urlshortener"],"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/adhocore.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"adhocore","custom":["https://paypal.me/ji10"]}},"created_at":"2020-10-02T02:19:21.000Z","updated_at":"2025-08-31T09:31:17.000Z","dependencies_parsed_at":"2024-11-23T06:02:20.253Z","dependency_job_id":"cc7d9bec-789d-4723-ad43-40dc60d14bc1","html_url":"https://github.com/adhocore/go-urlsh","commit_stats":{"total_commits":214,"total_committers":4,"mean_commits":53.5,"dds":0.08878504672897192,"last_synced_commit":"f726cde3e247f824fa41036069d6330065308e8d"},"previous_names":["adhocore/go-urlsh"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/adhocore/go-urlsh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adhocore%2Fgo-urlsh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adhocore%2Fgo-urlsh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adhocore%2Fgo-urlsh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adhocore%2Fgo-urlsh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adhocore","download_url":"https://codeload.github.com/adhocore/go-urlsh/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adhocore%2Fgo-urlsh/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30290902,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"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":["adhocore","go","go-url-shortener","golang","postgres","self-hosted","url-shortener","urlshortener"],"created_at":"2024-09-25T16:05:07.331Z","updated_at":"2026-03-09T10:01:33.256Z","avatar_url":"https://github.com/adhocore.png","language":"Go","funding_links":["https://github.com/sponsors/adhocore","https://paypal.me/ji10","https://www.paypal.me/ji10/15usd","https://www.paypal.me/ji10/25usd","https://www.paypal.me/ji10/50usd"],"categories":["Go"],"sub_categories":[],"readme":"# urlsh\n\n[![Latest Version](https://img.shields.io/github/release/adhocore/urlsh.svg?style=flat-square)](https://github.com/adhocore/urlsh/releases)\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)\n[![lint](https://github.com/adhocore/urlsh/actions/workflows/lint-github-action.yml/badge.svg)](https://github.com/adhocore/urlsh/actions/workflows/lint-github-action.yml)\n[![test](https://github.com/adhocore/urlsh/actions/workflows/test-github-action.yml/badge.svg)](https://github.com/adhocore/urlsh/actions/workflows/test-github-action.yml)\n[![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=URL+shortener+app+built+on+Golang\u0026url=https://github.com/adhocore/urlsh\u0026hashtags=go,golang,url,urlshortener)\n[![Support](https://img.shields.io/static/v1?label=Support\u0026message=%E2%9D%A4\u0026logo=GitHub)](https://github.com/sponsors/adhocore)\n\u003c!-- [![Donate 15](https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square\u0026label=donate+15)](https://www.paypal.me/ji10/15usd)\n[![Donate 25](https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square\u0026label=donate+25)](https://www.paypal.me/ji10/25usd)\n[![Donate 50](https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square\u0026label=donate+50)](https://www.paypal.me/ji10/50usd) --\u003e\n\n\n**urlsh** is URL shortener application built on [Go](https://golang.org) language.\n\nIt does not use external libraries except the [`gorm`](http://gorm.io) for\n[`postgres`](https://github.com/go-gorm/postgres) database and minimal redis\nmodule [redigo](https://github.com/gomodule/redigo).\n\n![URLSH](./assets/urlsh.png)\n\n# Usage\n\n#### Web client\n\nJust visit the homepage of your urlsh deployment site. You can also integrate API for programmatic usage.\n\n#### Terminal client\n\nIf you live inside the command line terminal, you can install a client:\n```sh\ngo get github.com/adhocore/urlsh/cmd/urlshc\n```\n\nor, with newer go versions\n```sh\ngo install github.com/adhocore/urlsh/cmd/urlshc\n```\n\nMake sure `$GOPATH` or `$HOME/go/bin` is in your `$PATH` or `%path%`, then use it like so:\n```sh\n# show help\nurlshc -h\n\n# shorten a url\nurlshc -url 'https://your.long.url/here'\n\n# shorten a url with keywords and expiry date\nurlshc -url 'https://your.long.url/here' -keywords 'word-1,word2' -expires '2022-12-31'\n\n# if you have self hosted or local instance of urlsh, pass in URLSH_HOST (with domain only)\nURLSH_HOST=https://your.urlsh-instance.com urlshc -url 'https://your.long.url/here'\n```\n\nRead below for self hosting, API integration and/or contributing to *urlsh*.\n\n___\n\n## Getting source\n\n```sh\ngit clone git@github.com:adhocore/urlsh.git\ncd urlsh\n```\n\n## Configuring\n\nIt should be configured using env variables.\n\nPlease check [.env.example](./.env.example) for available variables and explanation.\n\n`DATABASE_URL` is always required and is string of the following form:\n\n```\nDATABASE_URL=postgres://user:pass@host:port/dbname\n```\n\nWhen running *urlsh* with docker-compose, the **preferred** way, `DATABASE_URL` is\nautomatically set from [`POSTGRES_*`](https://hub.docker.com/_/postgres) variables.\n\n\u003e Please note that `urlsh` does not ship with `.env` loader so to run it in bare metal,\none needs to use `export KEY=VALUE` or `source .env` manually.\n\nIf `REDIS_URL` is provided with `redis://host:port`, then it will cache popular urls,\nthe popularity threshold is hard coded to minimal value in `common.constant`.\nThe cache will sync when short url is deleted and sometimes when expired.\nThe hit counters will however sync in realtime.\n\n## Setting up docker\n\nTo set up dockerized `urlsh`, run the commands below:\n\n```sh\n# first time only\ncp .example.env .env\n\n# change auth token for admin if you want in `.env` file\n# APP_ADMIN_TOKEN=\u003csomething crypto secure random hash\u003e\n\ndocker-compose up\n```\n\nAfter a few seconds, you should be able to browse to [localhost:2000](http://localhost:2000).\n\n## Testing\n\nFor running tests,\n\n```sh\ndocker-compose exec urlsh sh -c \"APP_ENV=test go test ./...\"\n\n# for coverage\ndocker-compose exec urlsh sh -c \"APP_ENV=test go test -cover ./...\"\n```\n\n`APP_ENV=test` is not required but ensures that tests are run against clone database with name prefixed by `test_`.\nNormally test db is already prepared if you use `docker-compose`.\n\n---\n## API Endpoints\n\n### GET /status\n\nStatus route for health/status check.\n\n#### Response payload\n\n```json\n{\n    \"status\": 200,\n    \"message\": \"it works\"\n}\n```\n\n---\n### POST /api/urls\n\nCreates a new short code for given URL.\n\n#### Request example\n\n- url: string, required, http/https/ftp only\n- expires_on: string, optional, utc date `yyyy-mm-dd hh:mm:ss`, default=`9999-01-01`\n- keywords: array of strings, 2-25 chars each, max 10 keywords\n\n```json\n{\n    \"url\": \"http://somedomain.com/some/very/long/url\",\n    \"expires_on\": \"\",\n    \"keywords\": [\"key\", \"word\"]\n}\n```\n\n#### Response example\n\n```json\n{\n    \"status\": 200,\n    \"short_code\": \"qaFxz\",\n    \"short_url\": \"http://localhost:2000/qaFxz\"\n}\n```\n\n\u003e If env var `APP_ALLOW_DUPE_URL` is set to 0 or empty, then trying to shorten same URL again\nwill return status 409 and payload will contain existing `short_code`.\n\u003e However if existing `short_code` is deleted, it will be shortened as usual.\n\n---\n### GET /{shortCode}\n\nRedirects the shortcode to original long URL.\n\n##### Response payload\n\nIn case short code exists it responds with 301 redirect.\n\nIf the short code is expired or deleted, it responds like so:\n\n```json\n{\n    \"status\": 410,\n    \"message\": \"requested resource is not available\"\n}\n```\n\n---\n### GET /api/admin/urls\n\n#### Authentication\n\nToken required in `Authorization` header like so:\n```ini\nAuthorization: Bearer \u003ctoken\u003e\n```\n\n#### Request query\n\nThe query params are *optional*.\n\n```ini\npage=\u003cint\u003e\nshort_code=\u003cstr\u003e\nkeyword=\u003cstr\u003e\n```\n\n*Examples:*\n\n- `/api/admin/urls?short_code=somecode`\n- `/api/admin/urls?page=1\u0026keyword=something`\n\n#### Response example\n\nResponse contains multiple matching url object inside `urls` array.\n\n```json\n{\n    \"status\": 200,\n    \"urls\": [\n        {\n            \"short_code\": \"X5JkFd\",\n            \"origin_url\": \"http://somedomain.com/some/very/long/url\",\n            \"hits\": 1,\n            \"is_deleted\": false,\n            \"expires_on\": \"9999-01-01T00:00:00Z\"\n        }\n    ]\n}\n```\n\n---\n### DELETE /api/admin/urls\n\n#### Authentication\n\nToken required in `Authorization` header like so:\n```\nAuthorization: Bearer \u003ctoken\u003e\n```\n\n#### Request query\n\nQuery param `short_code` is requied.\n\n*Example*: `/api/admin/urls?short_code=somecode`\n\n#### Response example\n\nIf delete success:\n\n```json\n{\n    \"status\": 200,\n    \"deleted\": true\n}\n```\n\nIf the code does not exist:\n\n```json\n{\n    \"status\": 404,\n    \"message\": \"the given short code is not found\"\n}\n```\n\n---\n### Using postman\n\n**urlsh** comes with [postman](./postman) collection and environment to aid manual testing of endpoints.\n\nOpen the postman app, click `Import`  at top left, select `Folder` and drag/choose `postman` folder of this repo.\nYou may need to adjust the `token` in postman `urlsh` env if you have configured `APP_ADMIN_TOKEN`.\n\nThe collection comes with post/pre request hooks for requests so you can just run the endpoints one after another in postman UI.\n\n\u003e For `redirect` request, you have to disable postman follow redirects from `Settings \u003e General \u003e Automatically follow redirects`.\n\n### License\n\nPlease check [license](./LICENSE) file.\n\n---\n### Other projects\nMy other golang projects you might find interesting and useful:\n\n- [**gronx**](https://github.com/adhocore/gronx) - Lightweight, fast and dependency-free Cron expression parser (due checker), task scheduler and/or daemon for Golang (tested on v1.13 and above) and standalone usage.\n- [**fast**](https://github.com/adhocore/fast) - Check your internet speed with ease and comfort right from the terminal.\n- [**goic**](https://github.com/adhocore/goic) - Go Open ID Connect, is OpenID connect client library for Golang, supports the Authorization Code Flow of OpenID Connect specification.\n- [**chin**](https://github.com/adhocore/chin) - A GO lang command line tool to show a spinner as user waits for some long running jobs to finish.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadhocore%2Fgo-urlsh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadhocore%2Fgo-urlsh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadhocore%2Fgo-urlsh/lists"}