Skip to content

Commit

Permalink
IWF-125: Limit error size return from API (#429)
Browse files Browse the repository at this point in the history
  • Loading branch information
lwolczynski authored Sep 25, 2024
1 parent ef706ab commit c185883
Show file tree
Hide file tree
Showing 3 changed files with 837 additions and 12 deletions.
27 changes: 15 additions & 12 deletions service/interpreter/activityImpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,22 +176,25 @@ func composeHttpError(
statusCode = httpResp.StatusCode
}
errMsg := err.Error()
var trimmedResponseBody, trimmedErrMsg string
if isLocalActivity {
maxL := len(errMsg)
if maxL > 5 {
maxL = 5
}
errMsg = errMsg[:maxL] + "..."

maxL = len(responseBody)
if maxL > 50 {
maxL = 50
}
responseBody = responseBody[:maxL] + "..."
trimmedErrMsg = trimText(errMsg, 5)
trimmedResponseBody = trimText(responseBody, 50)
errType = "1st-attempt-failure"
} else {
trimmedErrMsg = trimText(errMsg, 50)
trimmedResponseBody = trimText(responseBody, 500)
}

return provider.NewApplicationError(errType,
fmt.Sprintf("statusCode: %v, responseBody: %v, errMsg: %v", statusCode, responseBody, errMsg))
fmt.Sprintf("statusCode: %v, responseBody: %v, errMsg: %v", statusCode, trimmedResponseBody, trimmedErrMsg))
}

func trimText(msg string, maxLength int) string {
if len(msg) > maxLength {
return msg[:maxLength] + "..."
}
return msg
}

func checkCommandRequestFromWaitUntilResponse(resp *iwfidl.WorkflowStateStartResponse) error {
Expand Down
121 changes: 121 additions & 0 deletions service/interpreter/activityImpl_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package interpreter

import (
"errors"
"fmt"
"github.com/golang/mock/gomock"
"github.com/indeedeng/iwf/gen/iwfidl"
"github.com/indeedeng/iwf/service/common/ptr"
"github.com/stretchr/testify/assert"
"io"
"net/http"
"strings"
"testing"
"time"
)
Expand Down Expand Up @@ -88,3 +94,118 @@ func createCommands() ([]iwfidl.TimerCommand, []iwfidl.SignalCommand, []iwfidl.I
}
return validTimerCommands, validSignalCommands, internalCommands
}

func TestComposeHttpError_LocalActivity_LongErrorResponse(t *testing.T) {
longError := strings.Repeat("a", 1000)
errMsg := "original error message"
mockActivityProvider, httpResp, err := createTestComposeHttpErrorInitialState(t, longError, errMsg)

returnedError := errors.New("test error msg")
mockActivityProvider.EXPECT().NewApplicationError("1st-attempt-failure", fmt.Sprintf("statusCode: %v, responseBody: %v, errMsg: %v", httpResp.StatusCode, longError[:50]+"...", errors.New(errMsg[:5]+"..."))).Return(returnedError)

err = composeHttpError(true, mockActivityProvider, err, httpResp, "test-error-type")
if err != nil {
return
}

assert.Error(t, err)
assert.Equal(t, returnedError, err)
}

func TestComposeHttpError_RegularActivity_LongErrorResponse(t *testing.T) {
longError := strings.Repeat("a", 1000)
errMsg := "original error message which is very long like this"
mockActivityProvider, httpResp, err := createTestComposeHttpErrorInitialState(t, longError, errMsg)

returnedError := errors.New("test error msg")
mockActivityProvider.EXPECT().NewApplicationError("test-error-type", fmt.Sprintf("statusCode: %v, responseBody: %v, errMsg: %v", httpResp.StatusCode, longError[:500]+"...", errors.New(errMsg[:50]+"..."))).Return(returnedError)

err = composeHttpError(false, mockActivityProvider, err, httpResp, "test-error-type")
if err != nil {
return
}

assert.Error(t, err)
assert.Equal(t, returnedError, err)
}

func TestComposeHttpError_LocalActivity_ShortErrorResponse(t *testing.T) {
shortError := strings.Repeat("a", 40)
errMsg := "OK"
mockActivityProvider, httpResp, err := createTestComposeHttpErrorInitialState(t, shortError, errMsg)

returnedError := errors.New("test error msg")
mockActivityProvider.EXPECT().NewApplicationError("1st-attempt-failure", fmt.Sprintf("statusCode: %v, responseBody: %v, errMsg: %v", httpResp.StatusCode, shortError, errors.New(errMsg))).Return(returnedError)

err = composeHttpError(true, mockActivityProvider, err, httpResp, "test-error-type")
if err != nil {
return
}

assert.Error(t, err)
assert.Equal(t, returnedError, err)
}

func TestComposeHttpError_RegularActivity_ShortErrorResponse(t *testing.T) {
shortError := strings.Repeat("a", 40)
errMsg := "OK"
mockActivityProvider, httpResp, err := createTestComposeHttpErrorInitialState(t, shortError, errMsg)

returnedError := errors.New("test error msg")
mockActivityProvider.EXPECT().NewApplicationError("test-error-type", fmt.Sprintf("statusCode: %v, responseBody: %v, errMsg: %v", httpResp.StatusCode, shortError, errors.New(errMsg))).Return(returnedError)

err = composeHttpError(false, mockActivityProvider, err, httpResp, "test-error-type")
if err != nil {
return
}

assert.Error(t, err)
assert.Equal(t, returnedError, err)
}

func TestComposeHttpError_LocalActivity_NilResponse(t *testing.T) {
errMsg := "OK"
mockActivityProvider, httpResp, err := createTestComposeHttpErrorInitialState(t, "", errMsg)

returnedError := errors.New("test error msg")
mockActivityProvider.EXPECT().NewApplicationError("1st-attempt-failure", fmt.Sprintf("statusCode: %v, responseBody: %v, errMsg: %v", 0, "None", errors.New(errMsg))).Return(returnedError)

err = composeHttpError(true, mockActivityProvider, err, httpResp, "test-error-type")
if err != nil {
return
}

assert.Error(t, err)
assert.Equal(t, returnedError, err)
}

func TestComposeHttpError_RegularActivity_NilResponse(t *testing.T) {
errMsg := "OK"
mockActivityProvider, httpResp, err := createTestComposeHttpErrorInitialState(t, "", errMsg)

returnedError := errors.New("test error msg")
mockActivityProvider.EXPECT().NewApplicationError("test-error-type", fmt.Sprintf("statusCode: %v, responseBody: %v, errMsg: %v", 0, "None", errors.New(errMsg))).Return(returnedError)

err = composeHttpError(false, mockActivityProvider, err, httpResp, "test-error-type")
if err != nil {
return
}

assert.Error(t, err)
assert.Equal(t, returnedError, err)
}

func createTestComposeHttpErrorInitialState(t *testing.T, httpError string, initialError string) (*MockActivityProvider, *http.Response, error) {
ctrl := gomock.NewController(t)
mockActivityProvider := NewMockActivityProvider(ctrl)

var httpResp *http.Response = nil
if httpError != "" {
httpResp = &http.Response{
StatusCode: 400,
Body: io.NopCloser(strings.NewReader(httpError)),
}
}
err := errors.New(initialError)
return mockActivityProvider, httpResp, err
}
Loading

0 comments on commit c185883

Please sign in to comment.