pink_fox/application/packages/fw/response.go

133 lines
2.8 KiB
Go

package fw
import (
"fmt"
"github.com/CloudyKit/jet/v6"
"net/http"
)
type Response interface {
Render() Error
WriteHeader(statusCode int)
}
type ResponseFactory struct {
writer http.ResponseWriter
template *JetTemplate
GetView func() any
}
func NewResponseFactory(writer http.ResponseWriter, template *JetTemplate, getView func() any) *ResponseFactory {
return &ResponseFactory{
writer: writer,
template: template,
GetView: getView,
}
}
func (it *ResponseFactory) String(str string) *StringResponse {
return NewStringResponse(it.writer, str)
}
func (it *ResponseFactory) HtmlError(code int, message string) *HtmlErrorResponse {
return NewHtmlErrorResponse(it.makeJetRender(), code, message)
}
func (it *ResponseFactory) View(template string, data any) *ViewResponse {
return NewViewResponse(it.makeJetRender(), template, data)
}
func (it *ResponseFactory) makeJetRender() *JetRender {
variables := make(jet.VarMap)
if it.GetView != nil {
variables.Set("vi", it.GetView())
}
return NewJetRender(it.template, it.writer, variables)
}
type BaseResponse struct {
statusCode int
}
func (it *BaseResponse) WriteHeader(statusCode int) {
it.statusCode = statusCode
}
type StringResponse struct {
BaseResponse
str string
writer http.ResponseWriter
}
func NewStringResponse(writer http.ResponseWriter, str string) *StringResponse {
return &StringResponse{
writer: writer,
str: str,
}
}
func (it *StringResponse) Render() Error {
it.writer.WriteHeader(it.statusCode)
_, err := it.writer.Write([]byte(it.str))
if err != nil {
return Err(err)
}
return nil
}
type HtmlErrorResponse struct {
ViewResponse
statusCode int
message string
}
func NewHtmlErrorResponse(render *JetRender, code int, message string) *HtmlErrorResponse {
return &HtmlErrorResponse{
ViewResponse: *NewViewResponse(render, "errors/error.html", nil),
statusCode: code,
message: message,
}
}
func (it *HtmlErrorResponse) Render() Error {
fmt.Println("status", it.statusCode)
it.render.Writer.WriteHeader(it.statusCode)
err := it.render.Render(it.template, map[string]any{
"title": fmt.Sprintf("%d %s", it.statusCode, http.StatusText(it.statusCode)),
"message": it.message,
})
if err != nil {
return err.Tap()
}
return nil
}
type ViewResponse struct {
BaseResponse
render *JetRender
template string
data any
}
func NewViewResponse(render *JetRender, template string, data any) *ViewResponse {
return &ViewResponse{
render: render,
template: template,
data: data,
}
}
func (it *ViewResponse) Set(key string, value interface{}) *ViewResponse {
it.render.Variables.Set(key, value)
return it
}
func (it *ViewResponse) Render() Error {
it.render.Writer.WriteHeader(it.statusCode)
err := it.render.Render(it.template, it.data)
if err != nil {
return err.Tap()
}
return nil
}