Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
14 changes: 14 additions & 0 deletions advanced-configuration.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: "Advanced Configuration"
sidebarTitle: "Overview"
order: 60
---

This section covers less common settings, some of which require custom code. Areas include:

* [Transform Traffic](/advanced-configuration/transform-traffic). How to use request and response headers and bodies, URL rewriting, request method transforms, the validation of JSON, JQ transforms and how to use our API Endpoint Designer.
* [Integration Options](/advanced-configuration/integrate). How you can integrate Tyk with 3rd party providers for plugins, API Authentication, and Single Sign On.
* [Manage Multiple Environments](/advanced-configuration/manage-multiple-environments). How to configure Tyk Multi-Cloud and Self-Managed installations to work with multiple geographically or physically separate installations.
* [WebSockets](/advanced-configuration/websockets). How to use WebSockets connections with Tyk.
* [Log Data](/log-data). How to configure your logs, and 3rd party integration with Sentry, Logstash, Graylog ans Syslog.
* [Error Templates](/advanced-configuration/error-templates). How to create custom HTTP 500 error templates.
299 changes: 299 additions & 0 deletions advanced-configuration/compose-apis/demo-virtual-endpoint.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
---
title: "Virtual Endpoint examples"
'og:description': "Examples of Virtual Endpoints"
sidebarTitle: "Examples"
tags: ['JavaScript', 'JS', 'middleware', 'scripting', 'JSVM', 'examples', 'virtual endpoint']
---

Here we offer some examples to demonstrate valid use of JavaScript within Virtual Endpoints. You can either copy and paste the JavaScript code into the code editor in the Tyk Dashboard API Designer, or create a file and place it in a subdirectory of the Tyk configuration environment (for example under the `middleware` folder in your Tyk installation).

For instruction on how to configure the Virtual Endpoint middleware for your APIs, please see the appropriate documentation for the format of API that you are using:
- [Tyk OAS API](/product-stack/tyk-gateway/middleware/virtual-endpoint-tyk-oas)
- [Tyk Classic API](/product-stack/tyk-gateway/middleware/virtual-endpoint-tyk-classic)

## Example 1: Accessing Tyk data objects

In this example, we demonstrate how you can access different [external Tyk objects](/plugins/supported-languages/javascript-middleware/middleware-scripting-guide#accessing-external-and-dynamic-data) (API request, session key, API definition).

1. Enable the Virtual Endpoint middleware on an endpoint of your API and paste this JavaScript into the API Designer (or save in a file and reference it from the middleware config):

```javascript
function myFirstVirtualHandler (request, session, config) {
log("Virtual Test running")

log("Request Body: " + request.Body)
log("Session: " + JSON.stringify(session.allowance))
log("Config: " + JSON.stringify(config.APIID))
log("param-1: " + request.Params["param1"]) // case sensitive
log("auth Header: " + request.Headers["Authorization"]) // case sensitive

var responseObject = {
Body: "VIRTUAL ENDPOINT EXAMPLE #1",
Headers: {
"x-test": "virtual-header",
"x-test-2": "virtual-header-2"
},
Code: 200
}

return TykJsResponse(responseObject, session.meta_data)
}
log("Virtual Test initialised")
```

2. Make a call to your API endpoint passing a request body, a value in the `Authorization` header and a query parameter `param1`.

3. The virtual endpoint will terminate the request and return this response:

```bash
HTTP/1.1 200 OK
Date: Thu, 29 Feb 2024 17:39:00 GMT
Server: tyk
X-Test: virtual-header
X-Test-2: virtual-header-2
Content-Length: 27
Content-Type: text/plain; charset=utf-8

VIRTUAL ENDPOINT EXAMPLE #1
```

4. The gateway logs will include:

```text
time="" level=info msg="Virtual Test running" prefix=jsvm type=log-msg
time="" level=info msg="Request Body: <your-request-body>" prefix=jsvm type=log-msg
time="" level=info msg="Session: <allowance-from-your-session-key>" prefix=jsvm type=log-msg
time="" level=info msg="Config: <your-APIID>" prefix=jsvm type=log-msg
time="" level=info msg="param-1: <your_query_parameter>" prefix=jsvm type=log-msg
time="" level=info msg="auth Header: <your-auth-header>" prefix=jsvm type=log-msg
```

## Example 2: Accessing custom attributes in the API Definition

You can add [custom attributes](/plugins/supported-languages/javascript-middleware/middleware-scripting-guide#adding-custom-attributes-to-the-api-definition) to the API definition and access these from within your Virtual Endpoint.

1. Add the following custom attributes to your API definition:

```json
{
"string": "string",
"map": {
" key": 3
},
"num": 4
}
```

2. Enable the Virtual Endpoint middleware on an endpoint of your API and paste this JavaScript into the API Designer (or save in a file and reference it from the middleware config):

```js
function mySecondVirtualHandler (request, session, config) {
var responseObject = {
Body: "VIRTUAL ENDPOINT EXAMPLE #2",
Headers: {
"foo-header": "bar",
"map-header": JSON.stringify(config.config_data.map),
"string-header": config.config_data.string,
"num-header": JSON.stringify(config.config_data.num)
},
Code: 200
}
return TykJsResponse(responseObject, session.meta_data)
}
```

3. Make a call to your API endpoint.

4. The virtual endpoint will terminate the request and return this response:

```bash
HTTP/1.1 200 OK
Date: Thu, 29 Feb 2024 17:29:12 GMT
Foo-Header: bar
Map-Header: {" key":3}
Num-Header: 4
Server: tyk
String-Header: string
Content-Length: 26
Content-Type: text/plain; charset=utf-8

VIRTUAL ENDPOINT EXAMPLE #2
```

## Example 3: Advanced example

In this example, every line in the script gives an example of a functionality usage, including:

- how to get form param
- how to get to a specific key inside a JSON variable
- the structure of the request object
- using `TykMakeHttpRequest` to make an HTTP request from within the virtual endpoint, and the json it returns - `.Code` and `.Body`.

```js
function myVirtualHandlerGetHeaders (request, session, config) {
rawlog("Virtual Test running")

//Usage examples:
log("Request Session: " + JSON.stringify(session))
log("API Config:" + JSON.stringify(config))

log("Request object: " + JSON.stringify(request))
log("Request Body: " + JSON.stringify(request.Body))
log("Request Headers:" + JSON.stringify(request.Headers))
log("param-1:" + request.Params["param1"])

log("Request header type:" + typeof JSON.stringify(request.Headers))
log("Request header:" + JSON.stringify(request.Headers.Location))


//Make api call to upstream target
newRequest = {
"Method": "GET",
"Body": "",
"Headers": {"location":JSON.stringify(request.Headers.Location)},
"Domain": "http://httpbin.org",
"Resource": "/headers",
"FormData": {}
};
rawlog("--- before get to upstream ---")
response = TykMakeHttpRequest(JSON.stringify(newRequest));
rawlog("--- After get to upstream ---")
log("response type: " + typeof response);
log("response: " + response);
usableResponse = JSON.parse(response);
var bodyObject = JSON.parse(usableResponse.Body);

var responseObject = {
//Body: "THIS IS A VIRTUAL RESPONSE",
Body: "yo yo",
Headers: {
"test": "virtual",
"test-2": "virtual",
"location" : bodyObject.headers.Location
},
Code: usableResponse.Code
}

rawlog("Virtual Test ended")
return TykJsResponse(responseObject, session.meta_data)
}
```

#### Running the Advanced example

You can find a Tyk Classic API definition [here](https://gist.github.com/letzya/5b5edb3f9f59ab8e0c3c614219c40747) that includes the advanced example, with the JS encoded `inline` within the middleware config for the `GET /headers` endpoint.

Create a new Tyk Classic API using that API definition and then run the following command to send a request to the API endpoint:

```bash
curl http://tyk-gateway:8080/testvirtualendpoint2/headers -H "location: /get" -v
```

This should return the following:

```bash
Trying 127.0.0.1...
TCP_NODELAY set
Connected to tyk-gateway (127.0.0.1) port 8080 (#0)
GET /testvirtualendpoint2/headers HTTP/1.1
Host: tyk-gateway:8080
User-Agent: curl/7.54.0
Accept: */*
location: /get

HTTP/1.1 200 OK
Date: Fri, 08 Jun 2018 21:53:57 GMT
**Location: /get**
Server: tyk
Test: virtual
Test-2: virtual
Content-Length: 5
Content-Type: text/plain; charset=utf-8

Connection #0 to host tyk-gateway left intact
yo yo
```

#### Checking the Tyk Gateway Logs

The `log` and `rawlog` commands in the JS function write to the Tyk Gateway logs. If you check the logs you should see the following:

```text
[Jun 13 14:45:21] DEBUG jsvm: Running: myVirtualHandlerGetHeaders
Virtual Test running
[Jun 13 14:45:21] INFO jsvm-logmsg: Request Session: {"access_rights":null,"alias":"","allowance":0,"apply_policies":null,"apply_policy_id":"","basic_auth_data":{"hash_type":"","password":""},"certificate":"","data_expires":0,"enable_detail_recording":false,"expires":0,"hmac_enabled":false,"hmac_string":"","id_extractor_deadline":0,"is_inactive":false,"jwt_data":{"secret":""},"last_check":0,"last_updated":"","meta_data":null,"monitor":{"trigger_limits":null},"oauth_client_id":"","oauth_keys":null,"org_id":"","per":0,"quota_max":0,"quota_remaining":0,"quota_renewal_rate":0,"quota_renews":0,"rate":0,"session_lifetime":0,"tags":null} type=log-msg
[Jun 13 14:45:21] INFO jsvm-logmsg: API Config:{"APIID":"57d72796c5de45e649f22da390d7df43","OrgID":"5afad3a0de0dc60001ffdd07","config_data":{"bar":{"y":3},"foo":4}} type=log-msg
[Jun 13 14:45:21] INFO jsvm-logmsg: Request object: {"Body":"","Headers":{"Accept":["*/*"],"Location":["/get"],"User-Agent":["curl/7.54.0"]},"Params":{"param1":["I-am-param-1"]},"URL":"/testvirtualendpoint2/headers"} type=log-msg
[Jun 13 14:45:21] INFO jsvm-logmsg: Request Body: "" type=log-msg
[Jun 13 14:45:21] INFO jsvm-logmsg: Request Headers:{"Accept":["*/*"],"Location":["/get"],"User-Agent":["curl/7.54.0"]} type=log-msg
[Jun 13 14:45:21] INFO jsvm-logmsg: param-1:I-am-param-1 type=log-msg
[Jun 13 14:45:21] INFO jsvm-logmsg: Request header type:[object Object] type=log-msg
[Jun 13 14:45:21] INFO jsvm-logmsg: Request header: ["/get"] type=log-msg
[Jun 13 14:45:21] INFO jsvm-logmsg: Request location type: object type=log-msg
[Jun 13 14:45:21] INFO jsvm-logmsg: Request location type: string type=log-msg
[Jun 13 14:45:21] INFO jsvm-logmsg: Request location: /get type=log-msg
--- before get to upstream ---
--- After get to upstream ---
[Jun 13 14:45:22] INFO jsvm-logmsg: response type: string type=log-msg
[Jun 13 14:45:22] INFO jsvm-logmsg: response: {"Code":200,"Body":"{\"headers\":{\"Accept-Encoding\":\"gzip\",\"Connection\":\"close\",\"Host\":\"httpbin.org\",\"Location\":\"/get\",\"User-Agent\":\"Go-http-client/1.1\"}}\n","Headers":{"Access-Control-Allow-Credentials":["true"],"Access-Control-Allow-Origin":["*"],"Content-Length":["133"],"Content-Type":["application/json"],"Date":["Wed, 13 Jun 2018 13:45:21 GMT"],"Server":["gunicorn/19.8.1"],"Via":["1.1 vegur"]},"code":200,"body":"{\"headers\":{\"Accept-Encoding\":\"gzip\",\"Connection\":\"close\",\"Host\":\"httpbin.org\",\"Location\":\"/get\",\"User-Agent\":\"Go-http-client/1.1\"}}\n","headers":{"Access-Control-Allow-Credentials":["true"],"Access-Control-Allow-Origin":["*"],"Content-Length":["133"],"Content-Type":["application/json"],"Date":["Wed, 13 Jun 2018 13:45:21 GMT"],"Server":["gunicorn/19.8.1"],"Via":["1.1 vegur"]}} type=log-msg
Virtual Test ended
[Jun 13 14:45:22] DEBUG JSVM Virtual Endpoint execution took: (ns) 191031553
```

## Example 4: Aggregating upstream calls using batch processing

One of the most common use cases for virtual endpoints is to provide some form of aggregate data to your users, combining the responses from multiple upstream service calls. This virtual endpoint function will do just that using the batch processing function from the [JavaScript API](/plugins/supported-languages/javascript-middleware/javascript-api)

```js
function batchTest(request, session, config) {
// Set up a response object
var response = {
Body: "",
Headers: {
"test": "virtual-header-1",
"test-2": "virtual-header-2",
"content-type": "application/json"
},
Code: 200
}

// Batch request
var batch = {
"requests": [
{
"method": "GET",
"headers": {
"x-tyk-test": "1",
"x-tyk-version": "1.2",
"authorization": "1dbc83b9c431649d7698faa9797e2900f"
},
"body": "",
"relative_url": "http://httpbin.org/get"
},
{
"method": "GET",
"headers": {},
"body": "",
"relative_url": "http://httpbin.org/user-agent"
}
],
"suppress_parallel_execution": false
}

log("[Virtual Test] Making Upstream Batch Request")
var newBody = TykBatchRequest(JSON.stringify(batch))

// We know that the requests return JSON in their body, lets flatten it
var asJS = JSON.parse(newBody)
for (var i in asJS) {
asJS[i].body = JSON.parse(asJS[i].body)
}

// We need to send a string object back to Tyk to embed in the response
response.Body = JSON.stringify(asJS)

return TykJsResponse(response, session.meta_data)

}
log("Batch Test initialised")
```
69 changes: 69 additions & 0 deletions advanced-configuration/compose-apis/virtual-endpoints.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: "Tyk Virtual Endpoints"
'og:description': "Virtual Endpoint middleware"
sidebarTitle: "Overview"
tags: ['virtual endpoint', 'middleware', 'per-endpoint', 'JavaScript', 'JS']
---

Tyk's Virtual Endpoint is a programmable middleware component that is invoked towards the end of the request processing chain. It can be enabled at the per-endpoint level and can perform complex interactions with your upstream service(s) that cannot be handled by one of the other middleware components.

Virtual endpoint middleware provides a serverless compute function that allows for the execution of custom logic directly within the gateway itself, without the need to proxy the request to an upstream service. This functionality is particularly useful for a variety of use cases, including request transformation, aggregation of responses from multiple services, or implementing custom authentication mechanisms.

The Virtual Endpoint is an extremely powerful feature that is unique to Tyk and provides exceptional flexibility to your APIs.

## When to use virtual endpoints

#### Aggregating data from multiple services

From a virtual endpoint, you can make calls out to other internal and upstream APIs. You can then aggregate and process the responses, returning a single response object to the originating client. This allows you to configure a single externally facing API to simplify interaction with multiple internal services, leaving the heavy lifting to Tyk rather than starting up an aggregation service within your stack.

#### Enforcing custom policies

Tyk provides a very flexible [middleware chain](/concepts/middleware-execution-order) where you can combine functions to implement the access controls you require to protect your upstream services. Of course, not all scenarios can be covered by Tyk's standard middleware functions, but you can use a virtual endpoint to apply whatever custom logic you require to optimize your API experience.

#### Dynamic Routing

With a virtual endpoint you can implement complex dynamic routing of requests made to a single external endpoint on to different upstream services. The flexibility of the virtual endpoint gives access to data within the request (including the key session) and also the ability to make calls to other APIs to make decisions on the routing of the request. It can operate as a super-powered [URL rewrite](/transform-traffic/url-rewriting) middleware.

## How virtual endpoints work

The virtual endpoint middleware provides a JavaScript engine that runs the custom code that you provide either inline within the API definition or in a source code file accessible to the Gateway. The JavaScript Virtual Machine (JSVM) provided in the middleware is a traditional ECMAScript5 compatible environment which does not offer the more expressive power of something like Node.js.

The virtual endpoint terminates the request, so the JavaScript function must provide the response to be passed to the client. When a request hits a virtual endpoint, the JSVM executes the JavaScript code which can modify the request, make calls to other APIs or upstream services, process data, and ultimately determines the response returned to the client.


<Note>
You will need to enable Tyk's JavaScript Virtual Machine by setting `enable_jsvm` to `true` in your `tyk.conf` [file](/tyk-oss-gateway/configuration#enable_jsvm) for your virtual endpoints to work.
</Note>


## Scripting virtual endpoint functions

The [middleware scripting guide](/plugins/supported-languages/javascript-middleware/middleware-scripting-guide) provides guidance on writing JS functions for your virtual endpoints, including how to access key session data and custom attributes from the API definition.

#### Function naming

The virtual endpoint middleware will invoke a named function within the JS code that you provide (either inline or in a file). Both the filename and function name are configurable per endpoint, but note that function names must be unique across your API portfolio because all plugins run in the same virtual machine. This means that you can share a single function definition across multiple endpoints and APIs but you cannot have two different functions with the same name (this applies across all [JavaScript middleware components](/plugins/supported-languages/javascript-middleware)).

Inline mode is mainly used by the dashboard to make code injection easier on multiple node deployments.

## Virtual endpoint library

We have put together a [library](https://github.com/TykTechnologies/custom-plugins#virtual-endpoints) of JS functions that you could use in your virtual endpoints. We welcome submissions from the Tyk community so if you've created a function that you think would be useful to other users, please open an issue in the Github repository and we can discuss bringing it into the library.


<Note>
Virtual endpoints are not available in Tyk Cloud Classic.
</Note>


<hr />

If you're using Tyk OAS APIs, then you can find details and examples of how to configure the virtual endpoint middleware [here](/product-stack/tyk-gateway/middleware/virtual-endpoint-tyk-oas).

If you're using Tyk Classic APIs, then you can find details and examples of how to configure the virtual endpoint middleware [here](/product-stack/tyk-gateway/middleware/virtual-endpoint-tyk-classic).

{/* proposed "summary box" to be shown graphically on each middleware page
## Virtual Endpoint middleware summary
- The Virtual Endpoint middleware is an optional stage in Tyk's API Request processing chain, sitting between the [TBC]() and [TBC]() middleware.
- The Virtual Endpoint middleware can be configured at the per-endpoint level within the API Definition and is supported by the API Designer within the Tyk Dashboard. */}
Loading
Loading