diff --git a/examples/api/custom-pattern/README.md b/examples/api/custom-pattern/README.md new file mode 100644 index 0000000..bfa195d --- /dev/null +++ b/examples/api/custom-pattern/README.md @@ -0,0 +1,46 @@ +# Gateway using Custom-Pattern +This recipe is a gateway using the custom pattern. It uses counter activity to keep the track of number of successful +and failed HTTP calls. + +Example: +#Counter Activity +| Name | Type | Description | +|:-----------|:--------|:--------------| +| counterName | string, required:true | The name of the counter | +| op | string | Counter operation, 'get' is the default operation | + + +## Installation +* Install [Go](https://golang.org/) + +## Setup +```bash +git clone https://github.com/project-flogo/microgateway +cd microgateway/examples/api/custom-pattern +``` + +## Testing +Start the gateway: +```bash +go run main.go +``` +In another terminal start the server: +```bash +go run main.go -server + +### Request is successful +Run the following command: +```bash +curl --request GET http://localhost:9096/endpoint +``` + +You should see on successful call: +```json +{"Error-Calls":0,"Success-Calls":1} +``` + +Similarly, on unsuccessful call...or in case of error: +You should see on successful call: +```json +{"Error-Calls":1,"Success-Calls":0} +``` diff --git a/examples/api/custom-pattern/main.go b/examples/api/custom-pattern/main.go new file mode 100644 index 0000000..67f24fc --- /dev/null +++ b/examples/api/custom-pattern/main.go @@ -0,0 +1,146 @@ +package main + +import ( + "flag" + "fmt" + "html" + "io/ioutil" + "net/http" + + _ "github.com/project-flogo/contrib/activity/counter" + _ "github.com/project-flogo/contrib/activity/rest" + "github.com/project-flogo/core/engine" + _ "github.com/project-flogo/microgateway/activity/circuitbreaker" + "github.com/project-flogo/microgateway/examples" +) + +var ( + server = flag.Bool("server", false, "run the test server") +) + +const reply = `{ + "name": "sally" +}` + +const pattern = `{ + "name": "CustomPattern", + "steps": [ + { + "service": "HttpBackend", + "halt": "($.HttpBackend.error != nil) && !error.isneterror($.HttpBackend.error)" + }, + { + "if": "$.HttpBackend.error == nil", + "service": "SuccessCounter" + }, + { + "if": "$.HttpBackend.error != nil", + "service": "ErrorCounter" + }, + { + "service": "GetCounterSuccess" + }, + { + "service": "GetCounterError" + } + ], + "responses": [ + { + "if" : "$.GetCounterSuccess.error == nil", + "error": false, + "output": { + "code": 200, + "data": { + "Success-Calls": "=$.GetCounterSuccess.outputs.value", + "Error-Calls": "=$.GetCounterError.outputs.value" + } + } + }, + { + "error": true, + "output": { + "code": 400, + "data": "Error" + } + } + ], + "services": [ + { + "name": "HttpBackend", + "description": "Make an http call to your backend", + "ref": "github.com/project-flogo/contrib/activity/rest", + "settings": { + "method": "GET", + "uri": "http://localhost:1234/pets" + } + }, + { + "name": "SuccessCounter", + "description": "Increment counter on successful call", + "ref": "github.com/project-flogo/contrib/activity/counter", + "settings": { + "counterName": "SuccessCounter", + "op": "increment" + } + }, + { + "name": "ErrorCounter", + "description": "Increment counter on error call", + "ref": "github.com/project-flogo/contrib/activity/counter", + "settings": { + "counterName": "ErrorCounter", + "op": "increment" + } + }, + { + "name": "GetCounterSuccess", + "description": "Get success counter", + "ref": "github.com/project-flogo/contrib/activity/counter", + "settings": { + "counterName": "SuccessCounter" + } + }, + { + "name": "GetCounterError", + "description": "Get error counter", + "ref": "github.com/project-flogo/contrib/activity/counter", + "settings": { + "counterName": "ErrorCounter" + } + } + ] +}` + +func main() { + flag.Parse() + + if *server { + http.HandleFunc("/pets", func(w http.ResponseWriter, r *http.Request) { + fmt.Printf("url: %q\n", html.EscapeString(r.URL.Path)) + defer r.Body.Close() + body, err := ioutil.ReadAll(r.Body) + if err != nil { + panic(err) + } + fmt.Println(string(body)) + w.Header().Set("Content-Type", "application/json") + _, err = w.Write([]byte(reply)) + if err != nil { + panic(err) + } + }) + + err := http.ListenAndServe(":1234", nil) + if err != nil { + panic(err) + } + + return + } + + e, err := examples.CustomPattern("CustomPattern", pattern) + if err != nil { + panic(err) + } + engine.RunEngine(e) +} diff --git a/examples/api/default-channel-pattern/main.go b/examples/api/default-channel-pattern/main.go index 871f54a..72d98ed 100644 --- a/examples/api/default-channel-pattern/main.go +++ b/examples/api/default-channel-pattern/main.go @@ -1,15 +1,13 @@ package main import ( - + _ "github.com/project-flogo/contrib/activity/channel" "github.com/project-flogo/core/engine" - "github.com/project-flogo/microgateway/examples" _ "github.com/project-flogo/microgateway/activity/circuitbreaker" _ "github.com/project-flogo/microgateway/activity/jwt" - _ "github.com/project-flogo/contrib/activity/channel" + "github.com/project-flogo/microgateway/examples" ) - func main() { e, err := examples.DefaultChannelPattern() diff --git a/examples/examples.go b/examples/examples.go index 7674436..d73cf4b 100644 --- a/examples/examples.go +++ b/examples/examples.go @@ -10,6 +10,7 @@ import ( "github.com/project-flogo/core/engine/channels" "github.com/project-flogo/microgateway" microapi "github.com/project-flogo/microgateway/api" + "github.com/project-flogo/microgateway/internal/pattern" ) // BasicGatewayExample returns a Basic Gateway API example @@ -226,3 +227,30 @@ func DefaultChannelPattern() (engine.Engine, error) { return api.NewEngine(app) } + +// CustomPattern returns an engine configured for given pattern name +func CustomPattern(patternName string, custompattern string) (engine.Engine, error) { + err := pattern.Register(patternName, custompattern) + if err != nil { + panic(err) + } + app := api.NewApp() + + trg := app.NewTrigger(&trigger.Trigger{}, &trigger.Settings{Port: 9096}) + handler, err := trg.NewHandler(&trigger.HandlerSettings{ + Method: "GET", + Path: "/endpoint", + }) + if err != nil { + panic(err) + } + + _, err = handler.NewAction(µgateway.Action{}, map[string]interface{}{ + "pattern": patternName, + }) + if err != nil { + panic(err) + } + + return api.NewEngine(app) +} diff --git a/examples/examples_test.go b/examples/examples_test.go index 4eb47a8..fae9a38 100644 --- a/examples/examples_test.go +++ b/examples/examples_test.go @@ -10,12 +10,12 @@ import ( "testing" "time" + _ "github.com/project-flogo/contrib/activity/channel" _ "github.com/project-flogo/contrib/activity/rest" - _ "github.com/project-flogo/microgateway/activity/ratelimiter" - _ "github.com/project-flogo/microgateway/activity/circuitbreaker" "github.com/project-flogo/core/engine" + _ "github.com/project-flogo/microgateway/activity/circuitbreaker" _ "github.com/project-flogo/microgateway/activity/jwt" - _ "github.com/project-flogo/contrib/activity/channel" + _ "github.com/project-flogo/microgateway/activity/ratelimiter" "github.com/project-flogo/microgateway/api" test "github.com/project-flogo/microgateway/internal/testing" "github.com/stretchr/testify/assert" @@ -258,7 +258,6 @@ func TestDefaultHttpPatternJSON(t *testing.T) { testDefaultHTTPPattern(t, e) } - func testDefaultChannelPattern(t *testing.T, e engine.Engine) { defer api.ClearResources() diff --git a/internal/pattern/DefaultHttpPattern.json b/internal/pattern/DefaultHttpPattern.json index 1928a53..c32bc35 100644 --- a/internal/pattern/DefaultHttpPattern.json +++ b/internal/pattern/DefaultHttpPattern.json @@ -152,4 +152,4 @@ } } ] -} +} \ No newline at end of file diff --git a/internal/pattern/assets.go b/internal/pattern/assets.go index 4028133..9dc8907 100644 --- a/internal/pattern/assets.go +++ b/internal/pattern/assets.go @@ -159,7 +159,7 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "DefaultHttpPattern.json": defaulthttppatternJson, + "DefaultHttpPattern.json": defaulthttppatternJson, "DefaultChannelPattern.json": defaultchannelpatternJson, } @@ -202,9 +202,10 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ "DefaultChannelPattern.json": &bintree{defaultchannelpatternJson, map[string]*bintree{}}, - "DefaultHttpPattern.json": &bintree{defaulthttppatternJson, map[string]*bintree{}}, + "DefaultHttpPattern.json": &bintree{defaulthttppatternJson, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory @@ -253,4 +254,3 @@ func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } - diff --git a/internal/pattern/pattern.go b/internal/pattern/pattern.go index ab6463b..f020ff7 100644 --- a/internal/pattern/pattern.go +++ b/internal/pattern/pattern.go @@ -4,20 +4,50 @@ package pattern import ( "encoding/json" - + "fmt" "github.com/project-flogo/microgateway/api" ) +var patternMap = make(map[string][]byte) + +func init() { + patterns := []string{"DefaultChannelPattern", "DefaultHttpPattern"} + for i := range patterns { + patternName := patterns[i] + ".json" + JSON, err := Asset(patternName) + if err != nil { + fmt.Println("Error from Asset function") + } + patternMap[patternName] = JSON + } +} + // Load loads a pattern func Load(pattern string) (*api.Microgateway, error) { - patternJSON, err := Asset(pattern + ".json") - if err != nil { - return nil, err - } + patternJSON := []byte{} + patternJSON = getPattern(pattern) pDef := &api.Microgateway{} - err = json.Unmarshal(patternJSON, pDef) + err := json.Unmarshal(patternJSON, pDef) if err != nil { return nil, err } return pDef, nil } + +//Registers a pattern +func Register(patternName string, pattern string) error { + patternFileName := patternName + ".json" + if _, ok := patternMap[patternFileName]; !ok { + patternMap[patternFileName] = []byte(pattern) + } + return nil +} + +//Returns a registered pattern +func getPattern(pattern string) []byte { + patternFileName := pattern + ".json" + if _, ok := patternMap[patternFileName]; ok { + return patternMap[patternFileName] + } + return nil +}