167 lines
3.9 KiB
Go
167 lines
3.9 KiB
Go
|
// Copyright © 2023 Roberto Hidalgo <event-gateway@un.rob.mx>
|
||
|
// SPDX-License-Identifier: Apache-2.0
|
||
|
package http_test
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"net/http/httptest"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"git.rob.mx/nidito/event-gateway/internal/config"
|
||
|
"git.rob.mx/nidito/event-gateway/internal/payload"
|
||
|
"git.rob.mx/nidito/event-gateway/internal/sink"
|
||
|
"git.rob.mx/nidito/event-gateway/internal/sink/debug"
|
||
|
"git.rob.mx/nidito/event-gateway/internal/source/http"
|
||
|
"git.rob.mx/nidito/event-gateway/internal/source/types"
|
||
|
"github.com/sirupsen/logrus"
|
||
|
)
|
||
|
|
||
|
func TestHTTPPayload(t *testing.T) {
|
||
|
logrus.SetLevel(logrus.DebugLevel)
|
||
|
|
||
|
testCases := []struct {
|
||
|
Name string
|
||
|
Payload any
|
||
|
Expect any
|
||
|
ExpectKind payload.Kind
|
||
|
ContentType string
|
||
|
}{
|
||
|
{
|
||
|
Name: "empty-payload",
|
||
|
Payload: nil,
|
||
|
Expect: nil,
|
||
|
ExpectKind: "",
|
||
|
},
|
||
|
{
|
||
|
Name: "text-payload",
|
||
|
Payload: "sup",
|
||
|
Expect: "sup",
|
||
|
ExpectKind: payload.KindText,
|
||
|
},
|
||
|
{
|
||
|
Name: "json-payload",
|
||
|
Payload: map[string]any{"yo": "sup"},
|
||
|
ContentType: "application/json",
|
||
|
Expect: map[string]any{"yo": "sup"},
|
||
|
ExpectKind: payload.KindJSON,
|
||
|
},
|
||
|
{
|
||
|
Name: "form-urlencoded-payload",
|
||
|
Payload: "yo=sup&yo=quihubo&dude=sweet",
|
||
|
ContentType: "application/x-www-form-urlencoded",
|
||
|
Expect: map[string]any{"yo": []string{"sup", "quihubo"}, "dude": "sweet"},
|
||
|
ExpectKind: payload.KindForm,
|
||
|
},
|
||
|
{
|
||
|
Name: "form-data-payload",
|
||
|
Payload: strings.ReplaceAll(`
|
||
|
--424242
|
||
|
Content-Disposition: form-data; name="yo"
|
||
|
|
||
|
sup
|
||
|
--424242
|
||
|
Content-Disposition: form-data; name="yo"
|
||
|
|
||
|
quihubo
|
||
|
--424242
|
||
|
Content-Disposition: form-data; name="dude"
|
||
|
|
||
|
sweet
|
||
|
--424242
|
||
|
Content-Disposition: form-data; name="ignored"; filename="example.txt"
|
||
|
Content-type: text/plain
|
||
|
|
||
|
some ignored text
|
||
|
--424242--
|
||
|
`, "\n", "\r\n"),
|
||
|
ContentType: `multipart/form-data; boundary=424242`,
|
||
|
Expect: map[string]any{"yo": []string{"sup", "quihubo"}, "dude": "sweet"},
|
||
|
ExpectKind: payload.KindForm,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, tc := range testCases {
|
||
|
t.Run(tc.Name, func(t *testing.T) {
|
||
|
sink.Clear()
|
||
|
server := http.New(nil)
|
||
|
|
||
|
target := &debug.Event{}
|
||
|
l := &config.Listener{
|
||
|
ID: tc.Name,
|
||
|
Source: &config.RawSource{
|
||
|
Kind: types.HTTP,
|
||
|
Config: []byte(fmt.Sprintf(`{"path": "%s"}`, tc.Name)),
|
||
|
},
|
||
|
Event: target,
|
||
|
}
|
||
|
if err := server.Register(l); err != nil {
|
||
|
t.Fatalf("failed to register %s", tc.Name)
|
||
|
}
|
||
|
|
||
|
outbound := &bytes.Buffer{}
|
||
|
if tc.Payload != nil {
|
||
|
if tc.ContentType == "application/json" {
|
||
|
if serialized, err := json.Marshal(tc.Payload); err != nil {
|
||
|
t.Fatalf("could not serialize %s payload: %s", tc.Name, err)
|
||
|
} else {
|
||
|
outbound = bytes.NewBuffer(serialized)
|
||
|
}
|
||
|
} else {
|
||
|
outbound = bytes.NewBufferString(tc.Payload.(string))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
res := httptest.NewRecorder()
|
||
|
req := httptest.NewRequest("POST", "/-/"+tc.Name, outbound)
|
||
|
|
||
|
if tc.ContentType != "" {
|
||
|
req.Header["Content-Type"] = []string{tc.ContentType}
|
||
|
}
|
||
|
|
||
|
server.Router.ServeHTTP(res, req)
|
||
|
defer req.Body.Close()
|
||
|
|
||
|
if res.Code > 200 {
|
||
|
body, _ := io.ReadAll(res.Body)
|
||
|
logrus.Errorf("request headers: %+v", req.Header)
|
||
|
t.Fatalf("Request ended with non 200 code: %d: %s", res.Code, body)
|
||
|
}
|
||
|
|
||
|
time.Sleep(15 * time.Millisecond)
|
||
|
|
||
|
sI, err := sink.ForKind(target.Kind())
|
||
|
if err != nil {
|
||
|
t.Fatalf("could not get debug sink %s", err)
|
||
|
}
|
||
|
s := sI.(*debug.Sink)
|
||
|
if len(s.Calls) != 1 {
|
||
|
t.Fatalf("unexpected number of triggers called: %+v", s.Calls)
|
||
|
}
|
||
|
|
||
|
payload, err := payload.FromContext(s.Calls[0])
|
||
|
if err != nil {
|
||
|
t.Fatalf("Could not parse payload: %s", err)
|
||
|
}
|
||
|
|
||
|
var got any = nil
|
||
|
if tc.Expect != nil {
|
||
|
if payload == nil {
|
||
|
t.Fatalf("no payload parsed!")
|
||
|
}
|
||
|
got = payload.Value
|
||
|
}
|
||
|
|
||
|
if !reflect.DeepEqual(got, tc.Expect) {
|
||
|
t.Fatalf("%s: unexpected payload, wanted %v, got: %v", tc.Name, tc.Expect, got)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
}
|