mirror of https://github.com/jlelse/GoBlog
Post-post and post-delete hooks
This commit is contained in:
parent
141fe3485f
commit
96259912cb
|
@ -43,7 +43,7 @@ func servePostActivityStreams(w http.ResponseWriter, r *http.Request) {
|
|||
// Remove ".as" from path again
|
||||
r.URL.Path = strings.TrimSuffix(r.URL.Path, ".as")
|
||||
// Fetch post from db
|
||||
p, err := getPost(r.Context(), slashTrimmedPath(r))
|
||||
p, err := getPost(slashTrimmedPath(r))
|
||||
if err == errPostNotFound {
|
||||
serve404(w, r)
|
||||
return
|
||||
|
|
7
cache.go
7
cache.go
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
@ -61,7 +60,7 @@ func cacheMiddleware(next http.Handler) http.Handler {
|
|||
// Get cache
|
||||
cm := cacheMutexes[path]
|
||||
cm.Lock()
|
||||
cacheTime, header, body := getCache(r.Context(), path)
|
||||
cacheTime, header, body := getCache(path)
|
||||
cm.Unlock()
|
||||
if cacheTime == 0 {
|
||||
cm.Lock()
|
||||
|
@ -122,10 +121,10 @@ func renderCache(path string, next http.Handler, w http.ResponseWriter, r *http.
|
|||
}
|
||||
}
|
||||
|
||||
func getCache(context context.Context, path string) (creationTime int64, header map[string][]string, body []byte) {
|
||||
func getCache(path string) (creationTime int64, header map[string][]string, body []byte) {
|
||||
var headerBytes []byte
|
||||
allowedTime := time.Now().Unix() - appConfig.Cache.Expiration
|
||||
row := cacheDb.QueryRowContext(context, "select COALESCE(time, 0), header, body from cache where path=? and time>=?", path, allowedTime)
|
||||
row := cacheDb.QueryRow("select COALESCE(time, 0), header, body from cache where path=? and time>=?", path, allowedTime)
|
||||
_ = row.Scan(&creationTime, &headerBytes, &body)
|
||||
header = make(map[string][]string)
|
||||
_ = json.Unmarshal(headerBytes, &header)
|
||||
|
|
|
@ -108,6 +108,9 @@ type configHooks struct {
|
|||
Shell string `mapstructure:"shell"`
|
||||
Hourly []string `mapstructure:"hourly"`
|
||||
PreStart []string `mapstructure:"prestart"`
|
||||
// Can use template
|
||||
PostPost []string `mapstructure:"postpost"`
|
||||
PostDelete []string `mapstructure:"postdelete"`
|
||||
}
|
||||
|
||||
type configHugo struct {
|
||||
|
|
49
hooks.go
49
hooks.go
|
@ -1,6 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
"log"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
@ -8,11 +10,50 @@ import (
|
|||
|
||||
func preStartHooks() {
|
||||
for _, cmd := range appConfig.Hooks.PreStart {
|
||||
log.Println("Executing pre-start hook:", cmd)
|
||||
executeCommand(cmd)
|
||||
go func(cmd string) {
|
||||
log.Println("Executing pre-start hook:", cmd)
|
||||
executeCommand(cmd)
|
||||
}(cmd)
|
||||
}
|
||||
}
|
||||
|
||||
func postPostHooks(path string) {
|
||||
for _, cmdTmplString := range appConfig.Hooks.PostPost {
|
||||
go func(path, cmdTmplString string) {
|
||||
executeTemplateCommand("post-post", cmdTmplString, &hookTemplateData{
|
||||
URL: appConfig.Server.PublicAddress + path,
|
||||
})
|
||||
}(path, cmdTmplString)
|
||||
}
|
||||
}
|
||||
|
||||
func postDeleteHooks(path string) {
|
||||
for _, cmdTmplString := range appConfig.Hooks.PostDelete {
|
||||
go func(path, cmdTmplString string) {
|
||||
executeTemplateCommand("post-delete", cmdTmplString, &hookTemplateData{
|
||||
URL: appConfig.Server.PublicAddress + path,
|
||||
})
|
||||
}(path, cmdTmplString)
|
||||
}
|
||||
}
|
||||
|
||||
type hookTemplateData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func executeTemplateCommand(hookType string, tmpl string, data *hookTemplateData) {
|
||||
cmdTmpl, err := template.New("cmd").Parse(tmpl)
|
||||
if err != nil {
|
||||
log.Println("Failed to parse cmd template:", err.Error())
|
||||
return
|
||||
}
|
||||
var cmdBuf bytes.Buffer
|
||||
cmdTmpl.Execute(&cmdBuf, data)
|
||||
cmd := cmdBuf.String()
|
||||
log.Println("Executing "+hookType+" hook:", cmd)
|
||||
executeCommand(cmd)
|
||||
}
|
||||
|
||||
func startHourlyHooks() {
|
||||
for _, cmd := range appConfig.Hooks.Hourly {
|
||||
go func(cmd string) {
|
||||
|
@ -21,11 +62,11 @@ func startHourlyHooks() {
|
|||
executeCommand(cmd)
|
||||
}
|
||||
// Execute once
|
||||
run()
|
||||
go run()
|
||||
// Start ticker and execute regularly
|
||||
ticker := time.NewTicker(1 * time.Hour)
|
||||
for range ticker.C {
|
||||
run()
|
||||
go run()
|
||||
}
|
||||
}(cmd)
|
||||
}
|
||||
|
|
|
@ -38,14 +38,14 @@ func serveMicropubQuery(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
p, err := getPost(r.Context(), u.Path)
|
||||
p, err := getPost(u.Path)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
mf = p.toMfItem()
|
||||
} else {
|
||||
posts, err := getPosts(r.Context(), &postsRequestConfig{})
|
||||
posts, err := getPosts(&postsRequestConfig{})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
@ -391,7 +391,7 @@ func micropubUpdate(w http.ResponseWriter, r *http.Request, u *url.URL, mf *micr
|
|||
if !strings.Contains(r.Context().Value("scope").(string), "update") {
|
||||
http.Error(w, "update scope missing", http.StatusForbidden)
|
||||
}
|
||||
p, err := getPost(r.Context(), u.Path)
|
||||
p, err := getPost(u.Path)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
|
|
26
posts.go
26
posts.go
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
|
@ -35,7 +34,7 @@ func servePost(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
path := slashTrimmedPath(r)
|
||||
p, err := getPost(r.Context(), path)
|
||||
p, err := getPost(path)
|
||||
if err == errPostNotFound {
|
||||
serve404(w, r)
|
||||
return
|
||||
|
@ -62,14 +61,13 @@ type indexTemplateData struct {
|
|||
}
|
||||
|
||||
type postPaginationAdapter struct {
|
||||
context context.Context
|
||||
config *postsRequestConfig
|
||||
nums int
|
||||
config *postsRequestConfig
|
||||
nums int
|
||||
}
|
||||
|
||||
func (p *postPaginationAdapter) Nums() int {
|
||||
if p.nums == 0 {
|
||||
p.nums, _ = countPosts(p.context, p.config)
|
||||
p.nums, _ = countPosts(p.config)
|
||||
}
|
||||
return p.nums
|
||||
}
|
||||
|
@ -83,7 +81,7 @@ func (p *postPaginationAdapter) Slice(offset, length int, data interface{}) erro
|
|||
modifiedConfig.offset = offset
|
||||
modifiedConfig.limit = length
|
||||
|
||||
posts, err := getPosts(p.context, &modifiedConfig)
|
||||
posts, err := getPosts(&modifiedConfig)
|
||||
reflect.ValueOf(data).Elem().Set(reflect.ValueOf(&posts).Elem())
|
||||
return err
|
||||
}
|
||||
|
@ -163,7 +161,7 @@ func serveIndex(ic *indexConfig) func(w http.ResponseWriter, r *http.Request) {
|
|||
sections = append(sections, sectionKey)
|
||||
}
|
||||
}
|
||||
p := paginator.New(&postPaginationAdapter{context: r.Context(), config: &postsRequestConfig{
|
||||
p := paginator.New(&postPaginationAdapter{config: &postsRequestConfig{
|
||||
blog: ic.blog,
|
||||
sections: sections,
|
||||
taxonomy: ic.tax,
|
||||
|
@ -219,8 +217,8 @@ func serveIndex(ic *indexConfig) func(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
func getPost(context context.Context, path string) (*post, error) {
|
||||
posts, err := getPosts(context, &postsRequestConfig{path: path})
|
||||
func getPost(path string) (*post, error) {
|
||||
posts, err := getPosts(&postsRequestConfig{path: path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(posts) == 0 {
|
||||
|
@ -281,9 +279,9 @@ func buildQuery(config *postsRequestConfig) (query string, params []interface{})
|
|||
return
|
||||
}
|
||||
|
||||
func getPosts(context context.Context, config *postsRequestConfig) (posts []*post, err error) {
|
||||
func getPosts(config *postsRequestConfig) (posts []*post, err error) {
|
||||
query, queryParams := buildQuery(config)
|
||||
rows, err := appDb.QueryContext(context, query, queryParams...)
|
||||
rows, err := appDb.Query(query, queryParams...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -311,10 +309,10 @@ func getPosts(context context.Context, config *postsRequestConfig) (posts []*pos
|
|||
return posts, nil
|
||||
}
|
||||
|
||||
func countPosts(context context.Context, config *postsRequestConfig) (count int, err error) {
|
||||
func countPosts(config *postsRequestConfig) (count int, err error) {
|
||||
query, params := buildQuery(config)
|
||||
query = "select count(distinct path) from (" + query + ")"
|
||||
row := appDb.QueryRowContext(context, query, params...)
|
||||
row := appDb.QueryRow(query, params...)
|
||||
err = row.Scan(&count)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -156,6 +156,7 @@ func (p *post) createOrReplace(new bool) error {
|
|||
}
|
||||
finishWritingToDb()
|
||||
go purgeCache()
|
||||
defer postPostHooks(p.Path)
|
||||
return reloadRouter()
|
||||
}
|
||||
|
||||
|
@ -188,5 +189,6 @@ func deletePost(path string) error {
|
|||
}
|
||||
finishWritingToDb()
|
||||
go purgeCache()
|
||||
defer postDeleteHooks(path)
|
||||
return reloadRouter()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"html/template"
|
||||
"log"
|
||||
"strings"
|
||||
|
@ -56,7 +55,7 @@ func (p *post) translations() []*post {
|
|||
if translationkey == "" {
|
||||
return nil
|
||||
}
|
||||
posts, err := getPosts(context.Background(), &postsRequestConfig{
|
||||
posts, err := getPosts(&postsRequestConfig{
|
||||
parameter: "translationkey",
|
||||
parameterValue: translationkey,
|
||||
})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
@ -11,7 +10,7 @@ import (
|
|||
var errRedirectNotFound = errors.New("redirect not found")
|
||||
|
||||
func serveRedirect(w http.ResponseWriter, r *http.Request) {
|
||||
redirect, err := getRedirect(r.Context(), slashTrimmedPath(r))
|
||||
redirect, err := getRedirect(slashTrimmedPath(r))
|
||||
if err == errRedirectNotFound {
|
||||
serve404(w, r)
|
||||
return
|
||||
|
@ -27,9 +26,9 @@ func serveRedirect(w http.ResponseWriter, r *http.Request) {
|
|||
w.WriteHeader(http.StatusFound)
|
||||
}
|
||||
|
||||
func getRedirect(context context.Context, fromPath string) (string, error) {
|
||||
func getRedirect(fromPath string) (string, error) {
|
||||
var toPath string
|
||||
row := appDb.QueryRowContext(context, "with recursive f (i, fp, tp) as (select 1, fromPath, toPath from redirects where fromPath = ? union all select f.i + 1, r.fromPath, r.toPath from redirects as r join f on f.tp = r.fromPath) select tp from f order by i desc limit 1", fromPath)
|
||||
row := appDb.QueryRow("with recursive f (i, fp, tp) as (select 1, fromPath, toPath from redirects where fromPath = ? union all select f.i + 1, r.fromPath, r.toPath from redirects as r join f on f.tp = r.fromPath) select tp from f order by i desc limit 1", fromPath)
|
||||
err := row.Scan(&toPath)
|
||||
if err == sql.ErrNoRows {
|
||||
return "", errRedirectNotFound
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
const sitemapPath = "/sitemap.xml"
|
||||
|
||||
func serveSitemap(w http.ResponseWriter, r *http.Request) {
|
||||
posts, err := getPosts(r.Context(), &postsRequestConfig{})
|
||||
posts, err := getPosts(&postsRequestConfig{})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue