Fix BufferedReader, updated tests

This commit is contained in:
Peter Grlica
2022-02-17 15:00:16 +01:00
parent e822ad7c06
commit c8946e5e76
5 changed files with 75 additions and 44 deletions
@@ -2,7 +2,6 @@ package automation
import (
"context"
"fmt"
"io"
)
@@ -24,11 +23,6 @@ func ApigwBodyHandler(reg queueHandlerRegistry) *apigwBodyHandler {
func (h apigwBodyHandler) read(ctx context.Context, args *apigwBodyReadArgs) (res *apigwBodyReadResults, err error) {
res = &apigwBodyReadResults{}
if !args.hasRequest {
err = fmt.Errorf("could not read body, contents missing")
return
}
bb, err := io.ReadAll(args.Request.Body)
if err != nil {
+4 -3
View File
@@ -139,16 +139,17 @@ func Test_processerPayload(t *testing.T) {
},
exp: "{\"count\":2,\"results\":[{\"fullname\":\"Johnny Mnemonic\"},{\"fullname\":\"Johnny Knoxville\"}]}\n",
params: prepareFuncPayload(t, `
const b = JSON.parse(readRequestBody(input.Get('request')));
const readOnce = JSON.parse(readRequestBody(input.Get('request')));
const readTwice = JSON.parse(readRequestBody(input.Get('request')));
return {
"results":
b.map(function({ name, surname }) {
readTwice.map(function({ name, surname }) {
return {
"fullname": name[0].toUpperCase() + name.substring(1) + " " + surname[0].toUpperCase() + surname.substring(1)
}
}),
"count": b.length
"count": readTwice.length
};
`),
},
+4
View File
@@ -676,6 +676,10 @@ func CastToHttpRequest(val interface{}) (out *h.Request, err error) {
func CastToUrl(val interface{}) (out *url.URL, err error) {
switch val := UntypedValue(val).(type) {
case []byte:
return url.Parse(string(val))
case string:
return url.Parse(val)
case *url.URL:
return val, nil
case nil:
+56 -27
View File
@@ -1,11 +1,14 @@
package http
import (
"bytes"
"encoding/json"
"io"
"mime/multipart"
"net/http"
"net/url"
"github.com/pkg/errors"
)
type (
@@ -14,24 +17,16 @@ type (
Body io.Reader
}
// The BufferedReader behaves exactly like a bytes.Reader, with the exception
// when the last block is read, it automatically rewinds the internal pointer to the start,
// so effectively, the content can be read again without calling Seek() externally.
BufferedReader struct {
buffer []byte
s []byte
i int64 // current reading index
prevRune int // index of previous rune; or < 0
}
)
// NewBufferedReader creates a new reader from readcloser
func NewBufferedReader(r io.ReadCloser) (b *BufferedReader, err error) {
var bb []byte
if bb, err = io.ReadAll(r); err != nil {
return
}
b = &BufferedReader{bb}
return
}
// NewRequest creates a new Request with the buffered ready body
func NewRequest(r *http.Request) (rr *Request, err error) {
rs, err := NewBufferedReader(r.Body)
@@ -43,27 +38,61 @@ func NewRequest(r *http.Request) (rr *Request, err error) {
return
}
func (bb *BufferedReader) Read(p []byte) (n int, err error) {
if len(bb.buffer) <= n {
err = io.EOF
// NewBufferedReader copies original data to the
// BufferedReader
func NewBufferedReader(rr io.Reader) (bb *BufferedReader, err error) {
var (
buf = &bytes.Buffer{}
)
bb = &BufferedReader{}
_, err = io.Copy(buf, rr)
if err != nil {
return
}
if c := cap(p); c > 0 {
for n < c {
if len(bb.buffer) <= n {
err = io.EOF
break
}
return &BufferedReader{
s: buf.Bytes(),
i: 0,
prevRune: -1,
}, nil
}
p[n] = bb.buffer[n]
n++
}
func (r *BufferedReader) Read(b []byte) (n int, err error) {
if r.i >= int64(len(r.s)) {
n = 0
err = io.EOF
r.Seek(0, io.SeekStart)
return
}
r.prevRune = -1
n = copy(b, r.s[r.i:])
r.i += int64(n)
return
}
func (r *BufferedReader) Seek(offset int64, whence int) (int64, error) {
r.prevRune = -1
var abs int64
switch whence {
case io.SeekStart:
abs = offset
case io.SeekCurrent:
abs = r.i + offset
case io.SeekEnd:
abs = int64(len(r.s)) + offset
default:
return 0, errors.New("bytes.Reader.Seek: invalid whence")
}
if abs < 0 {
return 0, errors.New("bytes.Reader.Seek: negative position")
}
r.i = abs
return abs, nil
}
func (bb *Request) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Method string
+11 -8
View File
@@ -10,25 +10,28 @@ import (
)
func Test_requestReadMultiple(t *testing.T) {
var req = require.New(t)
r, _ := h.NewRequest("POST", "/foo", strings.NewReader(`foo body`))
var (
req = require.New(t)
tt = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi placerat suscipit finibus. Morbi luctus et lorem sed euismod. Donec bibendum lorem non justo pretium, a sagittis augue mollis. In varius libero id purus convallis pretium. Vestibulum ac mauris aliquet, pulvinar massa eu, rhoncus ipsum. Cras sit amet euismod metus, in tincidunt sapien. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Sed scelerisque vulputate imperdiet. Nulla orci magna, fringilla sit amet tempor vel, tempus pulvinar urna.`
)
rs, err := NewBufferedReader(r.Body)
r, _ := h.NewRequest("POST", "/foo", strings.NewReader(tt))
rs, err := NewRequest(r)
req.NoError(err)
req.Equal(`foo body`, must(io.ReadAll(rs)))
req.Equal(`foo body`, must(io.ReadAll(rs)))
req.Equal(tt, must(io.ReadAll(rs.Body)))
req.Equal(tt, must(io.ReadAll(rs.Body)))
}
func Test_requestReadMultipleNoBody(t *testing.T) {
var req = require.New(t)
r, _ := h.NewRequest("POST", "/foo", h.NoBody)
rs, err := NewBufferedReader(r.Body)
rs, err := NewRequest(r)
req.NoError(err)
req.Equal(``, must(io.ReadAll(rs)))
req.Equal(``, must(io.ReadAll(rs)))
req.Equal(``, must(io.ReadAll(rs.Body)))
req.Equal(``, must(io.ReadAll(rs.Body)))
}
func must(b []byte, e error) string {