diff --git a/micropub.go b/micropub.go index d3a1ac2..24bb8d6 100644 --- a/micropub.go +++ b/micropub.go @@ -13,7 +13,6 @@ import ( "github.com/samber/lo" "github.com/spf13/cast" - "go.goblog.app/app/pkgs/bufferpool" "go.goblog.app/app/pkgs/contenttype" "gopkg.in/yaml.v3" ) @@ -76,14 +75,12 @@ func (a *goBlog) serveMicropubQuery(w http.ResponseWriter, r *http.Request) { a.serve404(w, r) return } - buf := bufferpool.Get() - defer bufferpool.Put(buf) - if err := json.NewEncoder(buf).Encode(result); err != nil { - a.serveError(w, r, "Failed to encode json", http.StatusInternalServerError) - return - } + pr, pw := io.Pipe() + go func() { + _ = pw.CloseWithError(json.NewEncoder(pw).Encode(result)) + }() w.Header().Set(contentType, contenttype.JSONUTF8) - _ = a.min.Get().Minify(contenttype.JSON, w, buf) + _ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr)) } func (a *goBlog) getMicropubChannelsMap() []map[string]any { diff --git a/nodeinfo.go b/nodeinfo.go index ea2000d..2985918 100644 --- a/nodeinfo.go +++ b/nodeinfo.go @@ -5,29 +5,24 @@ import ( "io" "net/http" - "go.goblog.app/app/pkgs/bufferpool" "go.goblog.app/app/pkgs/contenttype" ) func (a *goBlog) serveNodeInfoDiscover(w http.ResponseWriter, r *http.Request) { - buf := bufferpool.Get() - defer bufferpool.Put(buf) - err := json.NewEncoder(buf).Encode(map[string]any{ + result := map[string]any{ "links": []map[string]any{ { "href": a.getFullAddress("/nodeinfo"), "rel": "http://nodeinfo.diaspora.software/ns/schema/2.1", }, }, - }) - if err != nil { - a.serveError(w, r, "", http.StatusInternalServerError) - return } + pr, pw := io.Pipe() + go func() { + _ = pw.CloseWithError(json.NewEncoder(pw).Encode(result)) + }() w.Header().Set(contentType, contenttype.JSONUTF8) - mw := a.min.Get().Writer(contenttype.JSON, w) - _, _ = io.Copy(mw, buf) - _ = mw.Close() + _ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr)) } func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) { @@ -35,9 +30,7 @@ func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) { status: []postStatus{statusPublished}, visibility: []postVisibility{visibilityPublic}, }) - buf := bufferpool.Get() - defer bufferpool.Put(buf) - if err := json.NewEncoder(buf).Encode(map[string]any{ + result := map[string]any{ "version": "2.1", "software": map[string]any{ "name": "goblog", @@ -55,10 +48,11 @@ func (a *goBlog) serveNodeInfo(w http.ResponseWriter, r *http.Request) { "webmention", }, "metadata": map[string]any{}, - }); err != nil { - a.serveError(w, r, "", http.StatusInternalServerError) - return } + pr, pw := io.Pipe() + go func() { + _ = pw.CloseWithError(json.NewEncoder(pw).Encode(result)) + }() w.Header().Set(contentType, contenttype.JSONUTF8) - _ = a.min.Get().Minify(contenttype.JSON, w, buf) + _ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr)) } diff --git a/opensearch.go b/opensearch.go index 5eedcc5..5bfc1a2 100644 --- a/opensearch.go +++ b/opensearch.go @@ -2,9 +2,9 @@ package main import ( "encoding/xml" + "io" "net/http" - "go.goblog.app/app/pkgs/bufferpool" "go.goblog.app/app/pkgs/contenttype" ) @@ -49,15 +49,13 @@ func (a *goBlog) serveOpenSearch(w http.ResponseWriter, r *http.Request) { }, SearchForm: sURL, } - buf := bufferpool.Get() - defer bufferpool.Put(buf) - _, _ = buf.WriteString(xml.Header) - if err := xml.NewEncoder(buf).Encode(openSearch); err != nil { - a.serveError(w, r, "", http.StatusInternalServerError) - return - } + pr, pw := io.Pipe() + go func() { + _, _ = io.WriteString(pw, xml.Header) + _ = pw.CloseWithError(xml.NewEncoder(pw).Encode(openSearch)) + }() w.Header().Set(contentType, "application/opensearchdescription+xml"+contenttype.CharsetUtf8Suffix) - _ = a.min.Get().Minify(contenttype.XML, w, buf) + _ = pr.CloseWithError(a.min.Get().Minify(contenttype.XML, w, pr)) } func openSearchUrl(b *configBlog) string { diff --git a/pkgs/highlighting/highlighting.go b/pkgs/highlighting/highlighting.go index 47ffd49..fe9728a 100644 --- a/pkgs/highlighting/highlighting.go +++ b/pkgs/highlighting/highlighting.go @@ -2,13 +2,13 @@ package highlighting import ( "io" + "strings" "github.com/yuin/goldmark" "github.com/yuin/goldmark/ast" "github.com/yuin/goldmark/renderer" "github.com/yuin/goldmark/renderer/html" "github.com/yuin/goldmark/util" - "go.goblog.app/app/pkgs/bufferpool" "github.com/alecthomas/chroma/v2" chromahtml "github.com/alecthomas/chroma/v2/formatters/html" @@ -60,8 +60,7 @@ func (r *htmlRenderer) renderFencedCodeBlock(w util.BufWriter, source []byte, no n := node.(*ast.FencedCodeBlock) // Read code block content. - buf := bufferpool.Get() - defer bufferpool.Put(buf) + var buf strings.Builder for _, line := range n.Lines().Sliced(0, n.Lines().Len()) { buf.Write(line.Value(source)) } @@ -70,7 +69,7 @@ func (r *htmlRenderer) renderFencedCodeBlock(w util.BufWriter, source []byte, no if highlight(w, buf.String(), string(n.Language(source)), r.formatter) != nil { // Highlight failed, fallback to plain text. _, _ = w.WriteString("
")
- r.Writer.RawWrite(w, buf.Bytes())
+ r.Writer.RawWrite(w, []byte(buf.String()))
_, _ = w.WriteString("
\n")
}
diff --git a/postsDb.go b/postsDb.go
index fec172a..e1f2a36 100644
--- a/postsDb.go
+++ b/postsDb.go
@@ -206,8 +206,7 @@ func (db *database) savePost(p *post, o *postCreationOptions) error {
db.pcm.Lock()
defer db.pcm.Unlock()
// Build SQL
- sqlBuilder := bufferpool.Get()
- defer bufferpool.Put(sqlBuilder)
+ var sqlBuilder strings.Builder
var sqlArgs = []any{dbNoCache}
// Start transaction
sqlBuilder.WriteString("begin;")
@@ -336,7 +335,7 @@ func (db *database) replacePostParam(path, param string, values []string) error
db.pcm.Lock()
defer db.pcm.Unlock()
// Build SQL
- sqlBuilder := bufferpool.Get()
+ var sqlBuilder strings.Builder
var sqlArgs = []any{dbNoCache}
// Start transaction
sqlBuilder.WriteString("begin;")
@@ -352,7 +351,6 @@ func (db *database) replacePostParam(path, param string, values []string) error
sqlBuilder.WriteString("commit;")
// Execute
_, err := db.Exec(sqlBuilder.String(), sqlArgs...)
- bufferpool.Put(sqlBuilder)
if err != nil {
return err
}
@@ -387,8 +385,7 @@ type postsRequestConfig struct {
}
func buildPostsQuery(c *postsRequestConfig, selection string) (query string, args []any) {
- queryBuilder := bufferpool.Get()
- defer bufferpool.Put(queryBuilder)
+ var queryBuilder strings.Builder
// Selection
queryBuilder.WriteString("select ")
queryBuilder.WriteString(selection)
@@ -413,11 +410,11 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
queryBuilder.WriteString(", ")
}
named := "status" + strconv.Itoa(i)
- queryBuilder.WriteByte('@')
+ queryBuilder.WriteString("@")
queryBuilder.WriteString(named)
args = append(args, sql.Named(named, status))
}
- queryBuilder.WriteByte(')')
+ queryBuilder.WriteString(")")
}
if c.visibility != nil && len(c.visibility) > 0 {
queryBuilder.WriteString(" and visibility in (")
@@ -426,11 +423,11 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
queryBuilder.WriteString(", ")
}
named := "visibility" + strconv.Itoa(i)
- queryBuilder.WriteByte('@')
+ queryBuilder.WriteString("@")
queryBuilder.WriteString(named)
args = append(args, sql.Named(named, visibility))
}
- queryBuilder.WriteByte(')')
+ queryBuilder.WriteString(")")
}
if c.blog != "" {
queryBuilder.WriteString(" and blog = @blog")
@@ -451,7 +448,7 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
queryBuilder.WriteString(", ")
}
named := "param" + strconv.Itoa(i)
- queryBuilder.WriteByte('@')
+ queryBuilder.WriteString("@")
queryBuilder.WriteString(named)
args = append(args, param)
}
@@ -477,11 +474,11 @@ func buildPostsQuery(c *postsRequestConfig, selection string) (query string, arg
queryBuilder.WriteString(", ")
}
named := "section" + strconv.Itoa(i)
- queryBuilder.WriteByte('@')
+ queryBuilder.WriteString("@")
queryBuilder.WriteString(named)
args = append(args, sql.Named(named, section))
}
- queryBuilder.WriteByte(')')
+ queryBuilder.WriteString(")")
}
if c.publishedYear != 0 {
queryBuilder.WriteString(" and substr(tolocal(published), 1, 4) = @publishedyear")
@@ -522,8 +519,7 @@ func (d *database) loadPostParameters(posts []*post, parameters ...string) (err
}
// Build query
sqlArgs := make([]any, 0)
- queryBuilder := bufferpool.Get()
- defer bufferpool.Put(queryBuilder)
+ var queryBuilder strings.Builder
queryBuilder.WriteString("select path, parameter, value from post_parameters where")
// Paths
queryBuilder.WriteString(" path in (")
@@ -532,11 +528,11 @@ func (d *database) loadPostParameters(posts []*post, parameters ...string) (err
queryBuilder.WriteString(", ")
}
named := "path" + strconv.Itoa(i)
- queryBuilder.WriteByte('@')
+ queryBuilder.WriteString("@")
queryBuilder.WriteString(named)
sqlArgs = append(sqlArgs, sql.Named(named, p.Path))
}
- queryBuilder.WriteByte(')')
+ queryBuilder.WriteString(")")
// Parameters
if len(parameters) > 0 {
queryBuilder.WriteString(" and parameter in (")
@@ -545,11 +541,11 @@ func (d *database) loadPostParameters(posts []*post, parameters ...string) (err
queryBuilder.WriteString(", ")
}
named := "param" + strconv.Itoa(i)
- queryBuilder.WriteByte('@')
+ queryBuilder.WriteString("@")
queryBuilder.WriteString(named)
sqlArgs = append(sqlArgs, sql.Named(named, p))
}
- queryBuilder.WriteByte(')')
+ queryBuilder.WriteString(")")
}
// Order
queryBuilder.WriteString(" order by id")
@@ -695,7 +691,7 @@ group by name;
func (db *database) usesOfMediaFile(names ...string) (counts []int, err error) {
sqlArgs := []any{dbNoCache}
- nameValues := bufferpool.Get()
+ var nameValues strings.Builder
for i, n := range names {
if i > 0 {
nameValues.WriteString(", ")
@@ -703,11 +699,10 @@ func (db *database) usesOfMediaFile(names ...string) (counts []int, err error) {
named := "name" + strconv.Itoa(i)
nameValues.WriteString("(@")
nameValues.WriteString(named)
- nameValues.WriteByte(')')
+ nameValues.WriteString(")")
sqlArgs = append(sqlArgs, sql.Named(named, n))
}
rows, err := db.Query(fmt.Sprintf(mediaUseSql, nameValues.String()), sqlArgs...)
- bufferpool.Put(nameValues)
if err != nil {
return nil, err
}
diff --git a/reactions.go b/reactions.go
index 40c5575..fd69e2c 100644
--- a/reactions.go
+++ b/reactions.go
@@ -5,10 +5,10 @@ import (
"errors"
"io"
"net/http"
+ "strings"
"github.com/dgraph-io/ristretto"
"github.com/samber/lo"
- "go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype"
)
@@ -88,15 +88,12 @@ func (a *goBlog) getReactions(w http.ResponseWriter, r *http.Request) {
a.serveError(w, r, "", http.StatusInternalServerError)
return
}
- buf := bufferpool.Get()
- defer bufferpool.Put(buf)
- err = json.NewEncoder(buf).Encode(reactions)
- if err != nil {
- a.serveError(w, r, "", http.StatusInternalServerError)
- return
- }
+ pr, pw := io.Pipe()
+ go func() {
+ _ = pw.CloseWithError(json.NewEncoder(pw).Encode(reactions))
+ }()
w.Header().Set(contentType, contenttype.JSONUTF8)
- _, _ = io.Copy(w, buf)
+ _ = pr.CloseWithError(a.min.Get().Minify(contenttype.JSON, w, pr))
}
func (a *goBlog) getReactionsFromDatabase(path string) (map[string]int, error) {
@@ -110,8 +107,7 @@ func (a *goBlog) getReactionsFromDatabase(path string) (map[string]int, error) {
// Get reactions
res, err, _ := a.reactionsSfg.Do(path, func() (any, error) {
// Build query
- sqlBuf := bufferpool.Get()
- defer bufferpool.Put(sqlBuf)
+ var sqlBuf strings.Builder
sqlArgs := []any{}
sqlBuf.WriteString("select reaction, count from reactions where path=? and reaction in (")
sqlArgs = append(sqlArgs, path)
diff --git a/reactions_test.go b/reactions_test.go
index 757cd9d..50e93f8 100644
--- a/reactions_test.go
+++ b/reactions_test.go
@@ -136,13 +136,13 @@ func Test_reactionsHighLevel(t *testing.T) {
rec = httptest.NewRecorder()
app.getReactions(rec, req)
assert.Equal(t, http.StatusOK, rec.Code)
- assert.Equal(t, "{\"❤️\":1}\n", rec.Body.String())
+ assert.Equal(t, "{\"❤️\":1}", rec.Body.String())
// Get reactions for a non-existing post
req = httptest.NewRequest(http.MethodGet, "/?path=/non-existing-post", nil)
rec = httptest.NewRecorder()
app.getReactions(rec, req)
assert.Equal(t, http.StatusOK, rec.Code)
- assert.Equal(t, "{}\n", rec.Body.String())
+ assert.Equal(t, "{}", rec.Body.String())
}
diff --git a/sitemap.go b/sitemap.go
index 75769b8..3580c22 100644
--- a/sitemap.go
+++ b/sitemap.go
@@ -3,12 +3,12 @@ package main
import (
"database/sql"
"encoding/xml"
+ "io"
"net/http"
"time"
"github.com/araddon/dateparse"
"github.com/snabb/sitemap"
- "go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype"
)
@@ -174,18 +174,16 @@ func (a *goBlog) serveSitemapBlogPosts(w http.ResponseWriter, r *http.Request) {
}
func (a *goBlog) writeSitemapXML(w http.ResponseWriter, r *http.Request, sm any) {
- buf := bufferpool.Get()
- defer bufferpool.Put(buf)
- _, _ = buf.WriteString(xml.Header)
- _, _ = buf.WriteString(``)
- if err := xml.NewEncoder(buf).Encode(sm); err != nil {
- a.serveError(w, r, "Failed to encode sitemap", http.StatusInternalServerError)
- return
- }
+ pr, pw := io.Pipe()
+ go func() {
+ _, _ = io.WriteString(pw, xml.Header)
+ _, _ = io.WriteString(pw, ``)
+ _ = pw.CloseWithError(xml.NewEncoder(pw).Encode(sm))
+ }()
w.Header().Set(contentType, contenttype.XMLUTF8)
- _ = a.min.Get().Minify(contenttype.XML, w, buf)
+ _ = pr.CloseWithError(a.min.Get().Minify(contenttype.XML, w, pr))
}
const sitemapDatePathsSql = `
diff --git a/telegram.go b/telegram.go
index cce491a..b3a081d 100644
--- a/telegram.go
+++ b/telegram.go
@@ -5,9 +5,9 @@ import (
"log"
"net/url"
"strconv"
+ "strings"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
- "go.goblog.app/app/pkgs/bufferpool"
)
func (a *goBlog) initTelegram() {
@@ -135,8 +135,7 @@ func (tg *configTelegram) generateHTML(title, fullURL, shortURL string) (html st
if !tg.enabled() {
return ""
}
- message := bufferpool.Get()
- defer bufferpool.Put(message)
+ var message strings.Builder
if title != "" {
message.WriteString(tgbotapi.EscapeText(tgbotapi.ModeHTML, title))
message.WriteString("\n\n")
diff --git a/uiComponents.go b/uiComponents.go
index 14acacb..3b2ea1b 100644
--- a/uiComponents.go
+++ b/uiComponents.go
@@ -6,7 +6,6 @@ import (
"time"
"github.com/samber/lo"
- "go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/htmlbuilder"
)
@@ -65,7 +64,7 @@ func (a *goBlog) renderSummary(hb *htmlbuilder.HtmlBuilder, bc *configBlog, p *p
}
// Show link to full post
hb.WriteElementOpen("p")
- prefix := bufferpool.Get()
+ var prefix strings.Builder
if len(photos) > 0 {
// Contains photos
prefix.WriteString("🖼️")
@@ -75,10 +74,9 @@ func (a *goBlog) renderSummary(hb *htmlbuilder.HtmlBuilder, bc *configBlog, p *p
prefix.WriteString("🗺️")
}
if prefix.Len() > 0 {
- prefix.WriteRune(' ')
+ prefix.WriteString(" ")
hb.WriteEscaped(prefix.String())
}
- bufferpool.Put(prefix)
hb.WriteElementOpen("a", "class", "u-url", "href", p.Path)
hb.WriteEscaped(a.ts.GetTemplateStringVariant(bc.Lang, "view"))
hb.WriteElementClose("a")
diff --git a/webmention.go b/webmention.go
index 52adab4..770cd40 100644
--- a/webmention.go
+++ b/webmention.go
@@ -8,7 +8,6 @@ import (
"strings"
"time"
- "go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/contenttype"
)
@@ -231,8 +230,7 @@ type webmentionsRequestConfig struct {
}
func buildWebmentionsQuery(config *webmentionsRequestConfig) (query string, args []any) {
- queryBuilder := bufferpool.Get()
- defer bufferpool.Put(queryBuilder)
+ var queryBuilder strings.Builder
queryBuilder.WriteString("select id, source, target, url, created, title, content, author, status from webmentions ")
if config != nil {
queryBuilder.WriteString("where 1")