You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
3.1 KiB

package nwweb
import (
"bytes"
"encoding/json"
"errors"
"git.nwestland.com/tools/nwjson"
"io"
)
var (
ErrCannotRead = errors.New("cannot read from body")
ErrCannotWrite = errors.New("cannot write to body")
ErrCannotConvertToBuffer = errors.New("cannot convert body to buffer")
)
type body struct {
parent any
readerWriter any
}
func newBody(parent any, readerWriter any) body {
return body{
parent: parent,
readerWriter: readerWriter,
}
}
func (b body) Read(p []byte) (int, error) {
if reader, ok := b.readerWriter.(io.Reader); ok {
return reader.Read(p)
}
return 0, ErrCannotRead
}
func (b body) Bytes() []byte {
if reader, ok := b.readerWriter.(io.Reader); ok {
data, _ := io.ReadAll(reader)
b.Close()
return data
}
return nil
}
func (b body) String() string {
return string(b.Bytes())
}
func (b body) Object() nwjson.Object {
if reader, ok := b.readerWriter.(io.Reader); ok {
return nwjson.ObjectFromStream(reader)
}
return nil
}
func (b body) Array() nwjson.Array {
if reader, ok := b.readerWriter.(io.Reader); ok {
return nwjson.ArrayFromStream(reader)
}
return nil
}
func (b body) UnmarshalJson(any any) error {
if reader, ok := b.readerWriter.(io.Reader); ok {
jd := json.NewDecoder(reader)
err := jd.Decode(&any)
b.Close()
return err
}
return ErrCannotRead
}
func (b body) Write(p []byte) (int, error) {
if writer, ok := b.readerWriter.(io.Writer); ok {
return writer.Write(p)
}
return 0, ErrCannotWrite
}
func (b body) WriteString(s string) (int, error) {
if writer, ok := b.readerWriter.(io.Writer); ok {
return writer.Write([]byte(s))
}
return 0, ErrCannotWrite
}
func (b body) WriteJsonError(errText string, statusCode int) error {
if response, ok := b.parent.(*Response); ok {
defer response.SetStatusCode(statusCode)
return b.MarshalJson(map[string]string{"Error": errText})
}
return ErrCannotWrite
}
func (b body) MarshalJson(any any) error {
switch b.parent.(type) {
case *Request:
b.parent.(*Request).Headers.SetContentType("application/json")
case *Response:
b.parent.(*Response).Headers.SetContentType("application/json")
}
if writer, ok := b.readerWriter.(io.Writer); ok {
je := json.NewEncoder(writer)
return je.Encode(any)
}
return ErrCannotWrite
}
func (b *body) Buffer() (*bytes.Buffer, error) {
switch b.readerWriter.(type) {
case *bytes.Buffer:
return b.readerWriter.(*bytes.Buffer), nil
case io.Reader:
buf := new(bytes.Buffer)
buf.ReadFrom(b.readerWriter.(io.Reader))
b.Close()
b.readerWriter = buf
return buf, nil
default:
return nil, ErrCannotConvertToBuffer
}
}
//TODO check if this is a good solution
func (b *body) Len() int {
var contentLength int
switch b.parent.(type) {
case *Request:
contentLength = b.parent.(*Request).Headers.ContentLength()
case *Response:
contentLength = b.parent.(*Response).Headers.ContentLength()
}
if contentLength == 0 {
if buf, err := b.Buffer(); err == nil {
return buf.Len()
}
}
return contentLength
}
func (b body) Close() error {
if readCloser, ok := b.readerWriter.(io.ReadCloser); ok {
return readCloser.Close()
}
return nil
}