Skip to content

Tyk 1.8 and Tyk Dashboard 0.9.6

Compare
Choose a tag to compare
@lonelycode lonelycode released this 26 Aug 09:37
· 4312 commits to master since this release

Tyk v1.8

Large update to Tyk, major improvements and new features.
New: Dashbaord also has FreeBSD versions

Full Changelog:

  • Security option added for shared nodes: Set disable_virtual_path_blobs=true to stop virtual paths from loading blob fields

  • Added session meta data variables to transform middleware:

    You can reference session metadata attached to a key in the header injector using:

    $tyk_meta.KEY_NAME
    

    And in the body transform template through:

    ._tyk_meta.KEYNAME
    

    You must enable sesison parsing in the TemplateData of the body tranform entry though by adding:

    "enable_session": true
    

    To the path entry

  • Added CORS support, add a CORS section to your API definition:

     CORS: {
        enable: false,
        allowed_origins: [
          "http://foo.com"
        ]
     },
    
  • Full CORS Options are:

    CORS struct {
        Enable             bool     `bson:"enable" json:"enable"`
        AllowedOrigins     []string `bson:"allowed_origins" json:"allowed_origins"`
        AllowedMethods     []string `bson:"allowed_methods" json:"allowed_methods"`
        AllowedHeaders     []string `bson:"allowed_headers" json:"allowed_headers"`
        ExposedHeaders     []string `bson:"exposed_headers" json:"exposed_headers"`
        AllowCredentials   bool     `bson:"allow_credentials" json:"allow_credentials"`
        MaxAge             int      `bson:"max_age" json:"max_age"`
        OptionsPassthrough bool     `bson:"options_pasthrough" json:"options_pasthrough"`
        Debug              bool     `bson:"debug" json:"debug"`
    } `bson:"CORS" json:"CORS"`
    
  • Fixed cache bug

  • When using node segments, tags will be transferred into analytics data as well as any token-level tags, so for example, you could tag each node independently, and then view the trafic that went through those nodes by ID or group them in aggregate

  • You can now segment gateways that use a DB-backed configurations for example if you vae APIs in different regions, or only wish to service a segment of your APIs (e.g. "Health APIs", "Finance APIs"). So you can have a centralised API registry using the dashboard, and then Tag APIs according to their segment(s), then configure your Tyk nodes to only load those API endpoints, so node 1 may only serve health APIs, while node 2 might serve a mixture and node 3 will serve only finance APIs. To enable, simply configure your node and add to tyk.conf and host_manager.conf (if using):

    "db_app_conf_options": {
            "node_is_segmented": false,
             "tags": ["test2"]
       }
    
  • You will need to add a tags: [] sectino to your API definition in the DB to enable this feature, or set it in the dashboard.

  • Dynamic endpoints support response middleware

  • Dynamic endpoints support caching

  • Dynamic endpoints also count towards analytics

  • JSVM now has access to a TykBatchRequest function to make batch requests in virtual paths. Use case: Create a virtual endpoint that interacts with multiple upstream APIs, gathers the data, processes the aggregates somehow and returns them as a single body. This can then be cached to save on load.

  • Added virtual path support, you can now have a JS Function respond to a request, makes mocking MUCh more flexible, TODO: expose batch methods to JSVM. To activate, add to extended paths:

    virtual: [
        {
          response_function_name: "thisTest",
          function_source_type: "file",
          function_source_uri: "middleware/testVirtual.js",
          path: "virtualtest",
          method: "GET",
          use_session: true
        }
    ]
    
  • Virtual endpoint functions are pretty clean:

    function thisTest(request, session, config) {
        log("Virtual Test running")
    
        log("Request Body: ")
        log(request.Body)
    
        log("Session: ")
        log(session)
    
        log("Config:")
        log(config)
    
        log("param-1:")
        log(request.Params["param1"])
    
        var responseObject = {
            Body: "THIS IS A  VIRTUAL RESPONSE"
            Headers: {
                "test": "virtual", 
                "test-2": "virtual"
            },
            Code: 200
        }
    
        return TykJsResponse(responseObject, session.meta_data)
    
    }
    log("Virtual Test initialised")
    
  • Added refresh tests for OAuth

  • URL Rewrite in place, you can specify URLs to rewrite in the extended_paths seciton f the API Definition like so:

    "url_rewrites": [
        {
          "path": "virtual/{wildcard1}/{wildcard2}",
          "method": "GET",
          "match_pattern": "virtual/(.*)/(\d+)",
          "rewrite_to": "new-path/id/$2/something/$1"
        }
      ]
    
  • You can now add a "tags":["tag1, "tag2", tag3"] field to token and policy definitions, these tags are transferred through to the analytics record when recorded. They will also be available to dynamic middleware. This means there is more flexibility with key ownership and reporting by segment.

  • Cleaned up server output, use --debug to see more detailed debug data. Keeps log size down

  • TCP Errors now actually raise an error

  • Added circuit breaker as a path-based option. To enable, add a new sectino to your versions extended_paths list:

    circuit_breakers: [
        {
          path: "get",
          method: "GET",
          threshold_percent: 0.5,
          samples: 5,
          return_to_service_after: 60
        }
    

    ]

Circuit breakers are individual on a singlie host, they do not centralise or pool back-end data, this is for speed. This means that in a load balanced environment where multiple Tyk nodes are used, some traffic can spill through as other nodes reach the sampling rate limit. This is for pure speed, adding a redis counter layer or data-store on every request to a servcie would jsut add latency.

Circuit breakers use a thresh-old-breaker pattern, so of sample size x if y% requests fail, trip the breaker.

The circuit breaker works across hosts (i.e. if you have multiple targets for an API, the samnple is across all upstream requests)

When a circuit breaker trips, it will fire and event: BreakerTriggered which you can define actions for in the event_handlers section:

```
event_handlers: {
    events: {
      BreakerTriggered: [
        {
          handler_name: "eh_log_handler",
          handler_meta: {
            prefix: "LOG-HANDLER-PREFIX"
          }
        },
        {
          handler_name: "eh_web_hook_handler",
          handler_meta: {
            method: "POST",
            target_path: "http://posttestserver.com/post.php?dir=tyk-event-test",
            template_path: "templates/breaker_webhook.json",
            header_map: {
              "X-Tyk-Test-Header": "Tyk v1.BANANA"
            },
            event_timeout: 10
          }
        }
      ]
    }
  },
```

Status codes are:

```
// BreakerTripped is sent when a breaker trips
BreakerTripped = 0

// BreakerReset is sent when a breaker resets
BreakerReset = 1
```
  • Added round-robin load balancing support, to enable, set up in the API Definition under the proxy section:

    ...
    "enable_load_balancing": true,
    "target_list": [
        "http://server1", 
        "http://server2", 
        "http://server3"
    ],
    ...
    
  • Added REST-based Servcie discovery for both single and load balanced entries (tested with etcd, but anything that returns JSON should work), to enable add a service discovery section to your Proxy section:

    // Solo
    service_discovery : {
      use_discovery_service: true,
      query_endpoint: "http://127.0.0.1:4001/v2/keys/services/single",
      use_nested_query: true,
      parent_data_path: "node.value",
      data_path: "hostname",
      port_data_path: "port",
      use_target_list: false,
      cache_timeout: 10
    },
    
    
    // With LB
    "enable_load_balancing": true,
    service_discovery: {
      use_discovery_service: true,
      query_endpoint: "http://127.0.0.1:4001/v2/keys/services/multiobj",
      use_nested_query: true,
      parent_data_path: "node.value",
      data_path: "array.hostname",
      port_data_path: "array.port",
      use_target_list: true,
      cache_timeout: 10
    },
    
  • For service discovery, multiple assumptions are made:

    • The response data is in JSON
    • The response data can have a nested value set that will be an encoded JSON string, e.g. from etcd:
    $ curl -L http://127.0.0.1:4001/v2/keys/services/solo
    
    {
        "action": "get",
        "node": {
            "key": "/services/single",
            "value": "{\"hostname\": \"http://httpbin.org\", \"port\": \"80\"}",
            "modifiedIndex": 6,
            "createdIndex": 6
        }
    }
    
    $ curl -L http://127.0.0.1:4001/v2/keys/services/multiobj
    
    {
        "action": "get",
        "node": {
            "key": "/services/multiobj",
            "value": "{\"array\":[{\"hostname\": \"http://httpbin.org\", \"port\": \"80\"},{\"hostname\": \"http://httpbin.org\", \"port\": \"80\"}]}",
            "modifiedIndex": 9,
            "createdIndex": 9
        }
    }
    

    Here the key value is actually an encoded JSON string, which needs to be decoded separately to get to the data.

    • In some cases port data will be separate from host data, if you specify a port_data_path, the values will be zipped together and concatenated into a valid proxy string.
    • If use_target_list is enabled, then enable_load_balancing msut also be enabled, as Tyk will treat the list as a target list.
    • The nested data object in a service registry key MUST be a JSON Object, not just an Array.
  • Fixed bug where version parameter on POST requests would empty request body, streamlined request copies in general.

  • it is now possible to use JSVM middleware on Open (Keyless) APIs

  • It is now possible to configure the timeout parameters around the http server in the tyk.conf file:

    "http_server_options": {
        "override_defaults": true,
        "read_timeout": 10,
        "write_timeout": 10
    }
    
    • It is now possible to set hard timeouts on a path-by-path basis, e.g. if you have a long-running microservice, but do not want to hold up a dependent client should a query take too long, you can enforce a timeout for that path so the requesting client is not held up forever (or maange it's own timeout). To do so, add this to the extended_paths section of your APi definition:

      ...
      extended_paths: {
          ...
          transform_response_headers: [],
          hard_timeouts: [
            {
              path: "delay/5",
              method: "GET",
              timeout: 3
            }
          ]
      }
      ...