From 0664052a203defff181e26037a7692e97f751aea Mon Sep 17 00:00:00 2001 From: celestix Date: Sat, 12 Aug 2023 16:20:29 +0530 Subject: [PATCH] add support for sqlite database --- go.mod | 6 +++ go.sum | 12 ++++++ server.go | 5 ++- utils/shortener/in_sql.go | 84 ++++++++++++++++++++++++++++++++++++ utils/shortener/shortener.go | 2 + 5 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 utils/shortener/in_sql.go diff --git a/go.mod b/go.mod index c8944ad..22d46d1 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,13 @@ require ( ) require ( + github.com/AnimeKaizoku/cacher v1.0.1 // indirect github.com/andybalholm/brotli v1.0.5 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/klauspost/compress v1.16.3 // indirect + github.com/mattn/go-sqlite3 v1.14.17 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect + gorm.io/driver/sqlite v1.5.2 // indirect + gorm.io/gorm v1.25.3 // indirect ) diff --git a/go.sum b/go.sum index 3453472..248fd10 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,15 @@ +github.com/AnimeKaizoku/cacher v1.0.1 h1:rDjeDphztR4h234mnUxlOQWyYAB63WdzJB9zBg9HVPg= +github.com/AnimeKaizoku/cacher v1.0.1/go.mod h1:jw0de/b0K6W7Y3T9rHCMGVKUf6oG7hENNcssxYcZTCc= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= +github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c= @@ -10,3 +18,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/sqlite v1.5.2 h1:TpQ+/dqCY4uCigCFyrfnrJnrW9zjpelWVoEVNy5qJkc= +gorm.io/driver/sqlite v1.5.2/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4= +gorm.io/gorm v1.25.3 h1:zi4rHZj1anhZS2EuEODMhDisGy+Daq9jtPrNGgbQYD8= +gorm.io/gorm v1.25.3/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= diff --git a/server.go b/server.go index 1827b74..29f511e 100644 --- a/server.go +++ b/server.go @@ -43,7 +43,7 @@ func (s *server) start() { s.log.Println("Settings:", s.conf.data) s.log.Println("Creating new shortener engine") - s.engine = shortener.NewEngine(shortener.EngineTypeInMemory) + s.engine = shortener.NewEngine(shortener.EngineTypeInSQL) s.dp = httputils.NewDispatcher(&httputils.DispatcherOpts{ NotFoundHandler: s.worker, @@ -83,6 +83,7 @@ func (s *server) mainPage(ctx *fasthttp.RequestCtx) { ctx.SetBodyString(templates.MAIN_HTML) return } + s.passCORS(&ctx.Response.Header) ctx.SetBody(s.htmlBuf) } @@ -123,9 +124,9 @@ func (s *server) createUrl(ctx *fasthttp.RequestCtx) { } hash = s.engine.Shorten(_url, hash) surl := strings.Join([]string{string(ctx.Host()), hash}, "/") + s.passCORS(&ctx.Response.Header) resp.SendSuccess(surl) s.log.Println("Created new shorturl from url (", _url, ") to", "surl (", surl, ")") - return } func (s *server) printGeneralDetails() { diff --git a/utils/shortener/in_sql.go b/utils/shortener/in_sql.go new file mode 100644 index 0000000..56805de --- /dev/null +++ b/utils/shortener/in_sql.go @@ -0,0 +1,84 @@ +package shortener + +import ( + "time" + + "github.com/AnimeKaizoku/cacher" + "github.com/srinkco/srink/utils/randomiser" + "gorm.io/driver/sqlite" + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +const DEF_SQLITE_FILE_NAME = "srink.sql" + +type InSQLEngine struct { + session *gorm.DB + cache *cacher.Cacher[string, string] +} + +type Surl struct { + Hash string `gorm:"primary_key"` + Dest string +} + +func newInSQLEngine(dbName string) *InSQLEngine { + db, err := gorm.Open(sqlite.Open(dbName), &gorm.Config{ + SkipDefaultTransaction: true, + Logger: logger.Default.LogMode(logger.Error), + }) + if err != nil { + panic("failed to connect database") + } + + // Migrate the schema + db.AutoMigrate(&Surl{}) + + return &InSQLEngine{ + session: db, + cache: cacher.NewCacher[string, string](&cacher.NewCacherOpts{ + TimeToLive: time.Hour * 24 * 30, + CleanInterval: time.Hour * 24 * 31, + }), + } +} + +func (e *InSQLEngine) Shorten(url, hash string) string { + if hash == "" { + if hash, ok := e.getHash(url); ok { + return hash + } + hash = randomiser.GetString(HASH_NUM) + } + e.saveUrl(hash, url) + return hash +} + +func (e *InSQLEngine) saveUrl(hash, dest string) { + tx := e.session.Begin() + v := &Surl{Hash: hash} + tx.FirstOrCreate(v) + v.Dest = dest + tx.Save(v) + tx.Commit() + e.cache.Set(hash, dest) +} + +func (e *InSQLEngine) getHash(url string) (string, bool) { + var s Surl + e.session.Where("dest = ?", url).Find(&s) + return s.Hash, s.Hash != "" +} + +func (e *InSQLEngine) GetUrl(hash string) string { + url, ok := e.cache.Get(hash) + if ok { + return url + } + var s Surl + e.session.Where("hash = ?", hash).Find(&s) + if s.Dest != "" { + e.cache.Set(hash, s.Dest) + } + return s.Dest +} diff --git a/utils/shortener/shortener.go b/utils/shortener/shortener.go index 945500f..bb8a6b6 100644 --- a/utils/shortener/shortener.go +++ b/utils/shortener/shortener.go @@ -15,6 +15,8 @@ const ( func NewEngine(eType EngineType) Engine { switch eType { + case EngineTypeInSQL: + return newInSQLEngine(DEF_SQLITE_FILE_NAME) default: return &InMemoryEngine{ hashToUrl: make(map[string]string),