Skip to content

Commit d2ddedd

Browse files
committed
Get rid of github.com/go-chi/render use
1 parent 34ea4c3 commit d2ddedd

File tree

8 files changed

+79
-72
lines changed

8 files changed

+79
-72
lines changed

backend/app/rest/api/admin.go

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"time"
88

99
"github.com/go-chi/chi/v5"
10-
"github.com/go-chi/render"
1110
"github.com/go-pkgz/auth/v2"
1211
cache "github.com/go-pkgz/lcw/v2"
1312
log "github.com/go-pkgz/lgr"
@@ -54,8 +53,7 @@ func (a *admin) deleteCommentCtrl(w http.ResponseWriter, r *http.Request) {
5453
return
5554
}
5655
a.cache.Flush(cache.Flusher(locator.SiteID).Scopes(locator.SiteID, locator.URL, lastCommentsScope))
57-
render.Status(r, http.StatusOK)
58-
render.JSON(w, r, R.JSON{"id": id, "locator": locator})
56+
R.RenderJSON(w, R.JSON{"id": id, "locator": locator})
5957
}
6058

6159
// DELETE /user/{userid}?site=side-id - delete all user comments for requested userid
@@ -69,8 +67,7 @@ func (a *admin) deleteUserCtrl(w http.ResponseWriter, r *http.Request) {
6967
return
7068
}
7169
a.cache.Flush(cache.Flusher(siteID).Scopes(userID, siteID, lastCommentsScope))
72-
render.Status(r, http.StatusOK)
73-
render.JSON(w, r, R.JSON{"user_id": userID, "site_id": siteID})
70+
R.RenderJSON(w, R.JSON{"user_id": userID, "site_id": siteID})
7471
}
7572

7673
// GET /user/{userid}?site=side-id - get user info for requested userid
@@ -84,8 +81,7 @@ func (a *admin) getUserInfoCtrl(w http.ResponseWriter, r *http.Request) {
8481
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't get user info", rest.ErrInternal)
8582
return
8683
}
87-
render.Status(r, http.StatusOK)
88-
render.JSON(w, r, ucomments[0].User)
84+
R.RenderJSON(w, ucomments[0].User)
8985
}
9086

9187
// GET /deleteme?token=jwt - delete all user comments and details by user's request. Gets info about deleted used from provided token
@@ -135,8 +131,7 @@ func (a *admin) deleteMeRequestCtrl(w http.ResponseWriter, r *http.Request) {
135131
}
136132

137133
a.cache.Flush(cache.Flusher(audience).Scopes(audience, claims.User.ID, lastCommentsScope))
138-
render.Status(r, http.StatusOK)
139-
render.JSON(w, r, R.JSON{"user_id": claims.User.ID, "site_id": claims.Audience})
134+
R.RenderJSON(w, R.JSON{"user_id": claims.User.ID, "site_id": claims.Audience})
140135
}
141136

142137
// PUT /user/{userid}?site=side-id&block=1&ttl=7d - block or unblock user
@@ -164,7 +159,7 @@ func (a *admin) setBlockCtrl(w http.ResponseWriter, r *http.Request) {
164159
}
165160
}
166161
a.cache.Flush(cache.Flusher(siteID).Scopes(userID, siteID, lastCommentsScope))
167-
render.JSON(w, r, R.JSON{"user_id": userID, "site_id": siteID, "block": blockStatus})
162+
R.RenderJSON(w, R.JSON{"user_id": userID, "site_id": siteID, "block": blockStatus})
168163
}
169164

170165
// GET /blocked?site=siteID - list blocked users
@@ -175,7 +170,7 @@ func (a *admin) blockedUsersCtrl(w http.ResponseWriter, r *http.Request) {
175170
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't get blocked users", rest.ErrSiteNotFound)
176171
return
177172
}
178-
render.JSON(w, r, users)
173+
R.RenderJSON(w, users)
179174
}
180175

181176
// PUT /readonly?site=siteID&url=post-url&ro=1 - set or reset read-only status for the post
@@ -202,7 +197,7 @@ func (a *admin) setReadOnlyCtrl(w http.ResponseWriter, r *http.Request) {
202197
return
203198
}
204199
a.cache.Flush(cache.Flusher(locator.SiteID).Scopes(locator.URL, locator.SiteID))
205-
render.JSON(w, r, R.JSON{"locator": locator, "read-only": roStatus})
200+
R.RenderJSON(w, R.JSON{"locator": locator, "read-only": roStatus})
206201
}
207202

208203
// PUT /title/{id}?site=siteID&url=post-url - set comment PostTitle to page's title
@@ -218,8 +213,7 @@ func (a *admin) setTitleCtrl(w http.ResponseWriter, r *http.Request) {
218213
log.Printf("[INFO] set comment's title %s to %q", id, c.PostTitle)
219214

220215
a.cache.Flush(cache.Flusher(locator.SiteID).Scopes(locator.URL, lastCommentsScope))
221-
render.Status(r, http.StatusOK)
222-
render.JSON(w, r, R.JSON{"id": id, "locator": locator})
216+
R.RenderJSON(w, R.JSON{"id": id, "locator": locator})
223217
}
224218

225219
// PUT /verify?site=siteID&url=post-url&ro=1 - set or reset read-only status for the post
@@ -233,7 +227,7 @@ func (a *admin) setVerifyCtrl(w http.ResponseWriter, r *http.Request) {
233227
return
234228
}
235229
a.cache.Flush(cache.Flusher(siteID).Scopes(siteID, userID))
236-
render.JSON(w, r, R.JSON{"user": userID, "verified": verifyStatus})
230+
R.RenderJSON(w, R.JSON{"user": userID, "verified": verifyStatus})
237231
}
238232

239233
// PUT /pin/{id}?site=siteID&url=post-url&pin=1
@@ -248,5 +242,5 @@ func (a *admin) setPinCtrl(w http.ResponseWriter, r *http.Request) {
248242
return
249243
}
250244
a.cache.Flush(cache.Flusher(locator.SiteID).Scopes(locator.URL))
251-
render.JSON(w, r, R.JSON{"id": commentID, "locator": locator, "pin": pinStatus})
245+
R.RenderJSON(w, R.JSON{"id": commentID, "locator": locator, "pin": pinStatus})
252246
}

backend/app/rest/api/migrator.go

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"sync"
1111
"time"
1212

13-
"github.com/go-chi/render"
1413
cache "github.com/go-pkgz/lcw/v2"
1514
log "github.com/go-pkgz/lgr"
1615
R "github.com/go-pkgz/rest"
@@ -58,8 +57,8 @@ func (m *Migrator) importCtrl(w http.ResponseWriter, r *http.Request) {
5857

5958
go m.runImport(siteID, r.URL.Query().Get("provider"), tmpfile) // import runs in background and sets busy flag for site
6059

61-
render.Status(r, http.StatusAccepted)
62-
render.JSON(w, r, R.JSON{"status": "import request accepted"})
60+
w.WriteHeader(http.StatusAccepted)
61+
R.RenderJSON(w, R.JSON{"status": "import request accepted"})
6362
}
6463

6564
// POST /import/form?secret=key&site=site-id&provider=disqus|remark|wordpress
@@ -93,8 +92,8 @@ func (m *Migrator) importFormCtrl(w http.ResponseWriter, r *http.Request) {
9392

9493
go m.runImport(siteID, r.URL.Query().Get("provider"), tmpfile) // import runs in background and sets busy flag for site
9594

96-
render.Status(r, http.StatusAccepted)
97-
render.JSON(w, r, R.JSON{"status": "import request accepted"})
95+
w.WriteHeader(http.StatusAccepted)
96+
R.RenderJSON(w, R.JSON{"status": "import request accepted"})
9897
}
9998

10099
// GET /wait?site=site-id
@@ -114,21 +113,28 @@ func (m *Migrator) waitCtrl(w http.ResponseWriter, r *http.Request) {
114113

115114
select {
116115
case <-ctx.Done():
117-
render.Status(r, http.StatusGatewayTimeout)
118-
render.JSON(w, r, R.JSON{"status": "timeout expired", "site_id": siteID})
116+
w.WriteHeader(http.StatusGatewayTimeout)
117+
R.RenderJSON(w, R.JSON{"status": "timeout expired", "site_id": siteID})
119118
return
120119
case <-time.After(100 * time.Millisecond):
121120
}
122121
}
123-
render.Status(r, http.StatusOK)
124-
render.JSON(w, r, R.JSON{"status": "completed", "site_id": siteID})
122+
R.RenderJSON(w, R.JSON{"status": "completed", "site_id": siteID})
125123
}
126124

127125
// GET /export?site=site-id&secret=12345&?mode=file|stream
128126
// exports all comments for siteID as gz file
129127
func (m *Migrator) exportCtrl(w http.ResponseWriter, r *http.Request) {
130128
siteID := r.URL.Query().Get("site")
131129

130+
// Check if export would succeed before setting headers
131+
// Use a nil writer for this check to avoid any partial writes
132+
if _, err := m.NativeExporter.Export(io.Discard, siteID); err != nil {
133+
rest.SendErrorJSON(w, r, http.StatusInternalServerError, err, "export failed", rest.ErrInternal)
134+
return
135+
}
136+
137+
// If we got here, the export should succeed, so we can set headers and perform the actual export
132138
var writer io.Writer = w
133139
if r.URL.Query().Get("mode") == "file" {
134140
exportFile := fmt.Sprintf("%s-%s.json.gz", siteID, time.Now().Format("20060102"))
@@ -143,10 +149,8 @@ func (m *Migrator) exportCtrl(w http.ResponseWriter, r *http.Request) {
143149
writer = gzWriter
144150
}
145151

146-
if _, err := m.NativeExporter.Export(writer, siteID); err != nil {
147-
rest.SendErrorJSON(w, r, http.StatusInternalServerError, err, "export failed", rest.ErrInternal)
148-
return
149-
}
152+
// Actually perform the export
153+
_, _ = m.NativeExporter.Export(writer, siteID)
150154
}
151155

152156
// POST /remap?site=site-id
@@ -201,8 +205,8 @@ func (m *Migrator) remapCtrl(w http.ResponseWriter, r *http.Request) {
201205
log.Printf("[DEBUG] convert request completed. site=%s, comments=%d", siteID, size)
202206
}()
203207

204-
render.Status(r, http.StatusAccepted)
205-
render.JSON(w, r, R.JSON{"status": "convert request accepted"})
208+
w.WriteHeader(http.StatusAccepted)
209+
R.RenderJSON(w, R.JSON{"status": "convert request accepted"})
206210
}
207211

208212
// runImport reads from tmpfile and import for given siteID and provider

backend/app/rest/api/rest.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"github.com/go-chi/chi/v5"
2121
"github.com/go-chi/chi/v5/middleware"
2222
"github.com/go-chi/cors"
23-
"github.com/go-chi/render"
2423
"github.com/go-pkgz/auth/v2"
2524
"github.com/go-pkgz/lcw/v2"
2625
log "github.com/go-pkgz/lgr"
@@ -473,8 +472,7 @@ func (s *Rest) configCtrl(w http.ResponseWriter, r *http.Request) {
473472
if cnf.Admins == nil { // prevent json serialization to nil
474473
cnf.Admins = []string{}
475474
}
476-
render.Status(r, http.StatusOK)
477-
render.JSON(w, r, cnf)
475+
R.RenderJSON(w, cnf)
478476
}
479477

480478
// serves static files from the webRoot directory or files embedded into the compiled binary if that directory is absent

backend/app/rest/api/rest_private.go

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"time"
1616

1717
"github.com/go-chi/chi/v5"
18-
"github.com/go-chi/render"
1918
"github.com/go-pkgz/auth/v2"
2019
"github.com/go-pkgz/auth/v2/token"
2120
cache "github.com/go-pkgz/lcw/v2"
@@ -77,7 +76,7 @@ func (s *private) previewCommentCtrl(w http.ResponseWriter, r *http.Request) {
7776
user := rest.MustGetUserInfo(r)
7877

7978
comment := store.Comment{}
80-
if err := render.DecodeJSON(http.MaxBytesReader(w, r.Body, hardBodyLimit), &comment); err != nil {
79+
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, hardBodyLimit)).Decode(&comment); err != nil {
8180
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't bind comment", rest.ErrDecode)
8281
return
8382
}
@@ -100,14 +99,13 @@ func (s *private) previewCommentCtrl(w http.ResponseWriter, r *http.Request) {
10099
return
101100
}
102101
}
103-
104-
render.HTML(w, r, comment.Text)
102+
rest.HTMLResponse(w, http.StatusOK, comment.Text)
105103
}
106104

107105
// POST /comment - adds comment, resets all immutable fields
108106
func (s *private) createCommentCtrl(w http.ResponseWriter, r *http.Request) {
109107
comment := store.Comment{}
110-
if err := render.DecodeJSON(http.MaxBytesReader(w, r.Body, hardBodyLimit), &comment); err != nil {
108+
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, hardBodyLimit)).Decode(&comment); err != nil {
111109
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't bind comment", rest.ErrDecode)
112110
return
113111
}
@@ -176,8 +174,8 @@ func (s *private) createCommentCtrl(w http.ResponseWriter, r *http.Request) {
176174

177175
log.Printf("[DEBUG] created comment %+v", finalComment)
178176

179-
render.Status(r, http.StatusCreated)
180-
render.JSON(w, r, &finalComment)
177+
w.WriteHeader(http.StatusCreated)
178+
R.RenderJSON(w, &finalComment)
181179
}
182180

183181
// PUT /comment/{id}?site=siteID&url=post-url - update comment
@@ -188,7 +186,7 @@ func (s *private) updateCommentCtrl(w http.ResponseWriter, r *http.Request) {
188186
Delete bool
189187
}{}
190188

191-
if err := render.DecodeJSON(http.MaxBytesReader(w, r.Body, hardBodyLimit), &edit); err != nil {
189+
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, hardBodyLimit)).Decode(&edit); err != nil {
192190
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't read comment details from body", rest.ErrDecode)
193191
return
194192
}
@@ -233,7 +231,7 @@ func (s *private) updateCommentCtrl(w http.ResponseWriter, r *http.Request) {
233231
}
234232

235233
s.cache.Flush(cache.Flusher(locator.SiteID).Scopes(locator.SiteID, locator.URL, lastCommentsScope, user.ID))
236-
render.JSON(w, r, res)
234+
R.RenderJSON(w, res)
237235
}
238236

239237
// GET /user?site=siteID - returns user info
@@ -251,7 +249,7 @@ func (s *private) userInfoCtrl(w http.ResponseWriter, r *http.Request) {
251249
}
252250
}
253251

254-
render.JSON(w, r, user)
252+
R.RenderJSON(w, user)
255253
}
256254

257255
// PUT /vote/{id}?site=siteID&url=post-url&vote=1 - vote for/against comment
@@ -292,7 +290,7 @@ func (s *private) voteCtrl(w http.ResponseWriter, r *http.Request) {
292290
return
293291
}
294292
s.cache.Flush(cache.Flusher(locator.SiteID).Scopes(locator.URL, comment.User.ID))
295-
render.JSON(w, r, R.JSON{"id": comment.ID, "score": comment.Score})
293+
R.RenderJSON(w, R.JSON{"id": comment.ID, "score": comment.Score})
296294
}
297295

298296
// getEmailCtrl gets email address for authenticated user.
@@ -305,7 +303,7 @@ func (s *private) getEmailCtrl(w http.ResponseWriter, r *http.Request) {
305303
log.Printf("[WARN] can't read email for %s, %v", user.ID, err)
306304
}
307305

308-
render.JSON(w, r, R.JSON{"user": user, "address": address})
306+
R.RenderJSON(w, R.JSON{"user": user, "address": address})
309307
}
310308

311309
// sendEmailConfirmationCtrl gets address and siteID from query, makes confirmation token and sends it to user.
@@ -322,7 +320,7 @@ func (s *private) sendEmailConfirmationCtrl(w http.ResponseWriter, r *http.Reque
322320
Address string
323321
autoConfirm bool
324322
}{autoConfirm: true}
325-
if err := render.DecodeJSON(http.MaxBytesReader(w, r.Body, hardBodyLimit), &subscribe); err != nil {
323+
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, hardBodyLimit)).Decode(&subscribe); err != nil {
326324
if err != io.EOF {
327325
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't parse request body", rest.ErrDecode)
328326
return
@@ -385,7 +383,7 @@ func (s *private) sendEmailConfirmationCtrl(w http.ResponseWriter, r *http.Reque
385383
},
386384
)
387385

388-
render.JSON(w, r, R.JSON{"user": user, "address": subscribe.Address, "updated": false})
386+
R.RenderJSON(w, R.JSON{"user": user, "address": subscribe.Address, "updated": false})
389387
}
390388

391389
// telegramSubscribeCtrl generates and verifies telegram notification request
@@ -423,7 +421,7 @@ func (s *private) telegramSubscribeCtrl(w http.ResponseWriter, r *http.Request)
423421

424422
s.telegramService.AddToken(tkn, user.ID, siteID, expires)
425423

426-
render.JSON(w, r, R.JSON{"token": tkn, "bot": s.telegramService.GetBotUsername()})
424+
R.RenderJSON(w, R.JSON{"token": tkn, "bot": s.telegramService.GetBotUsername()})
427425

428426
return
429427
}
@@ -445,7 +443,7 @@ func (s *private) telegramSubscribeCtrl(w http.ResponseWriter, r *http.Request)
445443
return
446444
}
447445

448-
render.JSON(w, r, R.JSON{"updated": true, "address": val})
446+
R.RenderJSON(w, R.JSON{"updated": true, "address": val})
449447
}
450448

451449
// setConfirmedEmailCtrl uses provided token parameter (generated by sendEmailConfirmationCtrl) to set email and add it to user token
@@ -457,7 +455,7 @@ func (s *private) setConfirmedEmailCtrl(w http.ResponseWriter, r *http.Request)
457455
Site string
458456
Token string
459457
}{}
460-
if err := render.DecodeJSON(http.MaxBytesReader(w, r.Body, hardBodyLimit), &confirm); err != nil {
458+
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, hardBodyLimit)).Decode(&confirm); err != nil {
461459
if err != io.EOF {
462460
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't parse request body", rest.ErrDecode)
463461
return
@@ -513,7 +511,7 @@ func (s *private) setEmail(w http.ResponseWriter, r *http.Request, userID, siteI
513511
rest.SendErrorJSON(w, r, http.StatusInternalServerError, err, "failed to set token", rest.ErrInternal)
514512
return
515513
}
516-
render.JSON(w, r, R.JSON{"updated": true, "address": val})
514+
R.RenderJSON(w, R.JSON{"updated": true, "address": val})
517515
}
518516

519517
// POST/GET /email/unsubscribe.html?site=siteID&tkn=jwt - unsubscribe the user in token from email notifications
@@ -597,7 +595,7 @@ func (s *private) emailUnsubscribeCtrl(w http.ResponseWriter, r *http.Request) {
597595
tmpl := template.Must(template.New("unsubscribe").Parse(tmplstr))
598596
msg := bytes.Buffer{}
599597
MustExecute(tmpl, &msg, nil)
600-
render.HTML(w, r, msg.String())
598+
rest.HTMLResponse(w, http.StatusOK, msg.String())
601599
}
602600

603601
// DELETE /email?site=siteID - removes user's email
@@ -624,7 +622,7 @@ func (s *private) deleteEmailCtrl(w http.ResponseWriter, r *http.Request) {
624622
return
625623
}
626624
}
627-
render.JSON(w, r, R.JSON{"deleted": true})
625+
R.RenderJSON(w, R.JSON{"deleted": true})
628626
}
629627

630628
// DELETE /telegram?site=siteID - removes user's telegram
@@ -638,7 +636,7 @@ func (s *private) deleteTelegramCtrl(w http.ResponseWriter, r *http.Request) {
638636
rest.SendErrorJSON(w, r, http.StatusBadRequest, err, "can't delete telegram for user", code)
639637
return
640638
}
641-
render.JSON(w, r, R.JSON{"deleted": true})
639+
R.RenderJSON(w, R.JSON{"deleted": true})
642640
}
643641

644642
// GET /userdata?site=siteID - exports all data about the user as a json with user info and list of all comments
@@ -726,7 +724,7 @@ func (s *private) deleteMeCtrl(w http.ResponseWriter, r *http.Request) {
726724
}
727725

728726
link := fmt.Sprintf("%s/web/deleteme.html?token=%s", s.remarkURL, tokenStr)
729-
render.JSON(w, r, R.JSON{"site": siteID, "user_id": user.ID, "token": tokenStr, "link": link})
727+
R.RenderJSON(w, R.JSON{"site": siteID, "user_id": user.ID, "token": tokenStr, "link": link})
730728
}
731729

732730
// POST /image - save image with form request
@@ -751,7 +749,7 @@ func (s *private) savePictureCtrl(w http.ResponseWriter, r *http.Request) {
751749
return
752750
}
753751

754-
render.JSON(w, r, R.JSON{"id": id})
752+
R.RenderJSON(w, R.JSON{"id": id})
755753
}
756754

757755
func (s *private) isReadOnly(locator store.Locator) bool {

0 commit comments

Comments
 (0)