updated web-tinkertoy to use new db package and broke out endpoints to their own files

This commit is contained in:
Colin Henry 2020-06-10 16:09:21 -07:00
parent fcc302dcfe
commit 59879ceb70
8 changed files with 225 additions and 140 deletions

View File

@ -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
}
}
}

36
cmd/web-tinkertoy/echo.go Normal file
View File

@ -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)
}
}
}
}

View File

@ -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)
}
}
}
}

View File

@ -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 => ../../

View File

@ -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=

View File

@ -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(),
}

View File

@ -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)
}
}
}
}

14
cmd/web-tinkertoy/time.go Normal file
View File

@ -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())
}
}