diff --git a/action_test.go b/action_test.go index bba9d1c..93da50e 100644 --- a/action_test.go +++ b/action_test.go @@ -258,7 +258,12 @@ func TestMicrogatewayHttpPattern(t *testing.T) { "useJWT": false, "useCircuitBreaker": false, "backendUrl": "http://localhost:1234/", + "method": "GET", "rateLimit": "3-M", + "mode": "a", + "threshold": 5, + "timeout": 60, + "period": 60, }) assert.Nil(t, err) assert.NotNil(t, action) diff --git a/examples/api/default-http-pattern/README.md b/examples/api/default-http-pattern/README.md index e97a2c5..668e18e 100644 --- a/examples/api/default-http-pattern/README.md +++ b/examples/api/default-http-pattern/README.md @@ -1,6 +1,32 @@ # Gateway using Default Http Pattern This recipe is a gateway using the defult http pattern which uses JWT, Rate Limiter, and Circuit Breaker. +#Circuit Breaker Service: +| Name | Type | Description | +|:-----------|:--------|:--------------| +| mode | string | The tripping mode: 'a' for contiguous errors, 'b' for errors within a time period, 'c' for contiguous errors within a time period, and 'd' for a probabilistic smart circuit breaker mode. Defaults to mode 'a' | +| threshold | number | The number of errors required for tripping| +| period | number | Number of seconds in which errors have to occur for the circuit breaker to trip. Applies to modes 'b' and 'c'| +| timeout | number | Number of seconds that the circuit breaker will remain tripped. Applies to modes 'a', 'b', 'c'| + + +#Rate Limiter +| Name | Type | Description | +|:-----------|:--------|:--------------| +| limit | string | Limit can be specifed in the format of "limit-period". Valid periods are 'S', 'M' & 'H' to represent Second, Minute & Hour. Example: "10-S" represents 10 request/second | + + +#JWT +| Name | Type | Description | +|:-----------|:--------|:--------------| +| token | string | The raw token | +| key | string | The key used to sign the token | +| signingMethod | string | The signing method used (HMAC, ECDSA, RSA, RSAPSS) | +| issuer | string | The 'iss' standard claim to match against | +| subject | string | The 'sub' standard claim to match against | +| audience | string | The 'aud' standard claim to match against | + + ## Installation * Install [Go](https://golang.org/) diff --git a/examples/api/default-http-pattern/main.go b/examples/api/default-http-pattern/main.go index 2dff584..3255f34 100644 --- a/examples/api/default-http-pattern/main.go +++ b/examples/api/default-http-pattern/main.go @@ -7,15 +7,12 @@ import ( "io/ioutil" "net/http" - trigger "github.com/project-flogo/contrib/trigger/rest" - "github.com/project-flogo/core/api" - "github.com/project-flogo/core/engine" - "github.com/project-flogo/microgateway" - _ "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/activity/jwt" _ "github.com/project-flogo/microgateway/activity/ratelimiter" + "github.com/project-flogo/microgateway/examples" ) var ( @@ -24,8 +21,7 @@ var ( const reply = `{ "id": 1, - "category": { - "id": 0, + "category": { "id": 0, "name": "string" }, "name": "sally", @@ -61,35 +57,7 @@ func main() { return } - 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": "DefaultHttpPattern", - "useRateLimiter": true, - "rateLimit": "1-S", - "useJWT": true, - "jwtSigningMethod": "HMAC", - "jwtKey": "qwertyuiopasdfghjklzxcvbnm789101", - "jwtAud": "www.mashling.io", - "jwtIss": "Mashling", - "jwtSub": "tempuser@mail.com", - "useCircuitBreaker": true, - "backendUrl": "http://localhost:1234/pets", - }) - if err != nil { - panic(err) - } - - e, err := api.NewEngine(app) + e, err := examples.DefaultHTTPPattern() if err != nil { panic(err) } diff --git a/examples/examples.go b/examples/examples.go index 80f715d..a2a8516 100644 --- a/examples/examples.go +++ b/examples/examples.go @@ -123,3 +123,42 @@ func HandlerRoutingExample() (engine.Engine, error) { return api.NewEngine(app) } + +// DefaultHTTPPattern returns an engine configured for the DefaultHttpPattern +func DefaultHTTPPattern() (engine.Engine, error) { + 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": "DefaultHttpPattern", + "useRateLimiter": true, + "rateLimit": "1-S", + "useJWT": true, + "jwtSigningMethod": "HMAC", + "jwtKey": "qwertyuiopasdfghjklzxcvbnm789101", + "jwtAud": "www.mashling.io", + "jwtIss": "Mashling", + "jwtSub": "tempuser@mail.com", + "useCircuitBreaker": true, + "backendUrl": "http://localhost:1234/pets", + "mode": "a", + "threshold": 5, + "timeout": 60, + "period": 60, + "method": "GET", + "content": "", + }) + if err != nil { + panic(err) + } + + return api.NewEngine(app) +} diff --git a/examples/examples_test.go b/examples/examples_test.go index 0383561..e5a8143 100644 --- a/examples/examples_test.go +++ b/examples/examples_test.go @@ -1,14 +1,20 @@ package examples import ( + "context" "encoding/json" "fmt" "io/ioutil" "net/http" "path/filepath" "testing" + "time" + _ "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/activity/jwt" + _ "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" @@ -19,6 +25,40 @@ type Response struct { Error string `json:"error"` } +type handler struct { + Slow bool +} + +func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + _, err := ioutil.ReadAll(r.Body) + if err != nil { + panic(err) + } + + if h.Slow { + time.Sleep(10 * time.Second) + } + + w.Header().Set("Content-Type", "application/json") + _, err = w.Write([]byte(reply)) + if err != nil { + panic(err) + } +} + +const reply = `{ + "id": 1, + "category": { + "id": 0, + "name": "string" + }, + "name": "sally", + "photoUrls": ["string"], + "tags": [{ "id": 0,"name": "string" }], + "status":"available" +}` + func testBasicGatewayApplication(t *testing.T, e engine.Engine) { defer api.ClearResources() test.Drain("9096") @@ -145,3 +185,74 @@ func TestHandlerRoutingIntegrationJSON(t *testing.T) { assert.Nil(t, err) testHandlerRoutingApplication(t, e) } + +func testDefaultHTTPPattern(t *testing.T, e engine.Engine) { + defer api.ClearResources() + test.Drain("1234") + testHandler := handler{} + s := &http.Server{ + Addr: ":1234", + Handler: &testHandler, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, + } + go func() { + s.ListenAndServe() + }() + test.Pour("1234") + defer s.Shutdown(context.Background()) + + test.Drain("9096") + err := e.Start() + assert.Nil(t, err) + defer func() { + err := e.Stop() + assert.Nil(t, err) + }() + test.Pour("9096") + + transport := &http.Transport{ + MaxIdleConns: 1, + } + defer transport.CloseIdleConnections() + client := &http.Client{ + Transport: transport, + } + request := func() string { + req, err := http.NewRequest(http.MethodGet, "http://localhost:9096/pets/1", nil) + assert.Nil(t, err) + response, err := client.Do(req) + assert.Nil(t, err) + body, err := ioutil.ReadAll(response.Body) + assert.Nil(t, err) + response.Body.Close() + return string(body) + } + + body := request() + assert.NotEqual(t, 0, len(body)) +} + +func TestDefaultHttpPatternAPI(t *testing.T) { + if testing.Short() { + t.Skip("skipping Basic Gateway API integration test in short mode") + } + + e, err := DefaultHTTPPattern() + assert.Nil(t, err) + testDefaultHTTPPattern(t, e) +} + +func TestDefaultHttpPatternJSON(t *testing.T) { + if testing.Short() { + t.Skip("skipping Basic Gateway JSON integration test in short mode") + } + data, err := ioutil.ReadFile(filepath.FromSlash("./json/default-http-pattern/flogo.json")) + assert.Nil(t, err) + cfg, err := engine.LoadAppConfig(string(data), false) + assert.Nil(t, err) + e, err := engine.New(cfg) + assert.Nil(t, err) + testDefaultHTTPPattern(t, e) +} diff --git a/examples/json/default-http-pattern/README.md b/examples/json/default-http-pattern/README.md index 7cd5b19..6021777 100644 --- a/examples/json/default-http-pattern/README.md +++ b/examples/json/default-http-pattern/README.md @@ -1,6 +1,33 @@ # Gateway using Default Http Pattern This recipe is a gateway using the defult http pattern which uses JWT, Rate Limiter, and Circuit Breaker. +#Circuit Breaker Service: +| Name | Type | Description | +|:-----------|:--------|:--------------| +| mode | string | The tripping mode: 'a' for contiguous errors, 'b' for errors within a time period, 'c' for contiguous errors within a time period, and 'd' for a probabilistic smart circuit breaker mode. Defaults to mode 'a' | +| threshold | number | The number of errors required for tripping| +| period | number | Number of seconds in which errors have to occur for the circuit breaker to trip. Applies to modes 'b' and 'c'| +| timeout | number | Number of seconds that the circuit breaker will remain tripped. Applies to modes 'a', 'b', 'c'| + + +#Rate Limiter +| Name | Type | Description | +|:-----------|:--------|:--------------| +| limit | string | Limit can be specifed in the format of "limit-period". Valid periods are 'S', 'M' & 'H' to represent Second, Minute & Hour. Example: "10-S" represents 10 request/second | + + +#JWT +| Name | Type | Description | +|:-----------|:--------|:--------------| +| token | string | The raw token | +| key | string | The key used to sign the token | +| signingMethod | string | The signing method used (HMAC, ECDSA, RSA, RSAPSS) | +| issuer | string | The 'iss' standard claim to match against | +| subject | string | The 'sub' standard claim to match against | +| audience | string | The 'aud' standard claim to match against | + + + ## Installation * Install [Go](https://golang.org/) * Install the flogo [cli](https://github.com/project-flogo/cli) diff --git a/examples/json/default-http-pattern/flogo.json b/examples/json/default-http-pattern/flogo.json index d73a847..97959a8 100644 --- a/examples/json/default-http-pattern/flogo.json +++ b/examples/json/default-http-pattern/flogo.json @@ -33,7 +33,13 @@ "jwtIss": "Mashling", "jwtSub": "tempuser@mail.com", "useCircuitBreaker": true, - "backendUrl": "http://localhost:1234/pets" + "backendUrl": "http://localhost:1234/pets", + "mode": "a", + "threshold": 2, + "timeout": 60, + "period": 60, + "method": "POST", + "content": "{\"name\":\"sally\"}" } } ] diff --git a/internal/pattern/DefaultHttpPattern.json b/internal/pattern/DefaultHttpPattern.json index ca13554..1928a53 100644 --- a/internal/pattern/DefaultHttpPattern.json +++ b/internal/pattern/DefaultHttpPattern.json @@ -25,19 +25,27 @@ "service": "CircuitBreaker" }, { - "if": "$.conf.useJWT == false || $.JWTValidator.outputs.valid == true", - "service": "HttpBackend", - "halt": "($.HttpBackend.error != nil) && !error.isneterror($.HttpBackend.error)" + "if": "($.conf.useJWT == false || $.JWTValidator.outputs.valid == true) && $.conf.method == 'GET'" , + "service": "HttpBackendA", + "halt": "($.HttpBackendA.error != nil) && !error.isneterror($.HttpBackendA.error)" }, { - "if": "$.conf.useCircuitBreaker == true && $.HttpBackend.error != nil", + "if": "($.conf.useJWT == false || $.JWTValidator.outputs.valid == true) && ($.conf.method == 'PUT' || $.conf.method == 'POST' || $.conf.method == 'PATCH')", + "service": "HttpBackendB", + "input": { + "content": "=$.conf.content" + }, + "halt": "($.HttpBackendB.error != nil) && !error.isneterror($.HttpBackendB.error)" + }, + { + "if": "$.conf.useCircuitBreaker == true && (($.HttpBackendA.error != nil && $.conf.method == 'GET')|| ($.HttpBackendB.error != nil && ($.conf.method == 'PUT' || $.conf.method == 'POST' || $.conf.method == 'PATCH')))", "service": "CircuitBreaker", "input": { "operation": "counter" } }, { - "if": "$.conf.useCircuitBreaker == true && $.HttpBackend.error == nil", + "if": "$.conf.useCircuitBreaker == true && (($.HttpBackendA.error == nil && $.conf.method == 'GET')|| ($.HttpBackendB.error == nil && ($.conf.method == 'PUT' || $.conf.method == 'POST' || $.conf.method == 'PATCH')))", "service": "CircuitBreaker", "input": { "operation": "reset" @@ -77,10 +85,26 @@ } }, { + "if": "($.conf.useJWT == false || $.JWTValidator.outputs.valid == true) && $.conf.method == 'GET'", "error": false, "output": { "code": 200, - "data": "=$.HttpBackend.outputs.data" + "data": "=$.HttpBackendA.outputs.data" + } + }, + { + "if": "($.conf.useJWT == false || $.JWTValidator.outputs.valid == true) && ($.conf.method == 'PUT' || $.conf.method == 'POST' || $.conf.method == 'PATCH')", + "error": false, + "output": { + "code": 200, + "data": "=$.HttpBackendB.outputs.data" + } + }, + { + "error": true, + "output": { + "code": 400, + "data": "Error" } } ], @@ -103,15 +127,27 @@ "description": "Circuit breaker service", "ref": "github.com/project-flogo/microgateway/activity/circuitbreaker", "settings": { - "mode": "a" + "mode": "=$.conf.mode", + "threshold": "=$.conf.threshold", + "timeout": "=$.conf.timeout", + "period": "=$.conf.period" + } + }, + { + "name": "HttpBackendA", + "description": "Make an http call to your backend", + "ref": "github.com/project-flogo/contrib/activity/rest", + "settings": { + "method": "=$.conf.method", + "uri": "=$.conf.backendUrl" } }, { - "name": "HttpBackend", + "name": "HttpBackendB", "description": "Make an http call to your backend", "ref": "github.com/project-flogo/contrib/activity/rest", "settings": { - "method": "GET", + "method": "=$.conf.method", "uri": "=$.conf.backendUrl" } } diff --git a/internal/pattern/assets.go b/internal/pattern/assets.go index 6200614..2b2333f 100644 --- a/internal/pattern/assets.go +++ b/internal/pattern/assets.go @@ -1,7 +1,9 @@ -// Code generated by go-bindata. DO NOT EDIT. @generated +// Code generated by go-bindata. // sources: // DefaultHttpPattern.json // DefaultChannelPattern.json +// DO NOT EDIT! + package pattern import ( @@ -67,7 +69,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _defaulthttppatternJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x56\x4b\x6f\xdb\x38\x10\xbe\xfb\x57\x4c\x08\x23\xd8\x00\x89\x9c\x7d\x9c\x0c\xf8\x90\x64\x83\xdd\xcd\x36\x40\x91\xba\xcd\xa1\xe8\x81\xa2\xc6\x12\x63\x99\x54\xc9\xa1\x5d\x37\xf1\x7f\x2f\x44\x4b\x8e\xa4\xc8\xb2\x13\x17\xbd\xe4\xc1\x79\x7d\x33\xf3\xcd\x68\x1e\x7b\x00\x4c\xf1\x19\xb2\x21\xb0\xbf\x71\xc2\x5d\x4a\xff\x12\x65\xef\x39\x11\x1a\xc5\x4e\x73\xb9\x25\xcc\x2c\x1b\xc2\xe7\x1e\x00\xc0\xa3\xff\x09\xc0\xe4\x24\x37\xea\x07\x42\xab\x49\xe0\x2c\xde\x71\xc2\x77\x72\x26\x09\x0d\x8c\x46\x40\xc6\xa1\xb7\xf7\xca\x16\xcd\x5c\x0a\x1f\xa6\xa2\xf7\x2c\x97\x2a\x73\xc4\x86\x1b\xef\x00\x8c\xf4\x14\x55\x6e\x10\xa7\x3a\xe4\x29\x2b\x24\x2b\xff\x7b\x75\xda\x0d\xe6\xe6\x7e\xdc\x09\xe2\xe6\x7e\xfc\x89\xa7\x32\xe2\xa4\xf7\x44\x31\xea\x07\x19\x5f\xa6\x9a\x47\x41\x82\x3c\x42\x63\x83\x0b\x47\x89\x36\xf2\x3b\x27\xa9\xd5\xc6\x4b\x1e\x48\xc6\x4a\xaa\xf8\x16\x29\xd1\x51\x61\xec\x91\x3d\x2c\xe8\x43\x4d\x56\x31\x9a\xe2\xb2\xa1\xfa\x3f\x2e\xab\x0a\xdc\x35\x7d\x5d\xb8\x9a\x07\x69\x6d\x43\xe1\x3f\x6b\x6b\xb8\x5c\xd8\x44\xe3\xc2\xd7\x15\xf6\x4a\x1a\xe1\x24\x5d\x1a\xe4\xd3\x1d\x8d\xae\xab\xb2\xd7\xf4\x6d\xc2\x53\x8b\xf0\xf4\x04\xfd\xa0\xda\xa9\x40\x3b\xca\x1c\xd9\x60\x9e\xbf\x74\x06\xcf\x59\x7c\xc9\xc5\x14\xd5\x73\x89\x58\xc2\xd3\xbc\xbd\xec\xb7\x7e\x50\x91\x07\x68\x8c\x36\x70\x34\x02\x25\xd3\x13\x38\x3e\x86\x23\xff\x12\x48\xab\x90\xfc\x9f\x6d\x06\x27\xfb\x65\xd4\x5e\xb0\x3c\xca\x76\x10\xfb\x94\xb3\x8b\xb4\x3a\x43\xb3\x26\xe5\x10\x98\xd0\x4e\x51\x59\xff\xc3\xda\xbc\x0d\xf5\xe8\xe7\xa3\x36\x68\x91\x1a\x98\x7b\x00\x5f\xfc\x46\x32\x68\x33\xad\x2c\x76\x6c\xa5\xca\x96\xd9\xb0\x26\xcd\xff\xbf\x43\x2e\x12\x6c\x21\x8f\x4f\x85\x0d\xfd\xeb\xe6\x71\x6d\x5a\xc7\x29\x74\x94\xa7\xf6\xd7\xf9\x9f\x95\xd1\x8a\x38\xf1\x9a\x9a\x5f\x9c\x9c\x9c\x2d\x77\x1e\x78\x38\x70\xfd\x4d\x20\x46\x18\xc1\x19\x8c\x13\x84\xa2\x54\xb0\xd4\x0e\x12\x3e\x47\x30\xf8\xd5\xa1\x25\x8c\x40\x5a\xd0\x73\x34\x40\x09\x02\x4f\x53\xbd\xc0\x08\x7c\x0a\x01\xdb\x44\x59\xbd\x75\x2b\xae\x5b\xd9\x3d\x5c\x7e\x0a\x0f\x29\xd0\xef\x3b\x0a\xe4\x3d\xde\xa2\xb5\x3c\xc6\x62\x31\xb5\x22\xaa\xe9\x9d\x56\x3d\xcc\xd7\xba\x52\xab\x3d\xdc\xbc\x54\x7e\x63\x1d\xbb\xa6\xa3\x2e\xdb\xc4\x26\x23\xb3\xec\xd7\xd0\xae\xf4\xc8\xc4\x1a\x0a\x84\x05\xce\x02\xc3\xbe\x59\x97\x7e\x3c\x0d\xf6\x81\xf6\xc7\xf9\xf9\x4b\x68\x79\x37\xaa\x1b\xa3\x2c\x88\x17\x6f\x99\xef\x62\x28\x5a\xc6\xbb\xbc\x55\x5a\x8f\x88\x08\xad\x30\x32\x2b\x57\x88\x1f\xba\xb4\xa9\x64\xd0\x37\x33\x96\x94\xb8\x30\x10\x7a\x36\xc8\x8c\x7e\x40\x41\x67\x93\x54\xc7\x7a\x30\x93\xc2\xe8\x98\x13\x2e\xf8\x72\xc0\x05\xc9\xb9\xa4\xe5\xc0\x70\xc2\x17\xae\x2c\x12\x49\x15\xdb\x7a\x31\xbc\x5a\xf5\x33\x6b\x4a\xac\xdd\x2b\xb8\x4c\xad\xfd\x34\x69\xe4\x56\x68\x20\x58\x3d\x43\xf0\x47\x8a\x3d\x34\xc7\x87\x05\xb5\x7f\xd2\x4a\x64\xdb\x76\x79\x03\xdb\x55\x83\x76\xe5\xd7\xe0\x40\x78\x05\x9b\xc3\x66\xf4\xf6\x2e\xcc\xd6\x94\x64\x4d\x8e\x6d\x49\xad\xf5\x5c\x68\xe4\x75\xcb\xa7\x08\x5c\x41\x42\x94\x81\xe0\x69\x0a\xa4\xf3\xbd\x6d\x20\x6c\x5a\xee\xca\x50\x68\x45\x46\x86\x15\x7e\xa1\xa5\x9d\x29\x6d\xce\xc9\x7f\xae\xc7\xd5\xb3\xce\x19\x59\xe5\x5b\x81\xe6\xa3\x69\xde\xcc\xf9\x7c\xf5\x56\xbd\x1f\x01\x00\x00\xff\xff\x3b\xd8\x78\xbf\xf5\x0b\x00\x00") +var _defaulthttppatternJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\x58\x5f\x6f\xdb\x36\x10\x7f\xf7\xa7\xb8\x0a\x41\x53\x03\xa9\x92\xfd\x79\x32\xe0\x87\x38\x0b\xd6\x75\x0b\x56\xb4\xee\xfa\x30\xec\x81\x96\xce\x16\x63\x8a\xd4\xc8\xa3\x33\xaf\xc9\x77\x1f\x44\x49\x0e\xf5\xc7\xb2\x9d\xc0\x01\x86\xbe\x24\x11\xef\x78\xfc\xdd\xef\x8e\x77\xbc\x7c\x1d\x00\x04\x92\xa5\x18\x8c\x20\xf8\x09\xe7\xcc\x0a\x7a\x47\x94\x7d\x60\x44\xa8\x65\x70\x96\xcb\x0d\x61\x66\x82\x11\xfc\x39\x00\x00\xf8\xea\x7e\x02\x04\x7c\x9e\x6f\x3a\x09\x23\x25\xe7\xa1\x35\xf8\x91\x11\xfe\xc6\x53\x4e\xa8\x61\x3c\x06\xd2\x16\xdd\x7e\xa7\x6c\x50\xaf\x78\xe4\x8e\xf1\xf4\x1e\xe5\x5c\x66\x96\x82\xd1\xc6\x3a\x40\x40\x6a\x89\x32\xdf\xb0\x10\x6a\xc6\x44\x50\x4a\x1e\xdc\xef\x87\xb3\x7e\x30\xef\xbf\x4c\x7b\x41\xbc\xff\x32\xfd\x83\x09\x1e\x33\x52\x7b\xa2\x18\x9f\x84\x19\x5b\x0b\xc5\xe2\x30\x41\x16\xa3\x36\xe1\xa5\xa5\x44\x69\xfe\x2f\x23\xae\xe4\xc6\x4a\x7e\x10\x5f\x48\x2e\x17\x37\x48\x89\x8a\xcb\xcd\x0e\xd9\xed\x1d\x7d\xaa\xc9\xbc\x4d\x4b\x5c\x37\x54\x7f\xc5\xb5\xaf\xc0\x6c\xd3\xd6\xa5\xad\x59\xe0\xc6\x34\x14\x7e\x31\xa6\x86\xcb\xce\x9a\x68\xec\xec\x30\x62\xaf\xb8\x8e\x2c\xa7\x89\x46\xb6\xdc\x11\xe8\xba\x6a\xd0\x63\xfe\x4d\x2b\x70\x73\x26\x0c\xc2\xfd\x3d\x9c\x84\x7e\xa8\x42\x65\x29\xb3\x64\xc2\x55\xbe\x52\x9d\x3e\x84\xd7\xaf\xa1\x34\x91\x3a\x5e\x73\xc9\xe9\xcf\xd7\xd3\xd3\x00\xba\x90\xe5\x29\x3e\x61\xd1\x12\x65\x7c\xf9\x08\x3d\x61\x82\x4a\x34\xbe\x42\x88\x5a\x2b\x0d\xaf\xc6\x20\xb9\x70\x47\xbd\x72\x2b\x21\x37\x12\xc9\xfd\xd9\xb9\x63\x78\x6c\x8f\xdf\xb4\x5d\xfe\xf0\x79\x7a\x5a\xd8\x68\x49\x7e\xff\xb4\x55\x74\x39\xbd\x7a\x77\x3a\xec\x8c\xa1\xe7\xd6\xa4\xf7\x9e\x44\x4a\x12\x4a\xf2\xd3\xab\x5a\xaa\xf2\x6b\x07\xd1\x93\x83\x89\x9e\xec\x41\xf4\xae\xcc\x75\x44\xf6\x45\x7c\x7b\x6e\x0d\xef\xef\xa1\xcf\x85\x23\xc4\x68\xd8\x1d\xa5\xc6\x4d\xeb\x8b\x93\xca\x50\x17\xf5\x6a\x94\x07\xcd\x4a\xaa\xae\xe6\xf3\x2a\x40\x0f\x8f\xe3\x27\xf3\x38\xfe\x9f\xf0\xa8\xd1\x20\x35\x58\x1c\x00\xfc\xe5\xda\xa7\x46\x93\x29\x69\xb0\xa7\x85\x7a\x2d\x71\x73\xdf\x45\xfe\xfd\x11\x59\x94\x60\xdc\x2e\xb3\x8e\x9f\x60\xe4\x56\x37\x8b\xc5\xd6\xe6\xbd\x8c\x73\xd7\x7e\xbc\xf8\xc1\xeb\x03\x31\x23\x56\x53\x73\x5d\x9e\x91\x35\x55\x83\x06\x07\x07\xae\xff\x89\x10\x63\x8c\xe1\x2d\x4c\x13\x84\x92\x2a\x58\x2b\x0b\x09\x5b\x21\x68\xfc\xdb\xa2\x21\x8c\x81\x1b\x50\x2b\xd4\x40\x09\x02\x13\x42\xdd\x61\x0c\xce\x85\x30\xd8\x9c\xf2\xf0\xd4\x16\x5e\xe4\x4e\x7f\x59\x74\xf5\xf3\x39\x04\x7d\xb7\x83\x20\x67\xf1\x06\x8d\x61\x0b\x2c\xcb\x5c\x27\xa2\x9a\xde\x99\x6f\x61\x55\xe8\x72\x25\xf7\x30\xd3\x56\x7e\x22\x8f\xdb\xef\xeb\x49\x58\x97\x6d\xce\x26\xcd\xb3\xec\x65\xd2\xae\xb2\x18\x44\x05\x14\x98\x95\x38\x4b\x0c\x87\x79\x7d\xc4\x87\x44\x8b\x03\x67\x79\x1f\x12\xbe\xbf\xb8\x68\x93\x90\xc7\xbd\x56\x2b\x2b\x40\x4e\xfe\x42\xae\x1e\xed\x05\x71\x14\x8e\x26\x07\x70\x74\x78\xa2\x76\x9d\x7f\xed\xac\x6c\xa9\xeb\x65\x31\xec\x28\xeb\xd5\x40\xd5\x39\xe9\xc4\x68\x22\xcd\xb3\xaa\x75\xb8\x62\x2b\x9a\x4a\x1a\x5d\x8c\x17\x9c\x12\x3b\x0b\x23\x95\x9e\x67\x5a\xdd\x62\x44\x6f\xe7\x42\x2d\xd4\x79\xca\x23\xad\x16\x8c\xf0\x8e\xad\xcf\x59\x44\x7c\xc5\x69\x7d\xae\x19\x61\xcb\x94\x41\x22\x2e\x17\xa6\xee\xb6\x53\xf3\x1f\x6b\xba\xc2\xda\xcf\x6b\xe5\x5a\xf7\xfc\xd4\xf0\xad\xd4\x40\x30\x2a\x45\x70\x93\x94\x79\xae\x8f\xb7\x77\xd4\xfd\xdc\xab\x90\x6d\xeb\xe1\x0d\x6c\x57\x8d\x72\x53\xbd\x02\x9e\x09\xaf\xac\x62\xb3\xe6\xe9\xdd\x51\x48\x8b\xe4\xdb\x04\xc1\x7d\x7b\x79\x48\x89\x46\x93\x28\x51\x9b\xfb\x1e\x17\x7d\x4d\x9e\xa2\xb2\xb5\x88\x56\x4b\x9e\x56\x86\x9a\xd7\x07\xd2\x72\x65\xaf\x98\x77\x4f\x4d\x0d\x5e\x6f\xd8\x12\x81\x49\x48\x88\x32\x88\x98\x10\x40\x2a\x7f\x2f\x68\x98\x15\x5b\xf7\x67\x38\x9f\x1f\x34\x9f\x79\xf9\x8d\x86\x76\x52\xda\x9a\xb9\xd3\xd6\xa4\x6d\x35\xf7\x15\x4a\x60\x9f\xf5\x8e\xff\x31\x74\xf0\x30\xf9\x26\x78\xc8\x4b\xde\xe0\x61\xf0\x5f\x00\x00\x00\xff\xff\x30\x31\xfa\x4b\x2d\x12\x00\x00") func defaulthttppatternJsonBytes() ([]byte, error) { return bindataRead( @@ -82,7 +84,7 @@ func defaulthttppatternJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "DefaultHttpPattern.json", size: 3061, mode: os.FileMode(420), modTime: time.Unix(1544138209, 0)} + info := bindataFileInfo{name: "DefaultHttpPattern.json", size: 4653, mode: os.FileMode(420), modTime: time.Unix(1549574923, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -102,7 +104,7 @@ func defaultchannelpatternJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "DefaultChannelPattern.json", size: 2184, mode: os.FileMode(420), modTime: time.Unix(1541190653, 0)} + info := bindataFileInfo{name: "DefaultChannelPattern.json", size: 2184, mode: os.FileMode(420), modTime: time.Unix(1549486667, 0)} a := &asset{bytes: bytes, info: info} return a, nil }