diff --git a/activity/rest/README.md b/activity/rest/README.md index 034f4e7e..8106609d 100644 --- a/activity/rest/README.md +++ b/activity/rest/README.md @@ -1,90 +1,57 @@ - +# REST Activity +This activity allows you to invoke a REST service. +It will pass through the uri and reads the domain:port from an application configuration if configured via the path settings, e.g.: +`{schemadomainnameport}/` where `schemadomainnameport` is the application property value. +The setting `` needs to be set to yes to function. -# REST -This activity allows you to invoke a REST service. - -## Installation +# Installation +flogo install github.com/project-flogo/contrib/activity/rest -### Flogo CLI +## TIBCO sandbox manual installation ```bash -flogo install github.com/project-flogo/contrib/activity/rest +zip the 'rest' directory (including the directory 'rest' ) +Go to https://eu.integration.cloud.tibco.com/envtools/flogo_extensions and upload the zip +ensure to increase the version nr in the description.json before uploading to distingues between versions ``` -## Configuration - -### Settings: -| Name | Type | Description -|:--- | :--- | :--- -| method | string | The HTTP method to invoke (Allowed values are GET, POST, PUT, DELETE, and PATCH) - **REQUIRED** -| uri | string | The URI of the service to invoke - **REQUIRED** -| headers | params | The HTTP header parameters -| proxy | string | The address of the proxy server to be used -| timeout | int | The request timeout in seconds -| sslConfig | object | SSL configuration - -#### *sslConfig* Object: -| Property | Type | Description -|:--- | :--- | :--- -| skipVerify | bool | Skip SSL validation, defaults to true -| useSystemCert | bool | Use the systems root certificate file, defaults to true -| caFile | string | The path to PEM encoded root certificates file -| certFile | string | The path to PEM encoded client certificate -| keyFile | string | The path to PEM encoded client key +# Configuration +## Settings: +| Name | Type | Description | +|------------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| method | string | The HTTP method to invoke (Allowed values are GET, POST, PUT, DELETE, PATCH, TRIGGER) - **REQUIRED**
When TRIGGER is selected, the actual method is taken from the incoming trigger | +| useEnvProp | boolean | define if you want to replace the schema://hostname:port part with the environment variable | +| uri | string | The URI of the service to invoke - **REQUIRED**
When the uri start with an { it is seen as the start of a applciation property. So {ap} where ap is the applciation property defined to replace runtime | +| headers | params | The HTTP header parameters | +| proxy | string | The address of the proxy server to be used | +| timeout | int | The request timeout in seconds | +| sslConfig | object | SSL configuration | + + +## *sslConfig* Object: +| Property | Type | Description | +|---------------|--------|---------------------------------------------------------| +| skipVerify | bool | Skip SSL validation, defaults to true | +| useSystemCert | bool | Use the systems root certificate file, defaults to true | +| caFile | string | The path to PEM encoded root certificates file | +| certFile | string | The path to PEM encoded client certificate | +| keyFile | string | The path to PEM encoded client key | *Note: used if URI is https* -### Input: -| Name | Type | Description -|:--- | :--- | :--- -| pathParams | params | The path parameters (e.g., 'id' in http://.../pet/:id/name ) -| queryParams | params | The query parameters (e.g., 'id' in http://.../pet?id=someValue ) -| headers | params | The HTTP header parameters -| content | any | The message content to send. This is only used in POST, PUT, and PATCH - -### Output: -| Name | Type | Description -|:--- | :--- | :--- -| status | int | The HTTP status code -| data | any | The HTTP response data -| headers | params | The HTTP response headers -| cookies | array | The response cookies (from 'Set-Cookie') - -## Examples -### Simple -The below example retrieves a pet with number '1234' from the [swagger petstore](http://petstore.swagger.io): - -```json -{ - "id": "rest_activity", - "name": "REST Activity", - "activity": { - "ref": "github.com/project-flogo/contrib/activity/rest", - "settings": { - "method": "GET", - "uri": "http://petstore.swagger.io/v2/pet/1234" - } - } -} -``` - -### Using Path Params -The below example is the same as above, it retrieves a pet with number '1234' from the [swagger petstore](http://petstore.swagger.io), but uses a URI parameter to configure the ID: - -```json -{ - "id": "rest_activity", - "name": "REST Activity", - "activity": { - "ref": "github.com/project-flogo/contrib/activity/rest", - "settings": { - "method": "GET", - "uri": "http://petstore.swagger.io/v2/pet/:id" - }, - "input": { - "params": { "id": "1234"} - } - } -} -``` \ No newline at end of file +## Input: +| Name | Type | Description | +|-------------|--------|----------------------------------------------------------------------------| +| pathParams | params | The path parameters (e.g., 'id' in http://.../pet/:id/name ) | +| queryParams | params | The query parameters (e.g., 'id' in http://.../pet?id=someValue ) | +| headers | params | The HTTP header parameters | +| method | string | the method coming in from the trigger; Only used if 'TRIGGER' is selected | +| content | any | The message content to send. This is only used in POST, PUT, and PATCH | +| envPropUri | string | Connect the availalbe environment variable into this activity | + + +## Output: +| Name | Type | Description | +|---------|--------|------------------------------------------| +| status | int | The HTTP status code | +| data | any | The HTTP response data | +| headers | params | The HTTP response headers | +| cookies | array | The response cookies (from 'Set-Cookie') | diff --git a/activity/rest/activity.go b/activity/rest/activity.go index 7d3d77d1..458b7b66 100644 --- a/activity/rest/activity.go +++ b/activity/rest/activity.go @@ -20,14 +20,18 @@ func init() { } const ( - methodPOST = "POST" - methodPUT = "PUT" - methodPATCH = "PATCH" + methodPOST = "POST" + methodPUT = "PUT" + methodPATCH = "PATCH" + methodTRIGGER = "TRIGGER" ) var activityMd = activity.ToMetadata(&Settings{}, &Input{}, &Output{}) func New(ctx activity.InitContext) (activity.Activity, error) { + logger := ctx.Logger() + logger.Debugf("Create REST activity") + s := &Settings{} err := metadata.MapToStruct(ctx.Settings(), s, true) if err != nil { @@ -45,8 +49,6 @@ func New(ctx activity.InitContext) (activity.Activity, error) { httpTransportSettings.ResponseHeaderTimeout = time.Second * time.Duration(s.Timeout) } - logger := ctx.Logger() - // Set the proxy server to use, if supplied if len(s.Proxy) > 0 { proxyURL, err := url.Parse(s.Proxy) @@ -60,7 +62,6 @@ func New(ctx activity.InitContext) (activity.Activity, error) { } if strings.HasPrefix(s.Uri, "https") { - cfg := &ssl.Config{} if len(s.SSLConfig) != 0 { @@ -111,7 +112,8 @@ func (a *Activity) Metadata() *activity.Metadata { // Eval implements api.Activity.Eval - Invokes a REST Operation func (a *Activity) Eval(ctx activity.Context) (done bool, err error) { - + logger := ctx.Logger() + logger.Debugf("ACTIVITY CALL START") input := &Input{} err = ctx.GetInputObject(input) if err != nil { @@ -119,42 +121,44 @@ func (a *Activity) Eval(ctx activity.Context) (done bool, err error) { } uri := a.settings.Uri - + if a.settings.UseEnvProp == "YES" { + uri = replaceSubString(uri, input.EnvPropUri) + } if a.containsParam { - - if len(input.PathParams) == 0 { + if len(input.PathParams) == 0 && strings.Index(strings.Replace(uri, ":restOfThePath", "", 1), "/:") > -1 { err := activity.NewError("Path Params not specified, required for URI: "+uri, "", nil) return false, err } - - uri = BuildURI(a.settings.Uri, input.PathParams) + uri, err = BuildURI(uri, input.PathParams) + if err != nil { + return false, err + } + } else { + logger.Debugf("No call to buildURI") } if len(input.QueryParams) > 0 { qp := url.Values{} - for key, value := range input.QueryParams { qp.Set(key, value) } - uri = uri + "?" + qp.Encode() } - logger := ctx.Logger() - + method := a.settings.Method + if method == methodTRIGGER { + method = input.Method + } if logger.DebugEnabled() { - logger.Debugf("REST Call: [%s] %s", a.settings.Method, uri) + logger.Debugf("REST Call: [%s] %s", method, uri) } var reqBody io.Reader contentType := "application/json; charset=UTF-8" - method := a.settings.Method if method == methodPOST || method == methodPUT || method == methodPATCH { - contentType = getContentType(input.Content) - if input.Content != nil { if str, ok := input.Content.(string); ok { reqBody = bytes.NewBuffer([]byte(str)) @@ -177,17 +181,22 @@ func (a *Activity) Eval(ctx activity.Context) (done bool, err error) { } headers := a.getHeaders(input.Headers) - - // Set headers if len(headers) > 0 { - if logger.DebugEnabled() { - logger.Debug("Setting HTTP request headers...") - } for key, value := range headers { - if logger.TraceEnabled() { - logger.Trace("%s: %s", key, value) + if strings.HasPrefix(key, "X-Forwarded") { + if logger.DebugEnabled() { + logger.Debugf("NOT Adding HTTP request headers: |%s| : |%s|", key, value) + } + + } else { + if strings.HasPrefix(key, "X-Authorization") { + key = key[2:] + } + if logger.DebugEnabled() { + logger.Debugf("Adding HTTP request headers: |%s| : |%s|", key, value) + } + req.Header.Set(key, value) } - req.Header.Set(key, value) } } @@ -197,7 +206,7 @@ func (a *Activity) Eval(ctx activity.Context) (done bool, err error) { } if resp == nil { - logger.Trace("Empty response") + logger.Debugf("Called but caller returned an empty response") return true, nil } @@ -208,9 +217,8 @@ func (a *Activity) Eval(ctx activity.Context) (done bool, err error) { }() if logger.DebugEnabled() { - logger.Debug("Response status:", resp.Status) + logger.Debugf("Response status: %s", resp.Status) } - respHeaders := make(map[string]string, len(resp.Header)) for key := range resp.Header { @@ -249,22 +257,32 @@ func (a *Activity) Eval(ctx activity.Context) (done bool, err error) { result = string(b) } - if logger.TraceEnabled() { - logger.Trace("Response body:", result) + if logger.DebugEnabled() { + for key, value := range respHeaders { + logger.Debugf("Response headers from REST CALL key: %s value: %s", key, value) + } + logger.Debugf("Status and code of HTTP Response: %s | %s", resp.StatusCode, resp.Status) + logger.Debugf("Response body:", result) } - - - output := &Output{Status: resp.StatusCode, Data: result, Headers:respHeaders, Cookies:cookies} + output := &Output{Status: resp.StatusCode, Data: result, Headers: respHeaders, Cookies: cookies} err = ctx.SetOutputObject(output) if err != nil { return false, err } - return true, nil } //////////////////////////////////////////////////////////////////////////////////////// // Utils +func replaceSubString(uri string, replacement string) string { + startChar := strings.Index(uri, "{") + endChar := strings.Index(uri, "}") + if startChar == -1 || endChar == -1 { + return uri + } + + return strings.Replace(uri, uri[startChar:endChar+1], replacement, 1) +} func (a *Activity) getHeaders(inputHeaders map[string]string) map[string]string { @@ -287,7 +305,6 @@ func (a *Activity) getHeaders(inputHeaders map[string]string) map[string]string return headers } - //todo just make contentType a setting func getContentType(replyData interface{}) string { @@ -307,38 +324,37 @@ func getContentType(replyData interface{}) string { return contentType } -// BuildURI is a temporary crude URI builder -func BuildURI(uri string, values map[string]string) string { +func BuildURI(uri string, values map[string]string) (string, error) { var buffer bytes.Buffer + var i int buffer.Grow(len(uri)) + // schema://host:port/path?query#fragment + // continue with normal processing as before having static domain:port addrStart := strings.Index(uri, "://") + i = addrStart + 3 - i := addrStart + 3 - - for i < len(uri) { - if uri[i] == '/' { - break + if uri[addrStart+3] != ':' { + for i < len(uri) { + if uri[i] == '/' { + break + } + i++ } - i++ + buffer.WriteString(uri[0:i]) } - buffer.WriteString(uri[0:i]) - for i < len(uri) { if uri[i] == ':' { j := i + 1 for j < len(uri) && uri[j] != '/' { j++ } - if i+1 == j { - buffer.WriteByte(uri[i]) i++ } else { - param := uri[i+1 : j] value := values[param] buffer.WriteString(value) @@ -347,12 +363,10 @@ func BuildURI(uri string, values map[string]string) string { } i = j + 1 } - } else { buffer.WriteByte(uri[i]) i++ } } - - return buffer.String() + return buffer.String(), nil } diff --git a/activity/rest/activity_test.go b/activity/rest/activity_test.go index 02eec248..cefbf96e 100644 --- a/activity/rest/activity_test.go +++ b/activity/rest/activity_test.go @@ -19,19 +19,25 @@ func TestRegister(t *testing.T) { } func TestSettings(t *testing.T) { - settings := &Settings{Method: "POS", Uri: "http://petstore.swagger.io/v2/pet"} + settings := &Settings{UseEnvProp: "NO", Method: "POS", Uri: "http://petstore.swagger.io/v2/pet"} iCtx := test.NewActivityInitContext(settings, nil) _, err := New(iCtx) assert.NotNil(t, err) - settings = &Settings{Method: "POST", Uri: ""} + settings = &Settings{UseEnvProp: "YES", Method: "POS", Uri: ""} iCtx = test.NewActivityInitContext(settings, nil) _, err = New(iCtx) assert.NotNil(t, err) - settings = &Settings{Method: "pOsT", Uri: "http://petstore.swagger.io/v2/pet"} + settings = &Settings{UseEnvProp: "NO", Method: "pOsT", Uri: "http://petstore.swagger.io/v2/pet"} + + iCtx = test.NewActivityInitContext(settings, nil) + _, err = New(iCtx) + assert.Nil(t, err) + + settings = &Settings{UseEnvProp: "YES", Method: "pOsT", Uri: "http://petstore.swagger.io/v2/pet"} iCtx = test.NewActivityInitContext(settings, nil) _, err = New(iCtx) @@ -47,7 +53,7 @@ var petID string func TestSimplePost(t *testing.T) { - settings := &Settings{Method: "POST", Uri: "http://petstore.swagger.io/v2/pet"} + settings := &Settings{UseEnvProp: "NO", Method: "POST", Uri: "http://petstore.swagger.io/v2/pet"} mf := mapper.NewFactory(resolve.GetBasicResolver()) iCtx := test.NewActivityInitContext(settings, mf) @@ -65,9 +71,9 @@ func TestSimplePost(t *testing.T) { } -func TestSimpleGet(t *testing.T) { +func TestPassThrough(t *testing.T) { - settings := &Settings{Method: "GET", Uri: "http://petstore.swagger.io/v2/pet/16"} + settings := &Settings{UseEnvProp: "NO", Method: "TRIGGER", Uri: "http://petstore.swagger.io/v2/pet"} mf := mapper.NewFactory(resolve.GetBasicResolver()) iCtx := test.NewActivityInitContext(settings, mf) @@ -76,6 +82,55 @@ func TestSimpleGet(t *testing.T) { tc := test.NewActivityContext(act.Metadata()) + //setup attrs + tc.SetInput("content", reqPostStr) + tc.SetInput("method", "GET") + + //eval + act.Eval(tc) + assert.NotNil(t, tc.GetOutput("data")) + +} + +func TestPassThroughEnv(t *testing.T) { + + // url to hit: http://petstore.swagger.io/v2/pet + + settings := &Settings{UseEnvProp: "YES", Method: "TRIGGER", Uri: "{envProp}/:restOfPath"} + + mf := mapper.NewFactory(resolve.GetBasicResolver()) + iCtx := test.NewActivityInitContext(settings, mf) + act, err := New(iCtx) + assert.Nil(t, err) + + tc := test.NewActivityContext(act.Metadata()) + + //setup attrs + pathParams := map[string]string{ + "restOfPath": "v2/pet", + } + tc.SetInput("content", reqPostStr) + tc.SetInput("method", "GET") + tc.SetInput("envPropUri", "http://petstore.swagger.io") + tc.SetInput("pathParams", pathParams) + + //eval + act.Eval(tc) + assert.NotNil(t, tc.GetOutput("data")) + +} + +func TestSimpleGet(t *testing.T) { + + settings := &Settings{UseEnvProp: "YES", Method: "GET", Uri: "{prop}/v2/pet/16"} + + mf := mapper.NewFactory(resolve.GetBasicResolver()) + iCtx := test.NewActivityInitContext(settings, mf) + act, err := New(iCtx) + assert.Nil(t, err) + + tc := test.NewActivityContext(act.Metadata()) + tc.SetInput("envPropUri", "http://www.httpbin.org/anything/firstPart") //eval act.Eval(tc) @@ -85,7 +140,7 @@ func TestSimpleGet(t *testing.T) { func TestSimpleGetWithHeaders(t *testing.T) { - settings := &Settings{Method: "GET", Uri: "http://petstore.swagger.io/v2/pet/1"} + settings := &Settings{UseEnvProp: "YES", Method: "GET", Uri: "http://petstore.swagger.io/v2/pet/1"} mf := mapper.NewFactory(resolve.GetBasicResolver()) iCtx := test.NewActivityInitContext(settings, mf) @@ -97,7 +152,7 @@ func TestSimpleGetWithHeaders(t *testing.T) { headers := make(map[string]string) headers["TestHeader"] = "TestValue" tc.SetInput("headers", headers) - + tc.SetInput("envPropUri", "http://www.httpbin.org/anything/firstPart") //eval act.Eval(tc) @@ -109,7 +164,7 @@ func TestSimpleGetWithHeaders(t *testing.T) { func TestParamGet(t *testing.T) { - settings := &Settings{Method: "GET", Uri: "http://petstore.swagger.io/v2/pet/:id"} + settings := &Settings{UseEnvProp: "YES", Method: "GET", Uri: "http://petstore.swagger.io/v2/pet/:id"} mf := mapper.NewFactory(resolve.GetBasicResolver()) iCtx := test.NewActivityInitContext(settings, mf) @@ -130,30 +185,9 @@ func TestParamGet(t *testing.T) { } -//func TestSimpleGetWithProxy(t *testing.T) { -// -// settings := &Settings{Method:"GET", Uri:"http://petstore.swagger.io/v2/pet/1"} -// settings.Proxy = "http://localhost:12345" -// -// mf := mapper.NewFactory(resolve.GetBasicResolver()) -// iCtx := test.NewActivityInitContext(settings, mf) -// act, err := New(iCtx) -// assert.Nil(t, err) -// -// tc := test.NewActivityContext(act.Metadata()) -// -// //eval -// _, err = act.Eval(tc) -// if err != nil { -// fmt.Printf("error: %v\n", err) -// } -// val := tc.GetOutput("result") -// fmt.Printf("result: %v\n", val) -//} - func TestSimpleGetQP(t *testing.T) { - settings := &Settings{Method: "GET", Uri: "http://petstore.swagger.io/v2/pet/findByStatus"} + settings := &Settings{UseEnvProp: "YES", Method: "GET", Uri: "http://petstore.swagger.io/v2/pet/findByStatus"} mf := mapper.NewFactory(resolve.GetBasicResolver()) iCtx := test.NewActivityInitContext(settings, mf) @@ -181,7 +215,7 @@ func TestBuildURI(t *testing.T) { "id": "1234", } - newURI := BuildURI(uri, params) + newURI, _ := BuildURI(uri, params) assert.NotNil(t, newURI) } @@ -195,19 +229,20 @@ func TestBuildURI2(t *testing.T) { "id": "1234", } - newURI := BuildURI(uri, params) + newURI, _ := BuildURI(uri, params) assert.NotNil(t, newURI) } func TestBuildURI3(t *testing.T) { - uri := "http://localhost/flow/:id" + uri := "http://:localhost/flow/:id" params := map[string]string{ - "id": "1234", + "id": "1234", + "localhost": "google.com", } - newURI := BuildURI(uri, params) + newURI, _ := BuildURI(uri, params) assert.NotNil(t, newURI) } @@ -221,7 +256,29 @@ func TestBuildURI4(t *testing.T) { "id": "1234", } - newURI := BuildURI(uri, params) + newURI, _ := BuildURI(uri, params) assert.NotNil(t, newURI) } + +func TestReplaceSubStringNothingToReplace(t *testing.T) { + + uri := "{startdomainname}/:cmd/:id/test" + + result := replaceSubString(uri, "http://www.google.com") + assert.Contains(t, result, "http://www.google.com/:cmd/:id/test") +} + +func TestReplaceSubString(t *testing.T) { + + uri := "{startdomainname}/:cmd/:id/test" + + result := replaceSubString(uri, "http://www.google.com") + assert.Contains(t, result, "http://www.google.com/:cmd/:id/test") +} + +func TestMe(t *testing.T) { + e := "X-Autorisation" + a := e[2:] + assert.Equal(t, "Autorisation", a) +} diff --git a/activity/rest/descriptor.json b/activity/rest/descriptor.json index 68cc7624..17b56105 100644 --- a/activity/rest/descriptor.json +++ b/activity/rest/descriptor.json @@ -1,23 +1,30 @@ { - "name": "flogo-rest", + "name": "flogo-lp-rest", "type": "flogo:activity", - "version": "0.10.0", - "title": "REST Invoke", - "description": "Invokes a REST Service", - "homepage": "https://github.com/project-flogo/contrib/tree/master/activity/rest", + "version": "1.0.0", + "title": "REST uri-pass through", + "description": "HTTP Method uri-part pass through activity", + "homepage": "https://gitlab.core-services.leaseplan.systems/workloads/0026-wkl-ng-integration/integration/shared/flogoresttrigger", "settings": [ { "name": "method", "type": "string", "required": true, - "allowed": [ "GET", "POST", "PUT", "PATCH", "DELETE" ], - "description" : "The HTTP method to invoke" + "allowed": [ "GET", "POST", "PUT", "PATCH", "DELETE", "TRIGGER" ], + "description" : "The HTTP method to invoke; Passed down from trigger then select TRIGGER" + }, + { + "name": "useEnvProp", + "type": "string", + "required": true, + "allowed": [ "YES", "NO"], + "description" : "If YES, then the input param envPropUri is used for the [schema://hostname:port/initialPart] of the uri; uri is concat behind the envPropUri" }, { "name": "uri", "type": "string", "required": true, - "description" : "The URI of the service to invoke" + "description" : "The URI of the service to invoke; use /:restOfThePath to replace with incoming path" }, { "name": "headers", @@ -85,10 +92,20 @@ "type": "params", "description" : "The HTTP header parameters" }, + { + "name": "method", + "type": "string", + "description": "The HTTP method to use" + }, { "name": "content", "type": "any", "description" : "The message content to send. This is only used in POST, PUT, and PATCH" + }, + { + "name": "envPropUri", + "type": "string", + "description" : "To push the environment property for the uri to use (schema://hostname:port/partialUrl)" } ], "output": [ diff --git a/activity/rest/go.mod b/activity/rest/go.mod index a031f482..e61523e1 100644 --- a/activity/rest/go.mod +++ b/activity/rest/go.mod @@ -1,9 +1,18 @@ -module github.com/project-flogo/contrib/activity/rest +module FlogoRestActivity/rest require ( - github.com/pkg/errors v0.9.1 // indirect - github.com/project-flogo/core v0.9.4-hf.1 - github.com/stretchr/testify v1.4.0 + github.com/project-flogo/core v1.6.0 + github.com/stretchr/testify v1.7.0 ) -go 1.12 +require ( + github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + go.uber.org/atomic v1.6.0 // indirect + go.uber.org/multierr v1.5.0 // indirect + go.uber.org/zap v1.16.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect +) + +go 1.17 diff --git a/activity/rest/go.sum b/activity/rest/go.sum index b17aee7d..a3e33c67 100644 --- a/activity/rest/go.sum +++ b/activity/rest/go.sum @@ -1,24 +1,67 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195 h1:c4mLfegoDw6OhSJXTd2jUEQgZUQuJWtocudb97Qn9EM= +github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/project-flogo/core v0.9.4-hf.1 h1:qjwXVpTL38yAgMFDDhb+SdOzye0qGoR2jOhkZiWgLh0= -github.com/project-flogo/core v0.9.4-hf.1/go.mod h1:QGWi7TDLlhGUaYH3n/16ImCuulbEHGADYEXyrcHhX7U= +github.com/project-flogo/core v1.6.0 h1:+LH226SGU5961xh5H9lp8iUGp5dWPHaMYGu0pTuSLSE= +github.com/project-flogo/core v1.6.0/go.mod h1:fapTXUhLxDeAHyb6eMkuwnYswO8FpZJAMat055QVdJE= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/activity/rest/metadata.go b/activity/rest/metadata.go index 21383308..c13cd4b5 100644 --- a/activity/rest/metadata.go +++ b/activity/rest/metadata.go @@ -5,16 +5,17 @@ import ( ) type Settings struct { - Method string `md:"method,required,allowed(GET,POST,PUT,PATCH,DELETE)"` // The HTTP method to invoke - Uri string `md:"uri,required"` // The URI of the service to invoke - Headers map[string]string `md:"headers"` // The HTTP header parameters - Proxy string `md:"proxy"` // The address of the proxy server to be use - Timeout int `md:"timeout"` // The request timeout in seconds - SkipSSLVerify bool `md:"skipSSLVerify"` // Skip SSL validation - CertFile string `md:"certFile"` // Path to PEM encoded client certificate - KeyFile string `md:"keyFile"` // Path to PEM encoded client key - CAFile string `md:"CAFile"` // Path to PEM encoded root certificates file - SSLConfig map[string]interface{} `md:"sslConfig"` // SSL Configuration + UseEnvProp string `md:"useEnvProp,default,allowed(YES,NO)"` // Do we want to use an environment property for the uri + Uri string `md:"uri,required"` // The URI of the service to invoke + Method string `md:"method,allowed(TRIGGER,GET,POST,PUT,PATCH,DELETE)"` // The HTTP method to invoke + Headers map[string]string `md:"headers"` // The HTTP header parameters + Proxy string `md:"proxy"` // The address of the proxy server to be use + Timeout int `md:"timeout"` // The request timeout in seconds + SkipSSLVerify bool `md:"skipSSLVerify"` // Skip SSL validation + CertFile string `md:"certFile"` // Path to PEM encoded client certificate + KeyFile string `md:"keyFile"` // Path to PEM encoded client key + CAFile string `md:"CAFile"` // Path to PEM encoded root certificates file + SSLConfig map[string]interface{} `md:"sslConfig"` // SSL Configuration } type Input struct { @@ -22,6 +23,8 @@ type Input struct { QueryParams map[string]string `md:"queryParams"` // The path parameters (e.g., 'id' in http://.../pet/:id/name ) Headers map[string]string `md:"headers"` // The HTTP header parameters Content interface{} `md:"content"` // The message content to send. This is only used in POST, PUT, and PATCH + Method string `md:"method"` // The HTTP method to use for this request + EnvPropUri string `md:"envPropUri"` // Using an environment property for the uri } func (i *Input) ToMap() map[string]interface{} { @@ -30,6 +33,8 @@ func (i *Input) ToMap() map[string]interface{} { "queryParams": i.QueryParams, "headers": i.Headers, "content": i.Content, + "method": i.Method, + "envPropUri": i.EnvPropUri, } } @@ -49,7 +54,11 @@ func (i *Input) FromMap(values map[string]interface{}) error { return err } i.Content = values["content"] - + i.Method, err = coerce.ToString(values["method"]) + if err != nil { + return err + } + i.EnvPropUri, err = coerce.ToString(values["envPropUri"]) return nil }