├── scripts ├── .gitignore └── build.bat ├── .gitattributes ├── admin ├── images │ ├── sort_asc.png │ ├── sort_both.png │ ├── sort_desc.png │ ├── sort_asc_disabled.png │ └── sort_desc_disabled.png ├── js │ ├── dataTables.foundation.min.js │ ├── jquery.dataTables.min.js │ └── jquery-3.2.1.min.js ├── css │ ├── dataTables.foundation.min.css │ └── jquery.dataTables.min.css └── index.html ├── .gitignore ├── go.mod ├── backend ├── backend.go ├── file.go └── mysql.go ├── LICENSE ├── README.md ├── go.sum ├── server.go └── web.go /scripts/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /admin/images/sort_asc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xtrafrancyz/golish/HEAD/admin/images/sort_asc.png -------------------------------------------------------------------------------- /admin/images/sort_both.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xtrafrancyz/golish/HEAD/admin/images/sort_both.png -------------------------------------------------------------------------------- /admin/images/sort_desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xtrafrancyz/golish/HEAD/admin/images/sort_desc.png -------------------------------------------------------------------------------- /admin/images/sort_asc_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xtrafrancyz/golish/HEAD/admin/images/sort_asc_disabled.png -------------------------------------------------------------------------------- /admin/images/sort_desc_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xtrafrancyz/golish/HEAD/admin/images/sort_desc_disabled.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | 16 | .idea/ 17 | 18 | config.ini 19 | db.json 20 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/xtrafrancyz/golish 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/fasthttp/router v1.4.18 7 | github.com/go-sql-driver/mysql v1.7.1 8 | github.com/valyala/fasthttp v1.46.0 9 | github.com/vharitonsky/iniflags v0.0.0-20180513140207-a33cd0b5f3de 10 | ) 11 | 12 | require ( 13 | github.com/andybalholm/brotli v1.0.5 // indirect 14 | github.com/klauspost/compress v1.16.3 // indirect 15 | github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect 16 | github.com/valyala/bytebufferpool v1.0.0 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /scripts/build.bat: -------------------------------------------------------------------------------- 1 | if not exist "build" mkdir build 2 | cd ../ 3 | 4 | set GOOS=windows 5 | set GOARCH=386 6 | go build -o scripts/build/golish-i386.exe 7 | rice append --exec scripts/build/golish-i386.exe 8 | 9 | set GOOS=windows 10 | set GOARCH=amd64 11 | go build -o scripts/build/golish-amd64.exe 12 | rice append --exec scripts/build/golish-amd64.exe 13 | 14 | set GOOS=linux 15 | set GOARCH=386 16 | go build -o scripts/build/golish-linux-i386 17 | rice append --exec scripts/build/golish-linux-i386 18 | 19 | set GOOS=linux 20 | set GOARCH=amd64 21 | go build -o scripts/build/golish-linux-amd64 22 | rice append --exec scripts/build/golish-linux-amd64 23 | -------------------------------------------------------------------------------- /backend/backend.go: -------------------------------------------------------------------------------- 1 | package backend 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | type Backend interface { 9 | GetLink(slug string) *Link 10 | TryClickLink(slug string) *Link 11 | GetAllLinks() []*Link 12 | Create(url string) (*Link, error) 13 | CreateCustom(slug, url string) (*Link, error) 14 | Delete(slug string) 15 | Edit(slug, url string) 16 | } 17 | 18 | type Link struct { 19 | Slug string `json:"slug"` 20 | Url string `json:"url"` 21 | Clicks uint64 `json:"clicks"` 22 | Created time.Time `json:"created"` 23 | } 24 | 25 | func (l *Link) String() string { 26 | return "Link(" + l.Slug + " => " + l.Url + ")" 27 | } 28 | 29 | func generateSlug(length int) string { 30 | // From: http://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang 31 | var chars = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 32 | s := make([]rune, length) 33 | for i := range s { 34 | s[i] = chars[rand.Intn(len(chars))] 35 | } 36 | 37 | return string(s) 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 xtrafrancyz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Golish 2 | Easy to use **Go** **Li**nk **Sh**ortener. Golish is not intended for tens of millions of shortened links 3 | because it tries to cache all links to improve performance. 4 | 5 | ![Golish screenshot](https://i.imgur.com/DAWpaxy.png "Golish screenshot") 6 | 7 | # Run 8 | 1. Download latest release 9 | 2. Create `config.ini` file ([Configuration](#configuration)) 10 | 3. Run `golish-**** -config config.ini` 11 | 12 | # Configuration 13 | - `host` -- Server bind host (default: 0.0.0.0). 14 | - `port` -- Server bind port (default: 34532). Put 80 here for default http server. 15 | - `slug-length` -- Length of the generated short url (default: 5). 16 | - `admin-path` -- Secret path with admin interface (default: admin (`example.com/@admin/`)). 17 | - `default-redirect` -- Address to redirect from root page (root page - `example.com/`). 18 | - `backend` -- Backend type **mysql** or **file** (default: file). 19 | - `mysql-host` -- Mysql server address (default: 127.0.0.1:3306). 20 | - `mysql-user` -- Mysql user (default: golish). 21 | - `mysql-password` -- Mysql password (default: golish). 22 | - `mysql-database` -- Mysql database name (default: golish). 23 | - `file-path` -- Database file path for **file** backend (default: db.json). 24 | 25 | ### Example of `config.ini` file 26 | ```ini 27 | port = 80 28 | admin-path = RANDOM_STRING 29 | default-redirect = https://google.com 30 | backend = mysql 31 | mysql-user = user99 32 | mysql-password = qwerty 33 | ``` 34 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= 2 | github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 3 | github.com/fasthttp/router v1.4.18 h1:elMnlFq527oZd8MHsuUpO6uLDup1exv8rXPfIjClDHk= 4 | github.com/fasthttp/router v1.4.18/go.mod h1:ZmC20Mn0VgCBbUWFDmnYzFbQYRfdGeKgpkBy0+JioKA= 5 | github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= 6 | github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= 7 | github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= 8 | github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 9 | github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk= 10 | github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= 11 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 12 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 13 | github.com/valyala/fasthttp v1.46.0 h1:6ZRhrFg8zBXTRYY6vdzbFhqsBd7FVv123pV2m9V87U4= 14 | github.com/valyala/fasthttp v1.46.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= 15 | github.com/vharitonsky/iniflags v0.0.0-20180513140207-a33cd0b5f3de h1:fkw+7JkxF3U1GzQoX9h69Wvtvxajo5Rbzy6+YMMzPIg= 16 | github.com/vharitonsky/iniflags v0.0.0-20180513140207-a33cd0b5f3de/go.mod h1:irMhzlTz8+fVFj6CH2AN2i+WI5S6wWFtK3MBCIxIpyI= 17 | -------------------------------------------------------------------------------- /admin/js/dataTables.foundation.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | DataTables Foundation integration 3 | ©2011-2015 SpryMedia Ltd - datatables.net/license 4 | */ 5 | (function(d){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return d(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);if(!b||!b.fn.dataTable)b=require("datatables.net")(a,b).$;return d(b,a,a.document)}:d(jQuery,window,document)})(function(d){var a=d.fn.dataTable,b=d('').appendTo("head");a.ext.foundationVersion=b.css("font-family").match(/small|medium|large/)?6:5;b.remove();d.extend(a.ext.classes, 6 | {sWrapper:"dataTables_wrapper dt-foundation",sProcessing:"dataTables_processing panel callout"});d.extend(!0,a.defaults,{dom:"<'row'<'small-6 columns'l><'small-6 columns'f>r>t<'row'<'small-6 columns'i><'small-6 columns'p>>",renderer:"foundation"});a.ext.renderer.pageButton.foundation=function(b,l,r,s,e,i){var m=new a.Api(b),t=b.oClasses,j=b.oLanguage.oPaginate,u=b.oLanguage.oAria.paginate||{},f,h,g,v=5===a.ext.foundationVersion,q=function(a,n){var k,o,p,c,l=function(a){a.preventDefault();!d(a.currentTarget).hasClass("unavailable")&& 7 | m.page()!=a.data.action&&m.page(a.data.action).draw("page")};k=0;for(o=n.length;k",{"class":t.sPageButton+" "+h,"aria-controls":b.sTableId,"aria-label":u[c],tabindex:b.iTabIndex,id:0===r&&"string"===typeof c?b.sTableId+"_"+c:null}).append(g?d("<"+g+"/>",{href:"#"}).html(f):f).appendTo(a),b.oApi._fnBindAction(p,{action:c},l))}};q(d(l).empty().html('