diff --git a/v2/client/service_test.go b/v2/client/service_test.go
index 85843f5..6e80a7d 100644
--- a/v2/client/service_test.go
+++ b/v2/client/service_test.go
@@ -1361,12 +1361,12 @@ var _ = Describe("ConnectionController", func() {
mockServer *httptest.Server
//mockToken string
mockRequest InvokeConnectionRequest
- mockResponse map[string]interface{}
+ //mockResponse map[string]interface{}
)
BeforeEach(func() {
//mockToken = "mock-valid-token"
- mockResponse = map[string]interface{}{"key": "value"}
+ //mockResponse = map[string]interface{}{"key": "value"}
mockRequest = InvokeConnectionRequest{
Headers: map[string]string{
"Content-Type": "application/json",
@@ -1405,7 +1405,7 @@ var _ = Describe("ConnectionController", func() {
service, err := client.Connection("failed")
response, err := service.Invoke(ctx, mockRequest)
Expect(err).To(BeNil())
- Expect(response.Data).To(Equal(mockResponse))
+ Expect(response.Data).To(Equal(fmt.Sprintf("%v", `{"key": "value"}`)))
})
})
Context("Handling query parameters", func() {
diff --git a/v2/internal/validation/validations.go b/v2/internal/validation/validations.go
index 5de8ac8..96269db 100644
--- a/v2/internal/validation/validations.go
+++ b/v2/internal/validation/validations.go
@@ -645,9 +645,12 @@ func ValidateInvokeConnectionRequest(request common.InvokeConnectionRequest) *sk
}
// Validate body
if request.Body != nil {
- if len(request.Body) == 0 {
- logger.Error(fmt.Sprintf(logs.EMPTY_REQUEST_BODY, constants.REQUEST_INVOKE_CONNECTION))
- return skyflowError.NewSkyflowError(skyflowError.INVALID_INPUT_CODE, skyflowError.EMPTY_REQUEST_BODY)
+ // Check if body is a map and if it's empty
+ if bodyMap, ok := request.Body.(map[string]interface{}); ok {
+ if len(bodyMap) == 0 {
+ logger.Error(fmt.Sprintf(logs.EMPTY_REQUEST_BODY, constants.REQUEST_INVOKE_CONNECTION))
+ return skyflowError.NewSkyflowError(skyflowError.INVALID_INPUT_CODE, skyflowError.EMPTY_REQUEST_BODY)
+ }
}
}
if request.Method != "" {
diff --git a/v2/internal/vault/controller/connection_controller.go b/v2/internal/vault/controller/connection_controller.go
index 1f9c2d1..552b8f7 100644
--- a/v2/internal/vault/controller/connection_controller.go
+++ b/v2/internal/vault/controller/connection_controller.go
@@ -6,9 +6,9 @@ import (
"encoding/json"
"fmt"
"io"
- "io/ioutil"
"mime/multipart"
"net/http"
+ "net/url"
"os"
"reflect"
"strconv"
@@ -22,7 +22,10 @@ import (
"github.com/skyflowapi/skyflow-go/v2/utils/logger"
logs "github.com/skyflowapi/skyflow-go/v2/utils/messages"
- "github.com/hetiansu5/urlquery"
+)
+
+const (
+ formatValue = "%v"
)
type ConnectionController struct {
@@ -119,6 +122,11 @@ func (v *ConnectionController) Invoke(ctx context.Context, request common.Invoke
logger.Error(logs.INVOKE_CONNECTION_REQUEST_REJECTED)
return nil, errors.NewSkyflowError(errors.INVALID_INPUT_CODE, fmt.Sprintf(errors.UNKNOWN_ERROR, invokeErr.Error()))
}
+ // Ensure response body is closed to prevent resource leaks
+ if res.Body != nil {
+ defer res.Body.Close()
+ }
+
metaData := map[string]interface{}{
constants.REQUEST_ID_KEY: requestId,
}
@@ -126,11 +134,58 @@ func (v *ConnectionController) Invoke(ctx context.Context, request common.Invoke
logger.Info(logs.INVOKE_CONNECTION_REQUEST_RESOLVED)
// Step 7: Parse Response
if res.StatusCode >= http.StatusOK && res.StatusCode < http.StatusMultipleChoices {
- parseRes, parseErr := parseResponse(res)
- if parseErr != nil {
- return nil, parseErr
+ response := common.InvokeConnectionResponse{Metadata: metaData}
+ if res.Body != nil {
+ contentType := res.Header.Get("Content-Type")
+ data, err := io.ReadAll(res.Body)
+ if err != nil {
+ return nil, errors.NewSkyflowError(errors.INVALID_INPUT_CODE, errors.INVALID_RESPONSE)
+ }
+ if strings.Contains(contentType, string(common.APPLICATIONXML)) || strings.Contains(contentType, string(common.TEXTORXML)) {
+ response.Data = string(data)
+ return &response, nil
+ } else if strings.Contains(contentType, string(common.APPLICATIONORJSON)) || contentType == "" {
+ var jsonData interface{}
+ err = json.Unmarshal(data, &jsonData)
+ if err != nil {
+ response.Data = data
+ return &response, nil
+ } else {
+ response.Data = jsonData
+ return &response, nil
+ }
+
+ } else if strings.Contains(contentType, string(common.TEXTORPLAIN)) {
+ response.Data = string(data)
+ return &response, nil
+ } else if strings.Contains(contentType, string(common.FORMURLENCODED)) {
+ // Parse URL-encoded form data
+ values, err := url.ParseQuery(string(data))
+ if err != nil {
+ return nil, errors.NewSkyflowError(errors.INVALID_INPUT_CODE, errors.INVALID_RESPONSE)
+ }
+ // Convert url.Values to map[string]interface{}
+ result := make(map[string]interface{})
+ for key, val := range values {
+ if len(val) == 1 {
+ result[key] = val[0]
+ } else {
+ result[key] = val
+ }
+ }
+ response.Data = result
+ return &response, nil
+ } else if strings.Contains(contentType, string(common.FORMDATA)) {
+ response.Data = string(data)
+ } else if strings.Contains(contentType, string(common.TEXTHTML)) {
+ response.Data = string(data)
+ return &response, nil
+ } else {
+ response.Data = string(data)
+ return &response, nil
+ }
}
- return &common.InvokeConnectionResponse{Data: parseRes, Metadata: metaData}, nil
+ return &response, nil
}
return nil, errors.SkyflowApiError(*res)
}
@@ -145,44 +200,185 @@ func buildRequestURL(baseURL string, pathParams map[string]string) string {
func prepareRequest(request common.InvokeConnectionRequest, url string) (*http.Request, error) {
var body io.Reader
var writer *multipart.Writer
- contentType := detectContentType(request.Headers)
+ var contentType string
+ shouldSetContentType := true
+
+ contentType = detectContentType(request.Headers)
+
+ // If no content-type and body is an object, default to JSON
+ if contentType == string(common.APPLICATIONORJSON) && request.Body != nil {
+ if _, ok := request.Body.(map[string]interface{}); ok {
+ contentType = string(common.APPLICATIONORJSON)
+ }
+ }
+
+ switch contentType {
+ case string(common.APPLICATIONORJSON):
+ if strBody, ok := request.Body.(string); ok {
+ body = strings.NewReader(strBody)
+ } else if bodyMap, ok := request.Body.(map[string]interface{}); ok {
+ data, err := json.Marshal(bodyMap)
+ if err != nil {
+ return nil, err
+ }
+ body = strings.NewReader(string(data))
+ } else if request.Body != nil {
+ if strBody, ok := request.Body.(string); ok {
+ body = strings.NewReader(strBody)
+ } else {
+ body = strings.NewReader(fmt.Sprintf(formatValue, request.Body))
+ }
+ }
- switch contentType {
case string(common.FORMURLENCODED):
- data, err := urlquery.Marshal(request.Body)
- if err != nil {
- return nil, err
+ if bodyMap, ok := request.Body.(map[string]interface{}); ok {
+ urlParams := buildURLEncodedParams(bodyMap)
+ body = strings.NewReader(urlParams.Encode())
+ } else { //need to check here
+ body = strings.NewReader("")
}
- body = strings.NewReader(string(data))
case string(common.FORMDATA):
buffer := new(bytes.Buffer)
writer = multipart.NewWriter(buffer)
- if err := writeFormData(writer, request.Body); err != nil {
- return nil, err
+
+ if bodyMap, ok := request.Body.(map[string]interface{}); ok {
+ for key, value := range bodyMap {
+ if value == nil {
+ continue
+ }
+
+ // Check if value is *os.File or io.Reader for file uploads
+ if file, ok := value.(*os.File); ok {
+ // Handle *os.File - create form file
+ part, err := writer.CreateFormFile(key, file.Name())
+ if err != nil {
+ return nil, err
+ }
+ if _, err := io.Copy(part, file); err != nil {
+ return nil, err
+ }
+ } else if reader, ok := value.(io.Reader); ok {
+ // Handle io.Reader - create form file with generic name
+ part, err := writer.CreateFormFile(key, key)
+ if err != nil {
+ return nil, err
+ }
+ if _, err := io.Copy(part, reader); err != nil {
+ return nil, err
+ }
+ } else if nestedMap, ok := value.(map[string]interface{}); ok {
+ // Check if value is a map/object - stringify it as JSON
+ jsonData, err := json.Marshal(nestedMap)
+ if err != nil {
+ return nil, err
+ }
+ if err := writer.WriteField(key, string(jsonData)); err != nil {
+ return nil, err
+ }
+ } else if arr, ok := value.([]interface{}); ok {
+ // Handle arrays - stringify as JSON
+ jsonData, err := json.Marshal(arr)
+ if err != nil {
+ return nil, err
+ }
+ if err := writer.WriteField(key, string(jsonData)); err != nil {
+ return nil, err
+ }
+ } else {
+ // Handle primitive values - convert to string
+ if err := writer.WriteField(key, fmt.Sprintf(formatValue, value)); err != nil {
+ return nil, err
+ }
+ }
+ }
+ } else if strBody, ok := request.Body.(string); ok {
+ // If body is already a string, use it as-is (though this is unusual for multipart)
+ body = strings.NewReader(strBody)
+ writer = nil // Don't use multipart writer for string body
+ shouldSetContentType = false // Keep user's content-type
+ } else if request.Body != nil {
+ // For other types, convert to string
+ body = strings.NewReader(fmt.Sprintf(formatValue, request.Body))
+ writer = nil
+ shouldSetContentType = false
+ }
+
+ if writer != nil {
+ writer.Close()
+ body = buffer
+ contentType = writer.FormDataContentType() // set with boundary
+ shouldSetContentType = true // Force set with boundary
}
- writer.Close()
- body = buffer
+ case string(common.APPLICATIONXML), string(common.TEXTORXML):
+ if strBody, ok := request.Body.(string); ok {
+ // Body is already a string (raw XML)
+ body = strings.NewReader(strBody)
+ } else if bodyMap, ok := request.Body.(map[string]interface{}); ok {
+ // Convert map to XML
+ data, err := mapToXML(bodyMap)
+ if err != nil {
+ return nil, err
+ }
+ body = bytes.NewReader(data)
+ } else {
+ // throw error for unsupported body type
+ return nil, errors.NewSkyflowError(errors.INVALID_INPUT_CODE, errors.INVALID_XML_FORMAT)
+ }
+
+ case string(common.TEXTORPLAIN):
+ if strBody, ok := request.Body.(string); ok {
+ body = strings.NewReader(strBody)
+ } else if request.Body != nil {
+ body = strings.NewReader(fmt.Sprintf(formatValue, request.Body))
+ }
+ case string(common.TEXTHTML):
+ if strBody, ok := request.Body.(string); ok {
+ body = strings.NewReader(strBody)
+ } else if bodyMap, ok := request.Body.(map[string]interface{}); ok {
+ // send map as json in body
+ data, err := json.Marshal(bodyMap)
+ if err != nil {
+ return nil, err
+ }
+ body = strings.NewReader(string(data))
+ } else if request.Body != nil {
+ body = strings.NewReader(fmt.Sprintf(formatValue, request.Body))
+ }
+
default:
- data, err := json.Marshal(request.Body)
- if err != nil {
- return nil, err
+ if strBody, ok := request.Body.(string); ok {
+ body = strings.NewReader(strBody)
+ } else if request.Body != nil {
+ if bodyMap, ok := request.Body.(map[string]interface{}); ok {
+ data, err := json.Marshal(bodyMap)
+ if err != nil {
+ return nil, err
+ }
+ body = strings.NewReader(string(data))
+ } else {
+ body = strings.NewReader(fmt.Sprintf(formatValue, request.Body))
+ }
}
- body = strings.NewReader(string(data))
}
if request.Method == "" {
request.Method = common.POST
}
request1, err := http.NewRequest(string(request.Method), url, body)
- if err == nil && writer != nil {
- request1.Header.Set(constants.HEADER_CONTENT_TYPE, writer.FormDataContentType())
+ if err != nil {
+ return nil, err
+ }
+
+ // Set content-type header
+ if shouldSetContentType && contentType != "" {
+ request1.Header.Set("content-type", contentType)
}
- return request1, err
+ return request1, nil
}
func writeFormData(writer *multipart.Writer, requestBody interface{}) error {
- formData := rUrlencode(make([]interface{}, 0), make(map[string]string), requestBody)
+ formData := RUrlencode(make([]interface{}, 0), make(map[string]string), requestBody)
for key, value := range formData {
if err := writer.WriteField(key, value); err != nil {
return err
@@ -190,7 +386,37 @@ func writeFormData(writer *multipart.Writer, requestBody interface{}) error {
}
return nil
}
-func rUrlencode(parents []interface{}, pairs map[string]string, data interface{}) map[string]string {
+
+// buildURLEncodedParams converts a map to URL encoded params matching Node.js URLSearchParams behavior
+func buildURLEncodedParams(data map[string]interface{}) *url.Values {
+ params := url.Values{}
+
+ for key, value := range data {
+ if value == nil {
+ continue
+ }
+
+ // Check if value is a map (nested object)
+ if nestedMap, ok := value.(map[string]interface{}); ok {
+ for nestedKey, nestedValue := range nestedMap {
+ paramKey := fmt.Sprintf("%s[%s]", key, nestedKey)
+ params.Add(paramKey, fmt.Sprintf(formatValue, nestedValue))
+ }
+ } else if arr, ok := value.([]interface{}); ok {
+ // Handle arrays
+ for _, item := range arr {
+ params.Add(key, fmt.Sprintf(formatValue, item))
+ }
+ } else {
+ // Handle primitive values
+ params.Add(key, fmt.Sprintf(formatValue, value))
+ }
+ }
+
+ return ¶ms
+}
+
+func RUrlencode(parents []interface{}, pairs map[string]string, data interface{}) map[string]string {
switch reflect.TypeOf(data).Kind() {
case reflect.Int:
@@ -205,7 +431,7 @@ func rUrlencode(parents []interface{}, pairs map[string]string, data interface{}
var mapOfdata = (data).(map[string]interface{})
for index, value := range mapOfdata {
parents = append(parents, index)
- rUrlencode(parents, pairs, value)
+ RUrlencode(parents, pairs, value)
parents = parents[:len(parents)-1]
}
default:
@@ -219,7 +445,7 @@ func renderKey(parents []interface{}) string {
for index := range parents {
var typeOfindex = reflect.TypeOf(parents[index]).Kind()
if depth > 0 || typeOfindex == reflect.Int {
- outputString = outputString + fmt.Sprintf("[%v]", parents[index])
+ outputString = outputString + fmt.Sprintf("["+formatValue+"]", parents[index])
} else {
outputString = outputString + (parents[index]).(string)
}
@@ -260,9 +486,17 @@ func setHeaders(request *http.Request, api ConnectionController, invokeRequest c
} else {
request.Header.Set(constants.HEADER_AUTHORIZATION, api.Token)
}
- request.Header.Set(constants.HEADER_CONTENT_TYPE, constants.CONTENT_TYPE_JSON)
+
+ // Only set default content-type if not already set (preserve multipart boundary)
+ if request.Header.Get(constants.HEADER_CONTENT_TYPE) == "" {
+ request.Header.Set(constants.HEADER_CONTENT_TYPE, constants.CONTENT_TYPE_JSON)
+ }
for key, value := range invokeRequest.Headers {
+ // Skip content-type from user headers to preserve the one set in prepareRequest (especially multipart boundaries)
+ if strings.ToLower(key) == constants.HEADER_CONTENT_TYPE {
+ continue
+ }
request.Header.Set(key, value)
}
}
@@ -277,14 +511,52 @@ func sendRequest(request *http.Request) (*http.Response, string, error) {
}
return response, requestId, nil
}
-func parseResponse(response *http.Response) (map[string]interface{}, *errors.SkyflowError) {
- data, err := ioutil.ReadAll(response.Body)
- if err != nil {
- return nil, errors.NewSkyflowError(errors.INVALID_INPUT_CODE, errors.INVALID_RESPONSE)
+
+// mapToXML converts a map[string]interface{} to XML format
+func mapToXML(data map[string]interface{}) ([]byte, error) {
+ var buf bytes.Buffer
+ buf.WriteString("")
+ buf.WriteString("")
+
+ for key, value := range data {
+ writeXMLElement(&buf, key, value)
}
- var result map[string]interface{}
- if err1 := json.Unmarshal(data, &result); err1 != nil {
- return nil, errors.NewSkyflowError(errors.INVALID_INPUT_CODE, errors.INVALID_RESPONSE)
+
+ buf.WriteString("")
+ return buf.Bytes(), nil
+}
+
+// writeXMLElement recursively writes XML elements with proper escaping
+func writeXMLElement(buf *bytes.Buffer, key string, value interface{}) {
+ if value == nil {
+ buf.WriteString(fmt.Sprintf("<%s/>", key))
+ return
}
- return result, nil
+
+ switch v := value.(type) {
+ case map[string]interface{}:
+ buf.WriteString(fmt.Sprintf("<%s>", key))
+ for k, val := range v {
+ writeXMLElement(buf, k, val)
+ }
+ buf.WriteString(fmt.Sprintf("%s>", key))
+ case []interface{}:
+ for _, item := range v {
+ writeXMLElement(buf, key, item)
+ }
+ default:
+ // Escape special XML characters
+ escapedValue := escapeXML(fmt.Sprintf(formatValue, v))
+ buf.WriteString(fmt.Sprintf("<%s>%s%s>", key, escapedValue, key))
+ }
+}
+
+// escapeXML escapes special XML characters
+func escapeXML(s string) string {
+ s = strings.ReplaceAll(s, "&", "&")
+ s = strings.ReplaceAll(s, "<", "<")
+ s = strings.ReplaceAll(s, ">", ">")
+ s = strings.ReplaceAll(s, "\"", """)
+ s = strings.ReplaceAll(s, "'", "'")
+ return s
}
diff --git a/v2/internal/vault/controller/controller_test.go b/v2/internal/vault/controller/controller_test.go
index 1f3bae3..f526929 100644
--- a/v2/internal/vault/controller/controller_test.go
+++ b/v2/internal/vault/controller/controller_test.go
@@ -1,13 +1,18 @@
package controller_test
import (
+ // "bytes"
"context"
"encoding/json"
+ "errors"
"fmt"
+ // "io"
+ // "mime/multipart"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
+ "strings"
"testing"
"github.com/skyflowapi/skyflow-go/v2/internal/generated/option"
@@ -22,6 +27,13 @@ import (
skyflowError "github.com/skyflowapi/skyflow-go/v2/utils/error"
)
+// errorReader is a custom io.Reader that always returns an error
+type errorReader struct{}
+
+func (e *errorReader) Read(p []byte) (n int, err error) {
+ return 0, errors.New("simulated read error")
+}
+
var (
mockInsertSuccessJSON = `{"vaultID":"id", "responses":[{"Body":{"records":[{"skyflow_id":"skyflowid", "tokens":{"name_on_card":"token1"}}]}, "Status":200}]}`
mockInsertContinueFalseSuccessJSON = `{"records":[{"skyflow_id":"skyflowid1", "tokens":{"name":"nameToken1"}}, {"skyflow_id":"skyflowid2", "tokens":{"expiry_month":"monthToken", "name":"nameToken3"}}]}`
@@ -1178,6 +1190,7 @@ var _ = Describe("ConnectionController", func() {
Context("when making a valid request", func() {
BeforeEach(func() {
mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"key": "value"}`))
}))
@@ -1240,6 +1253,7 @@ var _ = Describe("ConnectionController", func() {
})
It("should return an success from api with invalid body", func() {
mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Length", "0")
_, _ = w.Write([]byte(`67676`))
@@ -1249,13 +1263,15 @@ var _ = Describe("ConnectionController", func() {
return nil
}
response, err := ctrl.Invoke(ctx, mockRequest)
- Expect(response).To(BeNil())
- Expect(err).ToNot(BeNil())
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ Expect(response.Data).To(Equal(float64(67676)))
})
})
Context("Invoke with different content types", func() {
BeforeEach(func() {
mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"key": "value"}`))
}))
@@ -1432,7 +1448,1989 @@ var _ = Describe("ConnectionController", func() {
})
})
- })
+ Context("Handling XML content types", func() {
+ BeforeEach(func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/xml")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`value`))
+ }))
+ ctrl.Config.ConnectionUrl = mockServer.URL
+ })
+
+ AfterEach(func() {
+ mockServer.Close()
+ })
+
+ It("should handle application/xml content type with map body", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/xml",
+ },
+ Body: map[string]interface{}{
+ "key": "value",
+ "nested": map[string]interface{}{
+ "inner": "data",
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ Expect(response.Data).To(ContainSubstring("value"))
+ })
+
+ It("should handle text/xml content type", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "text/xml",
+ },
+ Body: map[string]interface{}{
+ "user": "john",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle XML with special characters requiring escaping", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/xml",
+ },
+ Body: map[string]interface{}{
+ "key": "value with & \"characters\" 'here'",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle XML with string body", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/xml",
+ },
+ Body: "- test
",
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle XML with arrays", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/xml",
+ },
+ Body: map[string]interface{}{
+ "items": []interface{}{"item1", "item2", "item3"},
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+ })
+
+ Context("Handling URL-encoded content with nested objects", func() {
+ BeforeEach(func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`key=value&nested=data`))
+ }))
+ ctrl.Config.ConnectionUrl = mockServer.URL
+ })
+
+ AfterEach(func() {
+ mockServer.Close()
+ })
+
+ It("should handle nested objects in URL-encoded format", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ Body: map[string]interface{}{
+ "user": map[string]interface{}{
+ "name": "john",
+ "age": 30,
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle arrays in URL-encoded format", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ Body: map[string]interface{}{
+ "tags": []interface{}{"tag1", "tag2", "tag3"},
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle mixed nested objects and arrays", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ Body: map[string]interface{}{
+ "user": map[string]interface{}{
+ "name": "john",
+ },
+ "tags": []interface{}{"tag1", "tag2"},
+ "key": "value",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+ })
+
+ Context("Handling multipart/form-data with file uploads", func() {
+ BeforeEach(func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"success": true}`))
+ }))
+ ctrl.Config.ConnectionUrl = mockServer.URL
+ })
+
+ AfterEach(func() {
+ mockServer.Close()
+ })
+
+ It("should handle multipart/form-data with *os.File", func() {
+ // Create a temporary file for testing
+ tmpFile, err := os.CreateTemp("", "test-*.txt")
+ Expect(err).To(BeNil())
+ defer os.Remove(tmpFile.Name())
+ _, _ = tmpFile.WriteString("test file content")
+ tmpFile.Close()
+
+ // Reopen for reading
+ file, err := os.Open(tmpFile.Name())
+ Expect(err).To(BeNil())
+ defer file.Close()
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "file": file,
+ "key": "value",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with io.Reader", func() {
+ reader := strings.NewReader("test content from reader")
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "upload": reader,
+ "name": "test",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with nested maps (JSON stringified)", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "user": map[string]interface{}{
+ "name": "john",
+ "age": 30,
+ },
+ "simple": "value",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with arrays (JSON stringified)", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "tags": []interface{}{"tag1", "tag2", "tag3"},
+ "key": "value",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+ })
+
+ Context("Handling text/plain and text/html content types", func() {
+ BeforeEach(func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ contentType := r.Header.Get("Content-Type")
+ w.Header().Set("Content-Type", contentType)
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte("plain text response"))
+ }))
+ ctrl.Config.ConnectionUrl = mockServer.URL
+ })
+
+ AfterEach(func() {
+ mockServer.Close()
+ })
+
+ It("should handle text/plain content type", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "text/plain",
+ },
+ Body: "This is plain text content",
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ Expect(response.Data).To(Equal("plain text response"))
+ })
+
+ It("should handle text/html content type", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "text/html",
+ },
+ Body: "Hello",
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle text/html with map body (converted to JSON)", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "text/html",
+ },
+ Body: map[string]interface{}{
+ "key": "value",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+ })
+
+ Context("Handling response parsing for different content types", func() {
+ It("should parse XML response correctly", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/xml")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`value`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "GET",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ Expect(response.Data).To(ContainSubstring("value"))
+ })
+
+ It("should parse URL-encoded response correctly", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`key1=value1&key2=value2&key3=value3a&key3=value3b`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "GET",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ // Response should be a map
+ dataMap, ok := response.Data.(map[string]interface{})
+ Expect(ok).To(BeTrue())
+ Expect(dataMap).To(HaveKey("key1"))
+ Expect(dataMap["key1"]).To(Equal("value1"))
+ // key3 should be an array since it has multiple values
+ Expect(dataMap).To(HaveKey("key3"))
+ })
+
+ It("should parse JSON response correctly", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"key": "value", "number": 42}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "GET",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ dataMap, ok := response.Data.(map[string]interface{})
+ Expect(ok).To(BeTrue())
+ Expect(dataMap["key"]).To(Equal("value"))
+ Expect(dataMap["number"]).To(Equal(float64(42)))
+ })
+
+ It("should parse text/plain response correctly", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/plain")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte("Simple plain text"))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "GET",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ Expect(response.Data).To(Equal("Simple plain text"))
+ })
+
+ It("should handle invalid JSON response gracefully", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`invalid json content`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "GET",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ // Should return as bytes when JSON parsing fails
+ Expect(response.Data).To(Equal([]byte("invalid json content")))
+ })
+
+ It("should handle invalid URL-encoded response gracefully", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`%invalid%`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "GET",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(response).To(BeNil())
+ Expect(err).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data response correctly", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "multipart/form-data")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`boundary data`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "GET",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ Expect(response.Data).To(Equal("boundary data"))
+ })
+
+ It("should handle URL-encoded response with multiple values for same key", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`color=red&color=blue&color=green`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "GET",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ dataMap, ok := response.Data.(map[string]interface{})
+ Expect(ok).To(BeTrue())
+ colors, ok := dataMap["color"].([]string)
+ Expect(ok).To(BeTrue())
+ Expect(len(colors)).To(Equal(3))
+ })
+
+ It("should handle multipart/form-data body as string", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: "raw string body",
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data body as non-map type", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: 12345,
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle text/plain body as non-string", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "text/plain",
+ },
+ Body: 98765,
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle text/html body as non-string", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "text/html",
+ },
+ Body: 54321,
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle unknown content-type with non-map body", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/octet-stream",
+ },
+ Body: 99999,
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle empty response body", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "GET",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle JSON body as string for application/json", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ Body: `{"test": "value"}`,
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle JSON body as non-map and non-string (integer)", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ Body: 12345,
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle URL-encoded body with non-map type", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ Body: "not a map",
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle XML body with unsupported type (not string or map)", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/xml",
+ },
+ Body: 12345,
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(response).To(BeNil())
+ Expect(err).ToNot(BeNil())
+ Expect(err.GetMessage()).To(ContainSubstring("Invalid XML format"))
+ })
+
+ It("should handle default method as POST when method is empty", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ Expect(r.Method).To(Equal("POST"))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "",
+ Headers: map[string]string{
+ "Content-Type": "application/json",
+ },
+ Body: map[string]interface{}{"test": "value"},
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle text/html body as map (converted to JSON)", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "text/html",
+ },
+ Body: map[string]interface{}{"html": "Title
"},
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle default content-type with map body", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/custom",
+ },
+ Body: map[string]interface{}{"key": "value"},
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle default content-type with string body", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "application/custom",
+ },
+ Body: "string body",
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with nil value in map", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "field1": "value1",
+ "field2": nil,
+ "field3": "value3",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ // Error handling tests for multipart/form-data
+ It("should handle multipart/form-data with complex nested map containing all valid types", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "nestedMap": map[string]interface{}{
+ "key1": "value1",
+ "key2": 123,
+ "key3": true,
+ "key4": 45.67,
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with array containing all valid types", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "arrayField": []interface{}{
+ "string",
+ 123,
+ true,
+ 45.67,
+ map[string]interface{}{"nested": "map"},
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with primitive string value", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "simpleString": "test value",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with primitive int value", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "simpleInt": 42,
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with primitive bool value", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "simpleBool": true,
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with primitive float value", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "simpleFloat": 3.14159,
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with map containing unsupported types that json.Marshal handles", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ // json.Marshal can handle most basic types, so this tests the success path
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "complexMap": map[string]interface{}{
+ "nullValue": nil,
+ "emptyString": "",
+ "zero": 0,
+ "negativInt": -42,
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with empty nested map", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "emptyMap": map[string]interface{}{},
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with empty array", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "emptyArray": []interface{}{},
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with deeply nested structure", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "level1": map[string]interface{}{
+ "level2": map[string]interface{}{
+ "level3": map[string]interface{}{
+ "data": "deep value",
+ },
+ },
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with array of arrays", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "matrix": []interface{}{
+ []interface{}{1, 2, 3},
+ []interface{}{4, 5, 6},
+ []interface{}{7, 8, 9},
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with mixed file and data fields", func() {
+ tmpFile, err := os.CreateTemp("", "test-mixed-*.txt")
+ Expect(err).To(BeNil())
+ defer os.Remove(tmpFile.Name())
+ _, _ = tmpFile.WriteString("file content")
+ tmpFile.Seek(0, 0)
+
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "file": tmpFile,
+ "name": "test file",
+ "metadata": map[string]interface{}{
+ "size": 12,
+ "type": "text",
+ },
+ "tags": []interface{}{"test", "sample"},
+ "count": 42,
+ "enabled": true,
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ // Error path tests for multipart/form-data operations
+ It("should handle error when file is closed before reading in multipart/form-data", func() {
+ tmpFile, err := os.CreateTemp("", "test-closed-*.txt")
+ Expect(err).To(BeNil())
+ fileName := tmpFile.Name()
+ _, _ = tmpFile.WriteString("file content")
+ // Close the file to trigger io.Copy error
+ tmpFile.Close()
+ defer os.Remove(fileName)
+
+ // Reopen file for deletion but create request with closed file handle
+ closedFile, _ := os.Open(fileName)
+ closedFile.Close() // Close immediately to trigger error
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "file": closedFile,
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ // Should return error due to closed file
+ Expect(err).ToNot(BeNil())
+ Expect(response).To(BeNil())
+ })
+
+ It("should handle multipart/form-data with types that json.Marshal can handle", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ // Test with all JSON-compatible types in nested map
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "complexData": map[string]interface{}{
+ "string": "value",
+ "number": 42,
+ "float": 3.14,
+ "bool": true,
+ "null": nil,
+ "array": []interface{}{1, 2, 3},
+ "nested": map[string]interface{}{"key": "val"},
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with arrays containing all JSON types", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "mixedArray": []interface{}{
+ "string",
+ 123,
+ 45.67,
+ true,
+ false,
+ nil,
+ map[string]interface{}{"nested": "object"},
+ []interface{}{1, 2, 3},
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with all primitive value types", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "stringField": "text value",
+ "intField": 42,
+ "floatField": 3.14159,
+ "boolField": true,
+ "zeroField": 0,
+ "emptyString": "",
+ "negativeInt": -100,
+ "negativeFloat": -99.99,
+ "falseField": false,
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with bytes.Reader as io.Reader", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ fileContent := []byte("This is file content from bytes.Reader")
+ reader := strings.NewReader(string(fileContent))
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "fileFromReader": reader,
+ "description": "File uploaded via io.Reader",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with multiple files of different types", func() {
+ // Create temp files
+ txtFile, _ := os.CreateTemp("", "test-*.txt")
+ _, _ = txtFile.WriteString("text content")
+ txtFile.Seek(0, 0)
+ defer os.Remove(txtFile.Name())
+
+ jsonFile, _ := os.CreateTemp("", "test-*.json")
+ _, _ = jsonFile.WriteString(`{"key": "value"}`)
+ jsonFile.Seek(0, 0)
+ defer os.Remove(jsonFile.Name())
+
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "textFile": txtFile,
+ "jsonFile": jsonFile,
+ "readerFile": strings.NewReader("reader content"),
+ "metadata": map[string]interface{}{"count": 2},
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with large nested structure", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "level1": map[string]interface{}{
+ "level2a": map[string]interface{}{
+ "level3": []interface{}{
+ map[string]interface{}{"id": 1, "name": "item1"},
+ map[string]interface{}{"id": 2, "name": "item2"},
+ },
+ },
+ "level2b": []interface{}{
+ []interface{}{1, 2, 3},
+ []interface{}{4, 5, 6},
+ },
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with special characters in primitive values", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "specialChars": "value with spaces & symbols !@#$%^&*()",
+ "unicode": "Hello δΈη π",
+ "quotes": `value with "quotes" and 'apostrophes'`,
+ "newlines": "line1\nline2\nline3",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ // Error path tests for FORMDATA case
+ It("should return error when io.Reader fails during io.Copy in multipart/form-data", func() {
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "failingReader": &errorReader{},
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ // Should return error due to failing reader
+ Expect(err).ToNot(BeNil())
+ Expect(response).To(BeNil())
+ })
+
+ It("should handle multipart/form-data with channel type causing json.Marshal to work with map", func() {
+ // Note: json.Marshal will handle most types, but channels, functions, and complex types cause issues
+ // However, since we're putting them in a map[string]interface{}, Go will handle the conversion
+ // This test verifies the happy path where json.Marshal succeeds even with edge case types
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "nestedData": map[string]interface{}{
+ "validString": "test",
+ "validNumber": 123,
+ "validBool": true,
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with array containing various valid types", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "arrayData": []interface{}{
+ "string",
+ 123,
+ 45.67,
+ true,
+ map[string]interface{}{"nested": "value"},
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with all primitive types as WriteField values", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "stringPrimitive": "text",
+ "intPrimitive": 42,
+ "floatPrimitive": 3.14,
+ "boolPrimitive": true,
+ "int64Primitive": int64(9223372036854775807),
+ "int32Primitive": int32(2147483647),
+ "float32Primitive": float32(3.14159),
+ "uint8Primitive": uint8(255),
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with empty string primitive", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "emptyString": "",
+ "whitespace": " ",
+ "tab": "\t",
+ "newline": "\n",
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with zero values for all numeric types", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "zeroInt": 0,
+ "zeroFloat": 0.0,
+ "zeroInt64": int64(0),
+ "zeroFloat32": float32(0.0),
+ "falseBool": false,
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with very long string primitive", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ longString := strings.Repeat("a", 10000)
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "longString": longString,
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with nested maps at multiple levels", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "nested1": map[string]interface{}{
+ "nested2": map[string]interface{}{
+ "nested3": map[string]interface{}{
+ "nested4": map[string]interface{}{
+ "value": "deeply nested",
+ },
+ },
+ },
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with arrays containing nested arrays", func() {
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "nestedArrays": []interface{}{
+ []interface{}{
+ []interface{}{
+ []interface{}{1, 2, 3},
+ },
+ },
+ },
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+
+ It("should handle multipart/form-data with combination of files, maps, arrays, and primitives", func() {
+ tmpFile, err := os.CreateTemp("", "combo-test-*.txt")
+ Expect(err).To(BeNil())
+ defer os.Remove(tmpFile.Name())
+ _, _ = tmpFile.WriteString("combo test content")
+ tmpFile.Seek(0, 0)
+
+ mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte(`{"status": "ok"}`))
+ }))
+ defer mockServer.Close()
+ ctrl.Config.ConnectionUrl = mockServer.URL
+
+ request := InvokeConnectionRequest{
+ Method: "POST",
+ Headers: map[string]string{
+ "Content-Type": "multipart/form-data",
+ },
+ Body: map[string]interface{}{
+ "file1": tmpFile,
+ "file2": strings.NewReader("reader content"),
+ "map1": map[string]interface{}{"key": "value"},
+ "array1": []interface{}{1, 2, 3},
+ "string1": "text",
+ "int1": 42,
+ "bool1": true,
+ "float1": 3.14,
+ },
+ }
+ SetBearerTokenForConnectionControllerFunc = func(v *ConnectionController) *skyflowError.SkyflowError {
+ return nil
+ }
+ response, err := ctrl.Invoke(ctx, request)
+ Expect(err).To(BeNil())
+ Expect(response).ToNot(BeNil())
+ })
+ })
+
+})
+
+var _ = Describe("Connection Utility Functions", func() {
+ Describe("RUrlencode and renderKey", func() {
+ It("should handle int values", func() {
+ parents := make([]interface{}, 0)
+ pairs := make(map[string]string)
+ parents = append(parents, "count")
+ result := RUrlencode(parents, pairs, 42)
+ Expect(result["count"]).To(Equal("42"))
+ })
+
+ It("should handle float32 values", func() {
+ parents := make([]interface{}, 0)
+ pairs := make(map[string]string)
+ parents = append(parents, "price")
+ result := RUrlencode(parents, pairs, float32(19.99))
+ Expect(result["price"]).To(ContainSubstring("19.99"))
+ })
+
+ It("should handle float64 values", func() {
+ parents := make([]interface{}, 0)
+ pairs := make(map[string]string)
+ parents = append(parents, "amount")
+ result := RUrlencode(parents, pairs, float64(99.95))
+ Expect(result["amount"]).To(ContainSubstring("99.95"))
+ })
+
+ It("should handle bool values", func() {
+ parents := make([]interface{}, 0)
+ pairs := make(map[string]string)
+ parents = append(parents, "active")
+ result := RUrlencode(parents, pairs, true)
+ Expect(result["active"]).To(Equal("true"))
+ })
+
+ It("should handle string values", func() {
+ parents := make([]interface{}, 0)
+ pairs := make(map[string]string)
+ parents = append(parents, "name")
+ result := RUrlencode(parents, pairs, "John Doe")
+ Expect(result["name"]).To(Equal("John Doe"))
+ })
+
+ It("should handle nested map values", func() {
+ parents := make([]interface{}, 0)
+ pairs := make(map[string]string)
+ parents = append(parents, "user")
+ data := map[string]interface{}{
+ "name": "Alice",
+ "age": 30,
+ }
+ result := RUrlencode(parents, pairs, data)
+ Expect(result["user[name]"]).To(Equal("Alice"))
+ Expect(result["user[age]"]).To(Equal("30"))
+ })
+
+ It("should handle deeply nested map values", func() {
+ parents := make([]interface{}, 0)
+ pairs := make(map[string]string)
+ parents = append(parents, "user")
+ data := map[string]interface{}{
+ "profile": map[string]interface{}{
+ "firstName": "Bob",
+ "age": 25,
+ },
+ }
+ result := RUrlencode(parents, pairs, data)
+ Expect(result["user[profile][firstName]"]).To(Equal("Bob"))
+ Expect(result["user[profile][age]"]).To(Equal("25"))
+ })
+ })
+
+ // Describe("writeFormData", func() {
+ // It("should write form data with multiple types", func() {
+ // buffer := new(bytes.Buffer)
+ // writer := multipart.NewWriter(buffer)
+
+ // requestBody := map[string]interface{}{
+ // "string": "value",
+ // "number": 123,
+ // "bool": true,
+ // "nested": map[string]interface{}{
+ // "key": "nested_value",
+ // },
+ // }
+
+ // err := writeFormData(writer, requestBody)
+ // Expect(err).To(BeNil())
+ // writer.Close()
+
+ // content := buffer.String()
+ // Expect(content).To(ContainSubstring("string"))
+ // Expect(content).To(ContainSubstring("value"))
+ // Expect(content).To(ContainSubstring("number"))
+ // Expect(content).To(ContainSubstring("123"))
+ // Expect(content).To(ContainSubstring("bool"))
+ // Expect(content).To(ContainSubstring("true"))
+ // Expect(content).To(ContainSubstring("nested[key]"))
+ // Expect(content).To(ContainSubstring("nested_value"))
+ // })
+
+ // It("should handle float values in form data", func() {
+ // buffer := new(bytes.Buffer)
+ // writer := multipart.NewWriter(buffer)
+
+ // requestBody := map[string]interface{}{
+ // "price": float64(19.99),
+ // }
+
+ // err := writeFormData(writer, requestBody)
+ // Expect(err).To(BeNil())
+ // writer.Close()
+
+ // content := buffer.String()
+ // Expect(content).To(ContainSubstring("price"))
+ // Expect(content).To(ContainSubstring("19.99"))
+ // })
+ // })
+})
})
var _ = Describe("VaultController", func() {
diff --git a/v2/utils/common/common.go b/v2/utils/common/common.go
index c94d243..097dd8f 100644
--- a/v2/utils/common/common.go
+++ b/v2/utils/common/common.go
@@ -218,7 +218,7 @@ const (
)
type InvokeConnectionResponse struct {
- Data map[string]interface{}
+ Data interface{}
Metadata map[string]interface{}
Errors map[string]interface{}
}
@@ -346,7 +346,7 @@ type InvokeConnectionRequest struct {
Method RequestMethod
QueryParams map[string]interface{}
PathParams map[string]string
- Body map[string]interface{}
+ Body interface{}
Headers map[string]string
}
type ContentType string
@@ -357,6 +357,8 @@ const (
FORMURLENCODED ContentType = "application/x-www-form-urlencoded"
FORMDATA ContentType = "multipart/form-data"
TEXTORXML ContentType = "text/xml"
+ APPLICATIONXML ContentType = "application/xml"
+ TEXTHTML ContentType = "text/html"
)
type OrderByEnum string
diff --git a/v2/utils/error/message.go b/v2/utils/error/message.go
index 784b86c..e36109b 100644
--- a/v2/utils/error/message.go
+++ b/v2/utils/error/message.go
@@ -5,6 +5,7 @@ import internal "github.com/skyflowapi/skyflow-go/v2/internal/constants"
// TO DO
const (
// config
+ INVALID_XML_FORMAT string = internal.SDK_PREFIX + " Validation error. Invalid XML format. Specify a valid XML format as string."
VAULT_ID_ALREADY_IN_CONFIG_LIST string = internal.SDK_PREFIX + " Validation error. VaultId is present in an existing config. Specify a new vaultId in config."
VAULT_ID_NOT_IN_CONFIG_LIST string = internal.SDK_PREFIX + " Validation error. VaultId is missing from the config. Specify the vaultIds from configs."
CONNECTION_ID_NOT_IN_CONFIG_LIST string = internal.SDK_PREFIX + " Validation error. ConnectionId is missing from the config. Specify the connectionIds from configs."
diff --git a/v2/utils/messages/error_logs.go b/v2/utils/messages/error_logs.go
index 3244ce4..c493844 100644
--- a/v2/utils/messages/error_logs.go
+++ b/v2/utils/messages/error_logs.go
@@ -3,6 +3,7 @@ package logs
import . "github.com/skyflowapi/skyflow-go/v2/internal/constants"
const (
+ INVALID_XML_FORMAT = SDK_LOG_PREFIX + " Validation error. Invalid XML format. Specify a valid XML format as string."
CLIENT_ID_NOT_FOUND = SDK_LOG_PREFIX + "Invalid credentials. Client ID cannot be empty."
TOKEN_URI_NOT_FOUND = SDK_LOG_PREFIX + "Invalid credentials. Token URI cannot be empty."
KEY_ID_NOT_FOUND = SDK_LOG_PREFIX + "Invalid credentials. Key ID cannot be empty."
diff --git a/v2/utils/messages/info_logs.go b/v2/utils/messages/info_logs.go
index 2a67223..fb1ebfc 100644
--- a/v2/utils/messages/info_logs.go
+++ b/v2/utils/messages/info_logs.go
@@ -6,7 +6,7 @@ import (
const (
EMPTY_BEARER_TOKEN = SDK_LOG_PREFIX + "BearerToken is Empty"
- BEARER_TOKEN_EXPIRED = SDK_LOG_PREFIX + "BearerToken is expired"
+ BEARER_TOKEN_EXPIRED = SDK_LOG_PREFIX + "Bearer Token provided is either invalid or has expired."
GENERATE_BEARER_TOKEN_TRIGGERED = SDK_LOG_PREFIX + "GenerateBearerToken is triggered"
GENERATE_BEARER_TOKEN_SUCCESS = SDK_LOG_PREFIX + "BearerToken is generated"
GENERATE_SIGNED_DATA_TOKEN_SUCCESS = SDK_LOG_PREFIX + "Signed Data tokens are generated"