Files
hsp.go/hsp/response.go
2025-04-19 12:38:40 +02:00

136 lines
2.6 KiB
Go

package hsp
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"log"
"maps"
"strconv"
)
type Response struct {
StatusCode int
Format DataFormat
Headers map[string]string
Payload []byte
}
func NewPacketResponse(packet *Packet) *Response {
status, sok := packet.Headers[H_STATUS]
if !sok {
panic(errors.New("Packet must contain status header for response"))
}
format, fok := packet.Headers[H_DATA_FORMAT]
if !fok {
panic(errors.New("Packet must contain data format header for response"))
}
s, err := strconv.Atoi(status)
if err != nil {
panic(errors.New(fmt.Sprintf("Packet's status code is invalid: %s", err.Error())))
}
df, err := ParseDataFormat(format)
if err != nil {
panic(errors.New(fmt.Sprintf("Failed to parse packet's data format: %s", err.Error())))
}
return &Response{
StatusCode: s,
Format: *df,
Headers: packet.Headers,
Payload: packet.Payload,
}
}
func NewStatusResponse(status int) *Response {
return &Response{
StatusCode: status,
Headers: make(map[string]string),
Format: DataFormat{
Format: DF_BYTES,
Encoding: "",
},
Payload: make([]byte, 0),
}
}
func NewTextResponse(text string) *Response {
return &Response{
StatusCode: STATUS_SUCCESS,
Headers: make(map[string]string),
Format: DataFormat{
Format: DF_TEXT,
Encoding: E_UTF8,
},
Payload: []byte(text),
}
}
func NewErrorResponse(err error) *Response {
return &Response{
StatusCode: STATUS_INTERNALERR,
Headers: make(map[string]string),
Format: DataFormat{
Format: DF_TEXT,
Encoding: E_UTF8,
},
Payload: []byte(err.Error()),
}
}
func NewJsonResponse(data any) (*Response, error) {
jsonBytes, err := json.Marshal(data)
if err != nil {
return nil, err
}
return &Response{
StatusCode: STATUS_SUCCESS,
Headers: make(map[string]string),
Format: DataFormat{
Format: DF_JSON,
Encoding: E_UTF8,
},
Payload: jsonBytes,
}, nil
}
func (res *Response) ToPacket() *Packet {
headers := make(map[string]string)
maps.Copy(headers, res.Headers)
if res.Format.Format == DF_BYTES {
headers[H_DATA_FORMAT] = DF_BYTES
} else {
headers[H_DATA_FORMAT] = fmt.Sprintf("%s:%s", res.Format.Format, res.Format.Encoding)
}
headers[H_STATUS] = strconv.Itoa(res.StatusCode)
return BuildPacket(headers, res.Payload)
}
func (res *Response) AddHeader(key, value string) {
if _, ok := res.Headers[key]; ok {
log.Printf("WARN: Rewriting already existing header: '%s'\n", key)
}
res.Headers[key] = value
}
func (res *Response) Write(p []byte) (int, error) {
buf := new(bytes.Buffer)
n, err := buf.Write(p)
if err != nil {
return n, err
}
res.Payload = buf.Bytes()
return n, err
}