Fix BufferedReader, updated tests
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
};
|
||||
`),
|
||||
},
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user