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
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
|
|
}
|