diff --git a/activitystreams.go b/activitystreams.go index 21652a5..173c6f1 100644 --- a/activitystreams.go +++ b/activitystreams.go @@ -1,7 +1,6 @@ package main import ( - "encoding/json" "net/http" "strings" "time" diff --git a/api.go b/api.go index aa9af52..e6bdd99 100644 --- a/api.go +++ b/api.go @@ -1,7 +1,6 @@ package main import ( - "encoding/json" "io/ioutil" "net/http" "strings" diff --git a/cache.go b/cache.go index 38b00b7..c498b03 100644 --- a/cache.go +++ b/cache.go @@ -3,7 +3,7 @@ package main import ( "context" "database/sql" - "encoding/json" + "log" "net/http" "net/http/httptest" "net/url" @@ -11,11 +11,13 @@ import ( "time" ) +var cacheMutexMapMutex *sync.Mutex var cacheMutexes map[string]*sync.Mutex var cacheDb *sql.DB var cacheDbWriteMutex = &sync.Mutex{} func initCache() (err error) { + cacheMutexMapMutex = &sync.Mutex{} cacheMutexes = map[string]*sync.Mutex{} cacheDb, err = sql.Open("sqlite3", ":memory:") if err != nil { @@ -52,36 +54,23 @@ func cacheMiddleware(next http.Handler) http.Handler { // check bypass query !(requestURL != nil && requestURL.Query().Get("cache") == "0") { // Check cache mutex + cacheMutexMapMutex.Lock() if cacheMutexes[path] == nil { cacheMutexes[path] = &sync.Mutex{} } - // Lock mutex - prevents multiple new renderings - cacheMutexes[path].Lock() + cacheMutexMapMutex.Unlock() // Get cache + cm := cacheMutexes[path] + cm.Lock() cacheTime, header, body := getCache(r.Context(), path) + cm.Unlock() if cacheTime == 0 { - // No cache available - recorder := httptest.NewRecorder() - next.ServeHTTP(recorder, r) - // copy values from recorder - code := recorder.Code - // send response - for k, v := range recorder.Header() { - w.Header()[k] = v - } - now := time.Now() - setCacheHeaders(w, now.Format(time.RFC1123), time.Unix(now.Unix()+appConfig.Cache.Expiration, 0).Format(time.RFC1123)) - w.Header().Set("GoBlog-Cache", "MISS") - w.WriteHeader(code) - _, _ = w.Write(recorder.Body.Bytes()) - // Save cache - if code == http.StatusOK { - saveCache(path, now, recorder.Header(), recorder.Body.Bytes()) - } - cacheMutexes[path].Unlock() + cm.Lock() + // Render cache + renderCache(path, next, w, r) + cm.Unlock() return } - cacheMutexes[path].Unlock() cacheTimeString := time.Unix(cacheTime, 0).Format(time.RFC1123) expiresTimeString := time.Unix(cacheTime+appConfig.Cache.Expiration, 0).Format(time.RFC1123) // check conditional request @@ -113,6 +102,28 @@ func setCacheHeaders(w http.ResponseWriter, cacheTimeString string, expiresTimeS w.Header().Set("Expires", expiresTimeString) } +func renderCache(path string, next http.Handler, w http.ResponseWriter, r *http.Request) { + log.Println("Render") + // No cache available + recorder := httptest.NewRecorder() + next.ServeHTTP(recorder, r) + // copy values from recorder + code := recorder.Code + // send response + for k, v := range recorder.Header() { + w.Header()[k] = v + } + now := time.Now() + setCacheHeaders(w, now.Format(time.RFC1123), time.Unix(now.Unix()+appConfig.Cache.Expiration, 0).Format(time.RFC1123)) + w.Header().Set("GoBlog-Cache", "MISS") + w.WriteHeader(code) + _, _ = w.Write(recorder.Body.Bytes()) + // Save cache + if code == http.StatusOK { + saveCache(path, now, recorder.Header(), recorder.Body.Bytes()) + } +} + func getCache(context context.Context, path string) (creationTime int64, header map[string][]string, body []byte) { var headerBytes []byte allowedTime := time.Now().Unix() - appConfig.Cache.Expiration diff --git a/go.mod b/go.mod index c32b498..575db83 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/gorilla/feeds v1.1.1 github.com/jeremywohl/flatten v1.0.1 github.com/jinzhu/gorm v1.9.16 // indirect + github.com/json-iterator/go v1.1.10 github.com/klauspost/cpuid v1.3.1 // indirect github.com/kr/pretty v0.2.1 // indirect github.com/kr/text v0.2.0 // indirect @@ -41,8 +42,8 @@ require ( golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 // indirect golang.org/x/sync v0.0.0-20200930132711-30421366ff76 // indirect - golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf // indirect - golang.org/x/tools v0.0.0-20201005185003-576e169c3de7 // indirect + golang.org/x/sys v0.0.0-20201007082116-8445cc04cbdf // indirect + golang.org/x/tools v0.0.0-20201007032633-0806396f153e // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect diff --git a/go.sum b/go.sum index 874329e..b332704 100644 --- a/go.sum +++ b/go.sum @@ -86,6 +86,7 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -135,7 +136,10 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -198,7 +202,11 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= @@ -398,8 +406,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c= golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf h1:Bg47KQy0JhTHuf4sLiQwTMKwUMfSDwgSGatrxGR7nLM= -golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201007082116-8445cc04cbdf h1:AvBTl0xbF/KtHyvm61X4gSPF7/dKJ/xQqJwKr1Qu9no= +golang.org/x/sys v0.0.0-20201007082116-8445cc04cbdf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= @@ -431,8 +439,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20201005185003-576e169c3de7 h1:YTAUHYgZh/ZOA35/OrjTDmFFKb6ddkBL1Zgtl9r8Di8= -golang.org/x/tools v0.0.0-20201005185003-576e169c3de7/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201007032633-0806396f153e h1:FJA2W4BQfMGZ+CD/tiAc39HXecuRsJl3EuczaSUu/Yk= +golang.org/x/tools v0.0.0-20201007032633-0806396f153e/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= diff --git a/indieauth.go b/indieauth.go index f855c84..5891df3 100644 --- a/indieauth.go +++ b/indieauth.go @@ -1,7 +1,6 @@ package main import ( - "encoding/json" "errors" "fmt" "net/http" diff --git a/main.go b/main.go index 7015d3f..72fe4ef 100644 --- a/main.go +++ b/main.go @@ -4,8 +4,12 @@ import ( "log" "os" "os/signal" + + jsoniter "github.com/json-iterator/go" ) +var json = jsoniter.ConfigCompatibleWithStandardLibrary + func main() { // Initialize config log.Println("Initialize configuration...") diff --git a/micropub.go b/micropub.go index 03d22c1..f85bdd0 100644 --- a/micropub.go +++ b/micropub.go @@ -1,7 +1,6 @@ package main import ( - "encoding/json" "errors" "net/http" "strings" diff --git a/minify.go b/minify.go index 849cd04..5f46381 100644 --- a/minify.go +++ b/minify.go @@ -2,21 +2,21 @@ package main import ( "github.com/tdewolff/minify/v2" - "github.com/tdewolff/minify/v2/css" - "github.com/tdewolff/minify/v2/html" - "github.com/tdewolff/minify/v2/js" - "github.com/tdewolff/minify/v2/json" - "github.com/tdewolff/minify/v2/xml" + mCss "github.com/tdewolff/minify/v2/css" + mHtml "github.com/tdewolff/minify/v2/html" + mJs "github.com/tdewolff/minify/v2/js" + mJson "github.com/tdewolff/minify/v2/json" + mXml "github.com/tdewolff/minify/v2/xml" ) var minifier *minify.M func initMinify() { minifier = minify.New() - minifier.AddFunc("text/html", html.Minify) - minifier.AddFunc("text/css", css.Minify) - minifier.AddFunc("application/javascript", js.Minify) - minifier.AddFunc("application/rss+xml", xml.Minify) - minifier.AddFunc("application/atom+xml", xml.Minify) - minifier.AddFunc("application/feed+json", json.Minify) + minifier.AddFunc("text/html", mHtml.Minify) + minifier.AddFunc("text/css", mCss.Minify) + minifier.AddFunc("application/javascript", mJs.Minify) + minifier.AddFunc("application/rss+xml", mXml.Minify) + minifier.AddFunc("application/atom+xml", mXml.Minify) + minifier.AddFunc("application/feed+json", mJson.Minify) }