From 59879ceb70e48f2d407e95cb03701d866ff89da8 Mon Sep 17 00:00:00 2001 From: Colin Henry Date: Wed, 10 Jun 2020 16:09:21 -0700 Subject: [PATCH] updated web-tinkertoy to use new db package and broke out endpoints to their own files --- cmd/web-tinkertoy/db.go | 39 ++++++++---- cmd/web-tinkertoy/echo.go | 36 +++++++++++ cmd/web-tinkertoy/fortune.go | 96 ++++++++++++++++++++++++++++ cmd/web-tinkertoy/go.mod | 16 ++++- cmd/web-tinkertoy/go.sum | 36 +++++++++++ cmd/web-tinkertoy/main.go | 10 --- cmd/web-tinkertoy/server.go | 118 ----------------------------------- cmd/web-tinkertoy/time.go | 14 +++++ 8 files changed, 225 insertions(+), 140 deletions(-) create mode 100644 cmd/web-tinkertoy/echo.go create mode 100644 cmd/web-tinkertoy/fortune.go create mode 100644 cmd/web-tinkertoy/time.go diff --git a/cmd/web-tinkertoy/db.go b/cmd/web-tinkertoy/db.go index 70f3d1c..01a3bd9 100644 --- a/cmd/web-tinkertoy/db.go +++ b/cmd/web-tinkertoy/db.go @@ -5,10 +5,12 @@ import ( "database/sql" "fmt" + "github.com/jchenry/jchenry/db" "rsc.io/dbstore" ) type DBFunc func(db *sql.DB) + type DBActor struct { DB *sql.DB ActionChan chan DBFunc @@ -25,29 +27,44 @@ func (a *DBActor) Run(ctx context.Context) error { } } -func DBStoreInsert(store *dbstore.Storage, e interface{}) DBFunc { +func DBStoreInsert(store *dbstore.Storage, e interface{}) db.Func { return func(db *sql.DB) { err := store.Insert(db, e) fmt.Println(err) - } } -func DBStoreDelete(store *dbstore.Storage, e interface{}) DBFunc { +func DBStoreDelete(store *dbstore.Storage, e interface{}) db.Func { return func(db *sql.DB) { store.Delete(db, e) } } -func DBStoreSelect(store *dbstore.Storage, e interface{}, query string, args ...interface{}) DBFunc { +func DBStoreSelect(store *dbstore.Storage, + err chan error, + results chan interface{}, + ent interface{}, + query string, + args ...interface{}) db.Func { return func(db *sql.DB) { - err := store.Select(db, e, query, args...) - fmt.Println(err) + if e := store.Select(db, ent, query, args...); e != nil { + err <- e + } else { + results <- ent + } } } -// func DBStoreRead(store *dbstore.Storage, e interface{}, IDCol string) DBFunc { -// return func(db *sql.DB) { -// store.Read(db, e, IDCol) -// } -// } +func DBStoreRead(store *dbstore.Storage, + err chan error, + results chan interface{}, + ent interface{}, + columns ...string) db.Func { + return func(db *sql.DB) { + if e := store.Read(db, ent, columns...); e != nil { + err <- e + } else { + results <- ent + } + } +} diff --git a/cmd/web-tinkertoy/echo.go b/cmd/web-tinkertoy/echo.go new file mode 100644 index 0000000..ee94fe2 --- /dev/null +++ b/cmd/web-tinkertoy/echo.go @@ -0,0 +1,36 @@ +package main + +import ( + "net/http" + "sync" + "text/template" +) + +func (s *server) handleEcho() http.HandlerFunc { + var ( + init sync.Once + tmpl *template.Template + tplerr error + ) + return func(w http.ResponseWriter, r *http.Request) { + init.Do(func() { + tmpl, tplerr = template.ParseFiles("echoform.tmpl") + }) + if tplerr != nil { + http.Error(w, tplerr.Error(), http.StatusInternalServerError) + return + } + + switch r.Method { + case http.MethodPost: + r.ParseForm() + s.echoMessage = r.Form.Get("msg") + http.Redirect(w, r, "/echo", 301) + return + case http.MethodGet: + if err := tmpl.Execute(w, map[string]string{"Message": s.echoMessage}); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } + } +} diff --git a/cmd/web-tinkertoy/fortune.go b/cmd/web-tinkertoy/fortune.go new file mode 100644 index 0000000..2035ebb --- /dev/null +++ b/cmd/web-tinkertoy/fortune.go @@ -0,0 +1,96 @@ +package main + +import ( + "bufio" + "context" + "fmt" + "log" + "net/http" + "sync" + "text/template" + + "github.com/jchenry/jchenry/db" + "rsc.io/dbstore" +) + +func (s *server) handleFortune() http.HandlerFunc { + var ( + init sync.Once + dba *db.Actor + storage *dbstore.Storage + tmpl *template.Template + tplerr error + ) + + type fortuneWrapper struct { + Fortune string + } + + return func(w http.ResponseWriter, r *http.Request) { + init.Do(func() { + ctx, _ := context.WithCancel(context.Background()) + dba = &db.Actor{ + DB: s.db, + ActionChan: make(chan db.Func), + } + go dba.Run(ctx) + storage = new(dbstore.Storage) + storage.Register(&fortuneWrapper{}) + err := storage.CreateTables(dba.DB) + if err != nil { + fmt.Println(err) + } + tmpl, tplerr = template.ParseFiles("fortunesupload.tmpl") + }) + + if tplerr != nil { + http.Error(w, tplerr.Error(), http.StatusInternalServerError) + return + } + + switch r.Method { + case http.MethodPost: + r.ParseMultipartForm(10 << 20) + file, _, err := r.FormFile("fortunes") + if err != nil { + fmt.Println("Error Retrieving the File") + fmt.Println(err) + return + } + defer file.Close() + + scanner := bufio.NewScanner(file) + var fortune string + for scanner.Scan() { + switch scanner.Text() { + case "%": + dba.ActionChan <- DBStoreInsert(storage, &fortuneWrapper{Fortune: fortune}) + default: + fortune = scanner.Text() + } + + } + + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + case http.MethodGet: + f := fortuneWrapper{} + results := make(chan interface{}) + err := make(chan error) + + dba.ActionChan <- DBStoreSelect(storage, err, results, &f, "ORDER BY RANDOM() LIMIT 1", "*") + select { + case r := <-results: + if err := tmpl.Execute(w, map[string]string{"Message": r.(*fortuneWrapper).Fortune}); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + + case e := <-err: + http.Error(w, e.Error(), http.StatusInternalServerError) + } + + } + + } +} diff --git a/cmd/web-tinkertoy/go.mod b/cmd/web-tinkertoy/go.mod index 5b76baa..50d51d5 100644 --- a/cmd/web-tinkertoy/go.mod +++ b/cmd/web-tinkertoy/go.mod @@ -1,8 +1,22 @@ -module github.com/jchenry/jch +module github.com/jchenry/jchenry/cmd/web-tinkertoy go 1.14 require ( + github.com/codegangsta/negroni v1.0.0 // indirect + github.com/coreos/go-oidc v2.1.0+incompatible // indirect + github.com/gorilla/sessions v1.2.0 // indirect + github.com/jchenry/jchenry v0.0.0-00010101000000-000000000000 + github.com/julienschmidt/httprouter v1.2.0 // indirect github.com/mattn/go-sqlite3 v2.0.3+incompatible + github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect + github.com/stretchr/testify v1.4.0 // indirect + github.com/stripe/stripe-go v63.4.0+incompatible // indirect + golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad // indirect + golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect + gopkg.in/auth0.v1 v1.2.7 // indirect + gopkg.in/square/go-jose.v2 v2.3.1 // indirect rsc.io/dbstore v0.1.1 ) + +replace github.com/jchenry/jchenry => ../../ diff --git a/cmd/web-tinkertoy/go.sum b/cmd/web-tinkertoy/go.sum index c62c743..b8731fd 100644 --- a/cmd/web-tinkertoy/go.sum +++ b/cmd/web-tinkertoy/go.sum @@ -1,6 +1,42 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/PuerkitoBio/rehttp v0.0.0-20180310210549-11cf6ea5d3e9/go.mod h1:ItsOiHl4XeMOV3rzbZqQRjLc3QQxbE6391/9iNG7rE8= +github.com/PuloV/ics-golang v0.0.0-20190808201353-a3394d3bcade/go.mod h1:f1P3hjG+t54/IrnXMnnw+gRmFCDR/ryj9xSQ7MPMkQw= +github.com/channelmeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61/go.mod h1:Rp8e0DCtEKwXFOC6JPJQVTz8tuGoGvw6Xfexggh/ed0= +github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/jchenry/jchenry v0.0.0-20191107034549-4697006d1099 h1:qUy+BhiLM5LzN0cOGtqvuC2v7FNfmQFg1cjZbNcMnBY= +github.com/jchenry/jchenry v0.0.0-20191107034549-4697006d1099/go.mod h1:5ywsKLPV6YOTZ7oNNmQo7EQRDKhlGCD311r/ZRZgHDM= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/mattn/go-sqlite3 v1.13.0 h1:LnJI81JidiW9r7pS/hXe6cFeO5EXNq7KbfvoJLRI69c= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stripe/stripe-go v63.4.0+incompatible/go.mod h1:A1dQZmO/QypXmsL0T8axYZkSN/uA/T/A64pfKdBAMiY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/auth0.v1 v1.2.7/go.mod h1:1FRtMXwYDgygZcO7Of7kj/I4mf9UjHGhMHUOqNT0d0M= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= rsc.io/dbstore v0.1.1 h1:LI4gBJUwbejn0wHJWe0KTwgCM33zUVP3BsNz5y2fkEE= rsc.io/dbstore v0.1.1/go.mod h1:zI7k1PCSLg9r/T2rBM4E/SctbGmqdtt3kjQSemVh1Rs= rsc.io/sqlite v0.5.0/go.mod h1:fqHuveM9iIqMzjD0WiZIvKYMty/WqTo2bxE9+zC54WE= diff --git a/cmd/web-tinkertoy/main.go b/cmd/web-tinkertoy/main.go index 5968666..31c85ce 100644 --- a/cmd/web-tinkertoy/main.go +++ b/cmd/web-tinkertoy/main.go @@ -18,16 +18,6 @@ func main() { } func run(args []string, stdout io.Writer) error { - // ctx, cancel := context.WithCancel(context.Background()) - // defer cancel() - // if db, err := sql.Open("sqlite3", "foo.db"); err == nil { - // dba := DBActor{ - // DB: db, - // ActionChan: make(chan DBFunc, 1), - // } - // go dba.Run(ctx) - // } - s := server{ router: http.NewServeMux(), } diff --git a/cmd/web-tinkertoy/server.go b/cmd/web-tinkertoy/server.go index 3964864..6cbda2e 100644 --- a/cmd/web-tinkertoy/server.go +++ b/cmd/web-tinkertoy/server.go @@ -1,18 +1,8 @@ package main import ( - "bufio" - "context" "database/sql" - "fmt" - "io" - "log" "net/http" - "sync" - "text/template" - "time" - - "rsc.io/dbstore" ) type server struct { @@ -27,111 +17,3 @@ func (s *server) routes() { s.router.HandleFunc("/fortune", s.handleFortune()) } - -func (s *server) handleTime() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - io.WriteString(w, time.Now().String()) - } -} - -func (s *server) handleEcho() http.HandlerFunc { - var ( - init sync.Once - tmpl *template.Template - tplerr error - ) - return func(w http.ResponseWriter, r *http.Request) { - init.Do(func() { - tmpl, tplerr = template.ParseFiles("echoform.tmpl") - }) - if tplerr != nil { - http.Error(w, tplerr.Error(), http.StatusInternalServerError) - return - } - - switch r.Method { - case http.MethodPost: - r.ParseForm() - s.echoMessage = r.Form.Get("msg") - http.Redirect(w, r, "/echo", 301) - return - case http.MethodGet: - if err := tmpl.Execute(w, map[string]string{"Message": s.echoMessage}); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - } - } -} - -func (s *server) handleFortune() http.HandlerFunc { - var ( - init sync.Once - dba *DBActor - storage *dbstore.Storage - tmpl *template.Template - tplerr error - ) - - type fortuneWrapper struct { - Fortune string - } - - return func(w http.ResponseWriter, r *http.Request) { - init.Do(func() { - ctx, _ := context.WithCancel(context.Background()) - dba = &DBActor{ - DB: s.db, - ActionChan: make(chan DBFunc), - } - go dba.Run(ctx) - storage = new(dbstore.Storage) - storage.Register(&fortuneWrapper{}) - err := storage.CreateTables(dba.DB) - if err != nil { - fmt.Println(err) - } - tmpl, tplerr = template.ParseFiles("fortunesupload.tmpl") - }) - - if tplerr != nil { - http.Error(w, tplerr.Error(), http.StatusInternalServerError) - return - } - - switch r.Method { - case http.MethodPost: - r.ParseMultipartForm(10 << 20) - file, _, err := r.FormFile("fortunes") - if err != nil { - fmt.Println("Error Retrieving the File") - fmt.Println(err) - return - } - defer file.Close() - - scanner := bufio.NewScanner(file) - var fortune string - for scanner.Scan() { - switch scanner.Text() { - case "%": - dba.ActionChan <- DBStoreInsert(storage, &fortuneWrapper{Fortune: fortune}) - default: - fortune = scanner.Text() - } - - } - - if err := scanner.Err(); err != nil { - log.Fatal(err) - } - case http.MethodGet: - f := fortuneWrapper{} - DBStoreSelect(storage, &f, "ORDER BY RANDOM() LIMIT 1", "*")(s.db) - if err := tmpl.Execute(w, map[string]string{"Message": f.Fortune}); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - } - - } -} diff --git a/cmd/web-tinkertoy/time.go b/cmd/web-tinkertoy/time.go new file mode 100644 index 0000000..a12d2db --- /dev/null +++ b/cmd/web-tinkertoy/time.go @@ -0,0 +1,14 @@ +package main + +import ( + "io" + "net/http" + "time" +) + +func (s *server) handleTime() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + io.WriteString(w, time.Now().String()) + } +}