lishwist/http/rsvp/response.go

120 lines
2.4 KiB
Go

package rsvp
import (
"bytes"
"encoding/json"
"fmt"
"lishwist/http/templates"
"log"
"net/http"
"strings"
)
type Response struct {
HtmlTemplateName string
Data any
SeeOther string
Session *Session
Status int
LogMessage string
}
func (res *Response) Write(w http.ResponseWriter, r *http.Request) error {
if res.LogMessage != "" {
log.Printf("%s --- %s\n", res.Data, res.LogMessage)
}
if res.Session != nil {
err := res.Session.inner.Save(r, w)
if err != nil {
return fmt.Errorf("Failed to write session: %w", err)
}
}
if res.SeeOther != "" {
http.Redirect(w, r, res.SeeOther, http.StatusSeeOther)
if res.Session != nil {
flash := res.Session.FlashPeek()
if flash != nil {
err := json.NewEncoder(w).Encode(flash)
if err != nil {
return err
}
}
}
return nil
}
bodyBytes := bytes.NewBuffer([]byte{})
accept := r.Header.Get("Accept")
if res.Status != 0 {
w.WriteHeader(res.Status)
}
switch {
case strings.Contains(accept, "text/html"):
if res.HtmlTemplateName == "" {
err := json.NewEncoder(bodyBytes).Encode(res.Data)
if err != nil {
return err
}
} else {
err := templates.Execute(bodyBytes, res.HtmlTemplateName, res.Data)
if err != nil {
return err
}
}
case strings.Contains(accept, "application/json"):
err := json.NewEncoder(bodyBytes).Encode(res.Data)
if err != nil {
return err
}
default:
err := json.NewEncoder(bodyBytes).Encode(res.Data)
if err != nil {
return err
}
}
_, err := w.Write(bodyBytes.Bytes())
if err != nil {
log.Printf("Failed to write rsvp.Response to HTTP: %s\n", err)
}
return nil
}
func Data(htmlTemplateName string, data any) Response {
return Response{
HtmlTemplateName: htmlTemplateName,
Data: data,
}
}
func (r Response) Log(format string, a ...any) Response {
r.LogMessage = fmt.Sprintf(format, a...)
return r
}
func (r Response) LogError(err error) Response {
r.LogMessage = fmt.Sprintf("%s", err)
return r
}
func (r Response) SaveSession(s Session) Response {
r.Session = &s
return r
}
func SeeOther(url string) Response {
return Response{SeeOther: url}
}
func Error(status int, format string, a ...any) Response {
return Response{
Status: status,
HtmlTemplateName: "error_page.gotmpl",
Data: struct{ Message string }{fmt.Sprintf(format, a...)},
}
}