{"id":13525532,"url":"https://github.com/barats/ohUrlShortener","last_synced_at":"2025-04-01T05:31:44.460Z","repository":{"id":37428049,"uuid":"466312589","full_name":"barats/ohUrlShortener","owner":"barats","description":"适合中小型社区网站使用的企业级短链接服务系统，支持短链接生产、查询及302转向，并自带点击量统计、独立IP数统计、访问日志","archived":false,"fork":false,"pushed_at":"2023-09-15T03:12:42.000Z","size":33516,"stargazers_count":420,"open_issues_count":2,"forks_count":69,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-24T01:15:37.559Z","etag":null,"topics":["golang","productivity","screenshot","shorturl","shorturl-services","url-shortener","urlshortener"],"latest_commit_sha":null,"homepage":"https://www.ohurls.cn","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/barats.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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}},"created_at":"2022-03-05T00:53:23.000Z","updated_at":"2025-03-19T02:03:47.000Z","dependencies_parsed_at":"2024-01-13T16:22:13.923Z","dependency_job_id":"306e1bd5-6d65-4bcc-9b81-5d8a7450d1ff","html_url":"https://github.com/barats/ohUrlShortener","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barats%2FohUrlShortener","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barats%2FohUrlShortener/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barats%2FohUrlShortener/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/barats%2FohUrlShortener/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/barats","download_url":"https://codeload.github.com/barats/ohUrlShortener/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246591279,"owners_count":20801981,"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":["golang","productivity","screenshot","shorturl","shorturl-services","url-shortener","urlshortener"],"created_at":"2024-08-01T06:01:19.703Z","updated_at":"2025-04-01T05:31:42.633Z","avatar_url":"https://github.com/barats.png","language":"Go","funding_links":[],"categories":["Go","ShortURL"],"sub_categories":[],"readme":"# ohUrlShortener\n\n 适合中小型社区网站使用的企业级短链接服务系统，支持短链接生产、查询及302转向，并自带点击量统计、独立IP数统计、访问日志查询：\n\n1. 支持 Docker One Step Start 部署启动\n1. 支持短链接生产、查询、存储、302转向\n1. 支持访问日志查询、访问量统计、独立IP数统计\n1. 支持 HTTP API 方式新建短链接、禁用/启用短链接、查看短链接统计信息、管理员设置\n1. 支持访问日志导出，方便线下分析\n\n![Screenshot](screenshot.jpg)\n\n\u003cp style=\"text-align: center\"\u003e\n\u003ca target=\"_blank\" href=\"https://www.ohurls.cn\"\u003ehttps://www.ohurls.cn\u003c/a\u003e\u003cbr/\u003e\u003cbr/\u003e\n\u003ca target=\"_blank\" href=\"https://github.com/barats/ohUrlShortener/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/barats/ohUrlShortener\"/\u003e\u003c/a\u003e\n\u003ca target=\"_blank\" href=\"https://github.com/barats/ohUrlShortener/network/members\"\u003e\u003cimg src=\"https://img.shields.io/github/forks/barats/ohUrlShortener\"/\u003e\u003c/a\u003e\n\u003ca target=\"_blank\" href=\"https://github.com/barats/ohUrlShortener/issues\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/barats/ohUrlShortener\"/\u003e\u003c/a\u003e  \n\u003ca target=\"_blank\" href='https://gitee.com/barat/ohurlshortener/stargazers'\u003e\u003cimg src='https://gitee.com/barat/ohurlshortener/badge/star.svg?theme=dark' /\u003e\u003c/a\u003e\n\u003ca target=\"_blank\" href='https://gitee.com/barat/ohurlshortener/members'\u003e\u003cimg src='https://gitee.com/barat/ohurlshortener/badge/fork.svg?theme=dark' /\u003e\u003c/a\u003e\n\u003ca target=\"_blank\" href='https://www.oschina.net/comment/project/64133'\u003e\u003cimg src='https://www.oschina.net/comment/badge/project/64133'/\u003e\u003c/a\u003e \n\u003ca target=\"_blank\" href=\"https://hub.docker.com/r/baratsemet/ohurlshortener-portal\"\u003e\u003cimg src=\"https://img.shields.io/docker/pulls/baratsemet/ohurlshortener-portal\" alt=\"Portal Docker Pulls\"\u003e\u003c/a\u003e\n\u003ca target=\"_blank\" href=\"https://hub.docker.com/r/baratsemet/ohurlshortener-admin\"\u003e\u003cimg src=\"https://img.shields.io/docker/pulls/baratsemet/ohurlshortener-admin\" alt=\"Admin Docker Pulls\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\n## 快速使用\n\nDocker 一步启动所有服务，运行 `docker/one_step_start.sh` ，该命令将会：  \n1. 拉取 [baratsemet/ohurlshortener-admin](https://hub.docker.com/r/baratsemet/ohurlshortener-admin) 镜像（本地构建可查看 `docker/admin.Dockerfile`）\n1. 拉取 [baratsemet/ohurlshortener-portal](https://hub.docker.com/r/baratsemet/ohurlshortener-portal) 镜像（本地构建镜像可查看`docker/portal.Dockerfile`）\n1. 通过 `docker/pull_build.yml` 其他描述内容构建 `redis` 和 `postgresql` 镜像及服务，并对其运行状态做判断，等待缓存和数据库服务正常之后，再启动其他必要服务 (本地构建镜像请查阅 `local_build.yml`) \n1. 构建名为 `network_ohurlshortener` 的虚拟网络供上述服务使用\n1. 开启本机 `9091`、`9092` 端口分别应对 `ohUrlShortener-Portal` 及 `ohUrlShortener-Admin` 应用\n\n\n## 参数说明  \n\n```shell\nohurlshortener [-c config_file] [-s admin|portal|\u003comit to start both\u003e]  \n```\n\n## 配置文件\n根目录下 `config.ini` 中存放着关于 ohUrlShortener 短链接系统的一些必要配置，请在启动应用之前确保这些配置的正确性\n\n```ini\n[app]\n\n# 短链接系统本地启动端口\nport = 9091\n\n# 短链接系统管理后台本地启动端口\nadmin_port = 9092\n\n# 例如：https://t.cn/ 是前缀(不要忘记最后一个/符号)\nurl_prefix = http://localhost:9091/\n\n# captcha 验证码默认会写入内存，也可以指定存储到 redis\n[captcha]\nstore = memory\n# store = redis\n\n# Redis 配置信息 \n[redis]\nhost = redis:6379\ndatabase = 0\nusername =\npassword =\npool_size = 50\n\n# Redis 集群配置\n[redis-cluster]\nhosts = localhost:6371,localhost:6372,localhost:6373,localhost:6374,localhost:6375,localhost:6376\nusername = \npassword = \npool_size = 50\n\n# Postgresql 数据库配置信息\n[postgres]\nhost = localhost\nport = 5432\nuser = postgres\npassword = xxx\ndatabase = oh_url_shortener\nmax_open_conn = 20\nmax_idle_conn = 5\n```\n\n## Admin 后台默认帐号 \n默认帐号: `ohUrlShortener`  \n默认密码: `-2aDzm=0(ln_9^1`  \n\n数据库中存储的是加密后的密码，在 [`structure.sql`](structure.sql) 中标有注释，如果需要自定义其他密码，可以修改这里  \n\n加密规则 `storage/users_storage.go` 中\n\n```golang \nfunc PasswordBase58Hash(password string) (string, error) {\n\tdata, err := utils.Sha256Of(password)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn base58.Encode(data), nil\n}\n```\n\n亦可参照 `storage/users_storage_test.go` 中的 `TestNewUser()` 方法\n\n## HTTP API 支持\n\n管理端 HTTP API 支持请参阅 [ohUrlShortener HTTP API](API.md)\n\n```golang\napi := router.Group(\"/api\", controller.APIAuthHandler())\napi.POST(\"/account\", controller.APINewAdmin)\napi.PUT(\"/account/:account/update\", controller.APIAdminUpdate)\napi.POST(\"/url\", controller.APIGenShortUrl)\napi.GET(\"/url/:url\", controller.APIUrlInfo)\napi.DELETE(\"/url/:url\", controller.APIDeleteUrl)\napi.PUT(\"/url/:url/change_state\", controller.APIUpdateUrl)\n```\n\n## 短链接在应用启动时会存入 Redis 中\n\n所有短链接再系统启动时会以 `Key(short_url) -\u003e Value(JSON{original_url,open_type})` 的形式存储在 Redis 中。\n\n### 1. 为什么要这么做？  \n\n当短链接的查询请求进入应用时，为了能够更快、更准确的将用户请求转向到目标链接，与传统的方式从数据库中查询相比，直接从 Redis 中获取目标链接就会显得更有价值。\n\n### 2. 这种处理方式有什么缺点？\n\n理论上来说，如果 Redis 所在的服务器的内存较大的话，存储10w个Key也是可以的。但是，硬件条件不允许的情况下，就需要控制 Redis 中的 Key 数量（主要是怕机器扛不住，Redis 本身的性能不会有问题）。这部分的功能扩展，考虑在将来的某个版本中实现并允许配置管理。\n\n### 3. 万一 \n\n考虑到可扩展性，多封装了一层 `service`，以便需要的时候在业务逻辑层进行自定义扩展，eg：将 key 查询改成数据库查询等。  \n\n## 短链接生产过程相关代码\n\n所在文件 `core/short_url.go` \n\n```golang\nfunc GenerateShortLink(initialLink string) (string, error) {\n\tif utils.EmptyString(initialLink) {\n\t\treturn \"\", fmt.Errorf(\"empty string\")\n\t}\n\turlHash, err := utils.Sha256Of(initialLink)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tstr := utils.Base58Encode(urlHash)\n\treturn str[:8], nil\n}\n```\n\n## 访问日志处理间隔：1分钟\n\n所在文件 `main.go` \n\n```golang\n//清理 Redis 中的访问日志的时间间隔\nconst AccessLogCleanInterval = 1 * time.Minute\n\nfunc startTicker() error {\n\tticker := time.NewTicker(AccessLogCleanInterval)\n\tfor range ticker.C {\n\t\tlog.Println(\"[StoreAccessLog] Start.\")\n\t\tif err := service.StoreAccessLogs(); err != nil {\n\t\t\tlog.Printf(\"Error while trying to store access_log %s\", err)\n\t\t}\n\t\tlog.Println(\"[StoreAccessLog] Finish.\")\n\t}\n\treturn nil\n}\n```\n\n## 当日 Top25 访问 URL 榜单处理间隔：5分钟\n所在文件 `main.go`\n\n```golang\n// Top25 榜单计算间隔\nTop25CalcInterval = 5 * time.Minute\n\nfunc startTicker2() error {\n\ttop25Ticker := time.NewTicker(Top25CalcInterval)\n\tfor range top25Ticker.C {\n\t\tlog.Println(\"[Top25Urls Ticker] Start.\")\n\t\tif err := storage.CallProcedureStatsTop25(); err != nil {\n\t\t\tlog.Printf(\"Error while trying to calculate Top25Urls %s\", err)\n\t\t}\n\t\tlog.Println(\"[Top25Urls Ticker] Finish.\")\n\t}\n\treturn nil\n}\n```\n\n## 仪表盘中几个相关统计处理间隔：5分钟\n所在文件 `main.go`\n\n```golang\n// 仪表盘页面中其他几个统计数据计算间隔\nStatsSumCalcInterval = 5 * time.Minute\n\nfunc startTicker4() error {\n\tstatsSumTicker := time.NewTicker(StatsSumCalcInterval)\n\tfor range statsSumTicker.C {\n\t\tlog.Println(\"[StatsSum Ticker] Start.\")\n\t\tif err := storage.CallProcedureStatsSum(); err != nil {\n\t\t\tlog.Printf(\"Error while trying to calculate StatsSum %s\", err)\n\t\t}\n\t\tlog.Println(\"[StatsSum Ticker] Finish.\")\n\t}\n\treturn nil\n}\n```\n\n## 全部访问日志统计处理间隔：30分钟\n所在文件 `main.go`\n\n```golang\n//全部访问日志分析统计的间隔\nStatsIpSumCalcInterval = 30 * time.Minute\n\nfunc startTicker3() error {\n\tstatsIpSumTicker := time.NewTicker(StatsIpSumCalcInterval)\n\tfor range statsIpSumTicker.C {\n\t\tlog.Println(\"[StatsIpSum Ticker] Start.\")\n\t\tif err := storage.CallProcedureStatsIPSum(); err != nil {\n\t\t\tlog.Printf(\"Error while trying to calculate StatsIpSum %s\", err)\n\t\t}\n\t\tlog.Println(\"[StatsIpSum Ticker] Finish.\")\n\t}\n\treturn nil\n}\n```\n\n## License \n\nohUrlShortener 以《木兰宽松许可证》 第2版 为开源协议发布  \n\n```\nCopyright (c) [2023] [巴拉迪维]\n[ohUrlShortener] is licensed under Mulan PSL v2.\nYou can use this software according to the terms and conditions of the Mulan PSL v2.\nYou may obtain a copy of Mulan PSL v2 at:\n         http://license.coscl.org.cn/MulanPSL2\nTHIS SOFTWARE IS PROVIDED ON AN \"AS IS\" BASIS, WITHOUT WARRANTIES OF ANY KIND,\nEITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,\nMERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.\nSee the Mulan PSL v2 for more details.\n```\n\n## Contributor License Agreement\n\n在 **第一次提交 Pull Request 时** ，请您在 Pull Request 内容中明确写明「本人自愿接受并签署 [《ohUrlShortener Contributor License Agreement》](CLA.md)」，并在 Pull Request 信息中附带该协议链接信息。\n\n## Give Thanks To\n\n由衷感谢以下开源软件、框架等（包括但不限于）\n\n1. [gin-gonic/gin](https://github.com/gin-gonic/gin) \n2. [FomanticUI](https://fomantic-ui.com/)\n3. [dchest/captcha](https://github.com/dchest/captcha) \n4. [Masterminds/sprig](https://github.com/Masterminds/sprig)\n5. [go-redis/redis](https://github.com/go-redis/redis/) \n6. [jmoiron/sqlx](https://github.com/jmoiron/sqlx)\n7. [go-ini/ini](https://github.com/go-ini/ini)\n\n## ohUrlShortener \n1. [ohUrlShortener 短链接系统 v2.0 发布，指定「打开方式」功能支持](https://www.oschina.net/news/241622/ohurlshortener-2-0-released)\n1. [ohUrlShortener 短链接系统 v1.9 发布，Redis Cluster 集群支持](https://www.oschina.net/news/230519/ohurlshortener-1-9-released)\n1. [ohUrlShortener 短链接系统 v1.8 发布，API 问题处理](https://www.oschina.net/news/228559/ohurlshortener-1-8-released)\n1. [ohUrlShortener 短链接系统 v1.7 发布，安全更新](https://www.oschina.net/news/211116/ohurlshortener-1-7-released)\n1. [ohUrlShortener 短链接系统 v1.6 发布，统计功能增强](https://www.oschina.net/news/207439/ohurlshortener-1-6-released) \n1. [ohUrlShortener 短链接系统 v1.5 发布，管理功能增强](https://www.oschina.net/news/200621/ohurlshortener-1-5-released)\n1. [ohUrlShortener 短链接系统 v1.4 正式发布](https://www.oschina.net/news/194904/ohurlshortener-1-4-released)\n2. [ohUrlShortener 短链接系统 v1.3 发布，支持导出访问日志](https://www.oschina.net/news/193422/ohurlshortener-1-3-released)\n3. [ohUrlShortener 短链接系统 v1.2 正式发布](https://www.oschina.net/news/190546/ohurlshortener-1-2-released)\n1. [ohUrlShortener 短链接服务系统 1.0 发布](https://www.oschina.net/news/190168/ohurlshortener-1-0-released)\n4. 软件信息收录 [https://www.oschina.net/p/ohurlshortener](https://www.oschina.net/p/ohurlshortener)\n5. Gitee [https://gitee.com/barat/ohurlshortener](https://gitee.com/barat/ohurlshortener)\n6. Github [https://github.com/barats/ohUrlShortener](https://github.com/barats/ohUrlShortener)\n7. Gitlink [https://www.gitlink.org.cn/baladiwei/ohurlshortener](https://www.gitlink.org.cn/baladiwei/ohurlshortener)\n\n## Stargazers over time\n[![Stargazers over time](https://starchart.cc/barats/ohUrlShortener.svg)](https://starchart.cc/barats/ohUrlShortener)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbarats%2FohUrlShortener","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbarats%2FohUrlShortener","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbarats%2FohUrlShortener/lists"}