add caching and change the layout a bit

This commit is contained in:
rramiachraf 2022-07-01 23:40:13 +01:00
parent 7b2c43cc16
commit e7aa7403c7
8 changed files with 114 additions and 29 deletions

1
go.mod
View File

@ -8,6 +8,7 @@ require (
) )
require ( require (
github.com/allegro/bigcache/v3 v3.0.2 // indirect
github.com/andybalholm/cascadia v1.3.1 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 // indirect golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 // indirect
) )

2
go.sum
View File

@ -1,5 +1,7 @@
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U= github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
github.com/allegro/bigcache/v3 v3.0.2 h1:AKZCw+5eAaVyNTBmI2fgyPVJhHkdWder3O9IrprcQfI=
github.com/allegro/bigcache/v3 v3.0.2/go.mod h1:aPyh7jEvrog9zAwx5N7+JUQX5dZTSGpxF1LAR4dr35I=
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=

View File

@ -49,6 +49,11 @@ func (s *song) parse(doc *goquery.Document) {
func lyricsHandler(w http.ResponseWriter, r *http.Request) { func lyricsHandler(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"] id := mux.Vars(r)["id"]
if data, err := getCache(id); err == nil {
render(w, data)
return
}
url := fmt.Sprintf("https://genius.com/%s-lyrics", id) url := fmt.Sprintf("https://genius.com/%s-lyrics", id)
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
@ -78,4 +83,5 @@ func lyricsHandler(w http.ResponseWriter, r *http.Request) {
} }
t.Execute(w, s) t.Execute(w, s)
setCache(id, s)
} }

23
main.go
View File

@ -2,32 +2,27 @@ package main
import ( import (
"fmt" "fmt"
"log"
"net" "net"
"net/http" "net/http"
"os" "os"
"strconv" "strconv"
"time" "time"
"github.com/allegro/bigcache/v3"
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
func fatal(err any) {
log.Fatalf("[ERR] %s\n", err)
}
func info(s string) {
log.Printf("[INFO] %s\n", s)
}
func write(w http.ResponseWriter, status int, data []byte) {
w.WriteHeader(status)
w.Write(data)
}
func main() { func main() {
c, err := bigcache.NewBigCache(bigcache.DefaultConfig(time.Hour * 2))
if err != nil {
fatal("can't initialize caching")
}
cache = c
r := mux.NewRouter() r := mux.NewRouter()
r.Use(securityHeaders)
r.HandleFunc("/{id}-lyrics", lyricsHandler) r.HandleFunc("/{id}-lyrics", lyricsHandler)
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))

View File

@ -1,4 +1,4 @@
document.querySelectorAll("#lyrics > a").forEach(item => { document.querySelectorAll("#lyrics a").forEach(item => {
item.addEventListener("click", getAnnotation) item.addEventListener("click", getAnnotation)
}) })

View File

@ -45,10 +45,6 @@ body {
} }
#lyrics { #lyrics {
position: absolute;
left: 50%;
transform: translateX(-50%);
padding: 1rem 0;
color: #171717; color: #171717;
line-height: 2.5rem; line-height: 2.5rem;
} }
@ -58,6 +54,10 @@ body {
color: inherit; color: inherit;
} }
#lyrics a:hover {
background-color: #ccc;
}
#nav { #nav {
font-size: 2.5rem; font-size: 2.5rem;
text-align: center; text-align: center;
@ -76,24 +76,30 @@ a {
#metadata { #metadata {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center;
gap: 0.5rem; gap: 0.5rem;
padding: 1rem; text-align: center;
} }
#metadata h1 { #metadata h1 {
font-size: 2.2rem; font-size: 2rem;
color: #171717; color: #171717;
} }
#metadata h2 { #metadata h2 {
font-size: 1.5rem; font-size: 1.4rem;
color: #1E1E1E; color: #1E1E1E;
text-transform: uppercase;
font-weight: 500; font-weight: 500;
} }
#metadata > img { #metadata > img {
width: 20rem; width: 20rem;
border-radius: 3px; border-radius: 3px;
box-shadow: 0 1px 1px #ddd;
}
#container {
display: flex;
padding: 2rem;
gap: 5rem;
justify-content: center;
} }

73
utils.go Normal file
View File

@ -0,0 +1,73 @@
package main
import (
"encoding/json"
"log"
"net/http"
"path"
"text/template"
"github.com/allegro/bigcache/v3"
)
var cache *bigcache.BigCache
func setCache(key string, entry any) error {
data, err := json.Marshal(&entry)
if err != nil {
return err
}
return cache.Set(key, data)
}
func getCache(key string) (any, error) {
data, err := cache.Get(key)
if err != nil {
return nil, err
}
var decoded any
if err = json.Unmarshal(data, &decoded); err != nil {
return nil, err
}
return decoded, nil
}
func fatal(err any) {
log.Fatalf("[ERR] %s\n", err)
}
func info(s string) {
log.Printf("[INFO] %s\n", s)
}
func write(w http.ResponseWriter, status int, data []byte) {
w.WriteHeader(status)
w.Write(data)
}
func securityHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
csp := "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' images.genius.com; object-src 'none'"
w.Header().Add("content-security-policy", csp)
w.Header().Add("referrer-policy", "no-referrer")
w.Header().Add("x-content-type-options", "nosniff")
next.ServeHTTP(w, r)
})
}
func render(w http.ResponseWriter, data any) {
t, err := template.ParseFiles(path.Join("views/lyrics.tmpl"))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
if err = t.Execute(w, data); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
}

View File

@ -8,11 +8,13 @@
</head> </head>
<body> <body>
<h1 id="nav">DUMB</h1> <h1 id="nav">DUMB</h1>
<div id="container">
<div id="metadata"> <div id="metadata">
<img src="{{.Image}}"/> <img src="{{.Image}}"/>
<h2>{{.Artist}}</h2> <h2>{{.Artist}}</h2>
<h1>{{.Title}}</h1> <h1>{{.Title}}</h1>
</div> </div>
<div id="lyrics">{{.Lyrics}}</div> <div id="lyrics">{{.Lyrics}}</div>
</div>
</body> </body>
</html> </html>