ETags are now set by /api/phrases and Hyperdrive on the topic list for better caching.
Initialised the fields in hyperspace properly. Eliminate an unnecessary line in client templates. Cleaned up some thaw code in the forum store. Fixed a potential premature thaw in Forums.BypassGet
This commit is contained in:
parent
4414957885
commit
efe7a0f3f0
|
@ -55,7 +55,7 @@ func (list SFileList) JSTmplInit() error {
|
|||
}
|
||||
|
||||
path = strings.TrimPrefix(path, "tmpl_client/")
|
||||
tmplName := strings.TrimSuffix(path, ".go")
|
||||
tmplName := strings.TrimSuffix(path, ".jgo")
|
||||
shortName := strings.TrimPrefix(tmplName, "template_")
|
||||
|
||||
var replace = func(data []byte, replaceThis string, withThis string) []byte {
|
||||
|
@ -104,10 +104,6 @@ func (list SFileList) JSTmplInit() error {
|
|||
}
|
||||
return out + "]"
|
||||
}*/
|
||||
data = replace(data, `)
|
||||
if !ok {
|
||||
return errors.New("invalid page struct value")
|
||||
}`, "*/tmpl_"+shortName+"_vars = tmpl_"+shortName+"_i")
|
||||
|
||||
// ? Can we just use a regex? I'm thinking of going more efficient, or just outright rolling wasm, this is a temp hack in a place where performance doesn't particularly matter
|
||||
var each = func(phrase string, handle func(index int)) {
|
||||
|
|
|
@ -143,6 +143,7 @@ func (mfs *MemoryForumStore) rebuildView() {
|
|||
})
|
||||
sort.Sort(SortForum(forumView))
|
||||
mfs.forumView.Store(forumView)
|
||||
TopicListThaw.Thaw()
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) DirtyGet(id int) *Forum {
|
||||
|
@ -190,7 +191,7 @@ func (mfs *MemoryForumStore) BypassGet(id int) (*Forum, error) {
|
|||
forum.Link = BuildForumURL(NameToSlug(forum.Name), forum.ID)
|
||||
forum.LastTopic = Topics.DirtyGet(forum.LastTopicID)
|
||||
forum.LastReplyer = Users.DirtyGet(forum.LastReplyerID)
|
||||
TopicListThaw.Thaw()
|
||||
//TopicListThaw.Thaw()
|
||||
|
||||
return forum, err
|
||||
}
|
||||
|
@ -219,7 +220,6 @@ func (mfs *MemoryForumStore) Reload(id int) error {
|
|||
forum.LastReplyer = Users.DirtyGet(forum.LastReplyerID)
|
||||
|
||||
mfs.CacheSet(forum)
|
||||
TopicListThaw.Thaw()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -290,7 +290,6 @@ func (mfs *MemoryForumStore) Delete(id int) error {
|
|||
}
|
||||
_, err := mfs.delete.Exec(id)
|
||||
mfs.CacheDelete(id)
|
||||
TopicListThaw.Thaw()
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -495,7 +495,7 @@ func compileJSTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName stri
|
|||
if tname != "" {
|
||||
tname = "_" + tname
|
||||
}
|
||||
err := writeFile(dirPrefix+"template_"+name+tname+".go", content)
|
||||
err := writeFile(dirPrefix+"template_"+name+tname+".jgo", content)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -442,20 +442,22 @@ func (c *CTemplateSet) compile(name string, content string, expects string, expe
|
|||
fout += "}\n\n"
|
||||
}
|
||||
|
||||
if c.lang == "normal" {
|
||||
fout += "// nolint\nfunc Template_" + fname + "(tmpl_" + fname + "_i interface{}, w io.Writer) error {\n"
|
||||
fout += `tmpl_` + fname + `_vars, ok := tmpl_` + fname + `_i.(` + expects + `)
|
||||
if !ok {
|
||||
return errors.New("invalid page struct value")
|
||||
}
|
||||
`
|
||||
if c.lang == "normal" {
|
||||
fout += `var iw http.ResponseWriter
|
||||
fout += `var iw http.ResponseWriter
|
||||
gzw, ok := w.(common.GzipResponseWriter)
|
||||
if ok {
|
||||
iw = gzw.ResponseWriter
|
||||
}
|
||||
_ = iw
|
||||
`
|
||||
} else {
|
||||
fout += "// nolint\nfunc Template_" + fname + "(tmpl_" + fname + "_vars interface{}, w io.Writer) error {\n"
|
||||
}
|
||||
|
||||
if len(c.langIndexToName) > 0 {
|
||||
|
|
|
@ -5,6 +5,9 @@ import (
|
|||
//"log"
|
||||
"bytes"
|
||||
"errors"
|
||||
"strings"
|
||||
"strconv"
|
||||
"time"
|
||||
"sync/atomic"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
@ -37,11 +40,14 @@ func deactivateHdrive(plugin *c.Plugin) {
|
|||
type Hyperspace struct {
|
||||
topicList atomic.Value
|
||||
gzipTopicList atomic.Value
|
||||
lastTopicListUpdate atomic.Value
|
||||
}
|
||||
|
||||
func newHyperspace() *Hyperspace {
|
||||
pageCache := new(Hyperspace)
|
||||
pageCache.topicList.Store([]byte(""))
|
||||
pageCache.gzipTopicList.Store([]byte(""))
|
||||
pageCache.lastTopicListUpdate.Store(int64(0))
|
||||
return pageCache
|
||||
}
|
||||
|
||||
|
@ -86,6 +92,7 @@ func tickHdrive(args ...interface{}) (skip bool, rerr c.RouteError) {
|
|||
return false, nil
|
||||
}
|
||||
hyperspace.gzipTopicList.Store(gbuf)
|
||||
hyperspace.lastTopicListUpdate.Store(time.Now().Unix())
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
@ -128,12 +135,29 @@ func jumpHdrive(args ...interface{}) (skip bool, rerr c.RouteError) {
|
|||
//c.DebugLog
|
||||
c.DebugLog("Successful jump")
|
||||
|
||||
var etag string
|
||||
lastUpdate := hyperspace.lastTopicListUpdate.Load().(int64)
|
||||
c.DebugLog("lastUpdate:",lastUpdate)
|
||||
if ok {
|
||||
iw.Header().Set("X-I","1")
|
||||
etag = "\""+strconv.FormatInt(lastUpdate, 10)+"-g\""
|
||||
} else {
|
||||
etag = "\""+strconv.FormatInt(lastUpdate, 10)+"\""
|
||||
}
|
||||
|
||||
if lastUpdate != 0 {
|
||||
iw.Header().Set("ETag", etag)
|
||||
if match := r.Header.Get("If-None-Match"); match != "" {
|
||||
if strings.Contains(match, etag) {
|
||||
iw.WriteHeader(http.StatusNotModified)
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header := args[3].(*c.Header)
|
||||
routes.FootHeaders(w, header)
|
||||
iw.Write(tList)
|
||||
if ok {
|
||||
w.Header().Set("X-I","1")
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
|
@ -185,7 +185,7 @@ function initPhrases(loggedIn, panel = false) {
|
|||
}
|
||||
|
||||
function fetchPhrases(plist) {
|
||||
fetch("/api/phrases/?query="+plist)
|
||||
fetch("/api/phrases/?query="+plist, {cache: "no-cache"})
|
||||
.then((resp) => resp.json())
|
||||
.then((data) => {
|
||||
console.log("loaded phrase endpoint data");
|
||||
|
|
80
routes.go
80
routes.go
|
@ -191,32 +191,50 @@ func routeAPIPhrases(w http.ResponseWriter, r *http.Request, user c.User) c.Rout
|
|||
return c.PreErrorJS("You haven't requested any phrases", w, r)
|
||||
}
|
||||
|
||||
var etag string
|
||||
_, ok := w.(c.GzipResponseWriter)
|
||||
if ok {
|
||||
etag = "\""+strconv.FormatInt(c.StartTime.Unix(), 10)+"-g\""
|
||||
} else {
|
||||
etag = "\""+strconv.FormatInt(c.StartTime.Unix(), 10)+"\""
|
||||
}
|
||||
|
||||
var plist map[string]string
|
||||
var posLoop = func(positive string) c.RouteError {
|
||||
// ! Constrain it to a subset of phrases for now
|
||||
for _, item := range phraseWhitelist {
|
||||
if strings.HasPrefix(positive, item) {
|
||||
// TODO: Break this down into smaller security boundaries based on control panel sections?
|
||||
if strings.HasPrefix(positive,"panel") {
|
||||
w.Header().Set("Cache-Control", "private")
|
||||
ok = user.IsSuperMod
|
||||
} else {
|
||||
ok = true
|
||||
w.Header().Set("ETag", etag)
|
||||
if match := r.Header.Get("If-None-Match"); match != "" {
|
||||
if strings.Contains(match, etag) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return c.PreErrorJS("Outside of phrase prefix whitelist", w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A little optimisation to avoid copying entries from one map to the other, if we don't have to mutate it
|
||||
// TODO: Reduce the amount of duplication here
|
||||
if len(positives) > 1 {
|
||||
plist = make(map[string]string)
|
||||
for _, positive := range positives {
|
||||
// ! Constrain it to a subset of phrases for now
|
||||
var ok = false
|
||||
for _, item := range phraseWhitelist {
|
||||
if strings.HasPrefix(positive, item) {
|
||||
// TODO: Break this down into smaller security boundaries based on control panel sections?
|
||||
if strings.HasPrefix(positive,"panel") {
|
||||
if user.IsSuperMod {
|
||||
ok = true
|
||||
w.Header().Set("Cache-Control", "private")
|
||||
}
|
||||
} else {
|
||||
ok = true
|
||||
}
|
||||
break
|
||||
}
|
||||
rerr := posLoop(positive)
|
||||
if rerr != nil {
|
||||
return rerr
|
||||
}
|
||||
if !ok {
|
||||
return c.PreErrorJS("Outside of phrase prefix whitelist", w, r)
|
||||
}
|
||||
|
||||
pPhrases, ok := phrases.GetTmplPhrasesByPrefix(positive)
|
||||
if !ok {
|
||||
return c.PreErrorJS("No such prefix", w, r)
|
||||
|
@ -226,26 +244,10 @@ func routeAPIPhrases(w http.ResponseWriter, r *http.Request, user c.User) c.Rout
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// ! Constrain it to a subset of phrases for now
|
||||
var ok = false
|
||||
for _, item := range phraseWhitelist {
|
||||
if strings.HasPrefix(positives[0], item) {
|
||||
// TODO: Break this down into smaller security boundaries based on control panel sections?
|
||||
if strings.HasPrefix(positives[0],"panel") {
|
||||
if user.IsSuperMod {
|
||||
ok = true
|
||||
w.Header().Set("Cache-Control", "private")
|
||||
}
|
||||
} else {
|
||||
ok = true
|
||||
}
|
||||
break
|
||||
}
|
||||
rerr := posLoop(positives[0])
|
||||
if rerr != nil {
|
||||
return rerr
|
||||
}
|
||||
if !ok {
|
||||
return c.PreErrorJS("Outside of phrase prefix whitelist", w, r)
|
||||
}
|
||||
|
||||
pPhrases, ok := phrases.GetTmplPhrasesByPrefix(positives[0])
|
||||
if !ok {
|
||||
return c.PreErrorJS("No such prefix", w, r)
|
||||
|
|
Loading…
Reference in New Issue