Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add extended routing capability, fixes #639 #1146

Merged
merged 3 commits into from
Dec 18, 2017
Merged

Add extended routing capability, fixes #639 #1146

merged 3 commits into from
Dec 18, 2017

Conversation

lonelycode
Copy link
Member

@lonelycode lonelycode commented Sep 22, 2017

Fixed #639

This PR adds rewrite "triggers" on top of the existing rewrite functionality. These are essentially sub-matches to allow a rewrite rule to have variations.

For example, for the URL /foo/bar/baz I want to rewrite to /fooble/barble/bazble if the query string variable culprit is set to kronk, but I want to redirect to /foozle/barzle/bazzle if the variable culprit is set to yzma.

I can do this with the new URL Rewriter as follows:

{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle"
				}
			]
		}
	]
}

Here if there is no trigger match, the rwrite will fallback to the parent rewrite_to, but if either of the other two are triggered, the rewrite target is changed.

Each trigger also sets a context variable for each match it finds, these context vars can then be used in the rewrites, so the above example with context vars could be rewritten to:

{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble?victim=$tyk_context.trigger-0-culprit-0"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle?victim=$tyk_context.trigger-1-culprit-0"
				}
			]
		}
	]
}

Trigger contexts take the format: $tyk_context.trigger-{n}-{name}-{i} where n is the trigger index in the array, nam is the rx matcher name and i is the index of that match (since querystrings and headers can be arrays of values).

The Trigger functionality supports:

  1. Header matches
  2. Query string variable/value matches
  3. Path part matches, i.e. components of the path itself
  4. Session meta data values (edit)
  5. Payload matches

For each trigger, the trigger can either use the on: any or on: all formatting, for any, if any one of the options in the trigger is true, the rewrite rule is fired. for all, all the options must be satisfied. This is limited to triggers, not groups of triggers, these will be evaluated one by one.

@lonelycode lonelycode requested review from buger and mvdan September 22, 2017 22:04
@buger
Copy link
Member

buger commented Sep 25, 2017

Nice!

@lghiur @nickReyn UI for this feature can be non-obvious, and require planning.

@lghiur
Copy link
Member

lghiur commented Sep 29, 2017

@buger @lonelycode I'm discussing about the UX with @nickReyn @ViolaMarku already, but can you please enable the dashboard api for this functionality, or let me know where will these data sit in the existing Dashboard API responses (I'm assuming in the api designer object at api_definition.versions_data.versions.{versionName}.extended_paths.url_rewrites[index]). Thanks!

@buger
Copy link
Member

buger commented Sep 29, 2017

There is no dashboard API needed here. The example you see here is part of API definitions url_rewrites object, mentioned by you.

@mvdan mvdan removed their request for review November 18, 2017 18:03
@nickReyn
Copy link

nickReyn commented Dec 8, 2017

@lonelycode @buger @lghiur I've sketched out the below for how I see this could work. Can you guys take a look and feedback thoughts pls.
screen shot 2017-12-08 at 15 40 43

In terms of how a user get's to this, i see a few options. Number 1 is my preferred.

  1. We add a button close to the Match pattern field, something like Triggers which opens a modal with the above in. This is my preferred option because the UI of the endpoint designer is already very complex, and adding more might just add complexity when we could split this functionality into a diff UI element. e.g.

screen shot 2017-12-08 at 15 32 48

  1. We add this UI to underneath the Match pattern and Rewrite to fields. However, as i said above, this just adds more complexity to an already very complex UI piece.

I'm not sure if there are different fields that need to show up if a user selects one of the other Match types, can you advise please? e.g.

Header matches
Query string variable/value matches
Path part matches, i.e. components of the path itself
Session meta data values (edit)
Payload matches

@nickReyn
Copy link

Round two of this based on feedback from @lghiur and @buger.

This will be another plugin on the Endpoint designer, because it's too complex to create it as an extension of the current URL rewrites functionality, as discussed with Leon.

Check out a simple flow here: https://www.figma.com/proto/JJXxlc0Cr7yKaHgAYWSx2kRR/Routing-rules?scaling=contain&node-id=49%3A18&redirected=1

@lonelycode

@nickReyn
Copy link

@buger @lghiur and I had some slack convos about this and decided it's not ideal to have another plugin for this. I propose we have it as a separate section below the standard url rewrites which is activated on checkbox, labelled "Enable advanced url rewrites".

The flow is here: https://www.figma.com/proto/JJXxlc0Cr7yKaHgAYWSx2kRR/Routing-rules?scaling=contain&node-id=86%3A2

@lghiur
Copy link
Member

lghiur commented Dec 18, 2017

@lonelycode @buger
I'm getting some errors when trying to build this branch

 github.com/TykTechnologies/tyk
./mw_url_rewrite.go:33: meta.Triggers undefined (type *apidef.URLRewriteMeta has no field or method Triggers)
./mw_url_rewrite.go:42: meta.Triggers undefined (type *apidef.URLRewriteMeta has no field or method Triggers)
./mw_url_rewrite.go:45: undefined: apidef.Any
./mw_url_rewrite.go:229: path.Triggers undefined (type apidef.URLRewriteMeta has no field or method Triggers)
./mw_url_rewrite.go:292: undefined: apidef.StringRegexMap
./mw_url_rewrite.go:322: undefined: apidef.StringRegexMap
./mw_url_rewrite.go:352: undefined: apidef.StringRegexMap
./mw_url_rewrite.go:380: undefined: apidef.StringRegexMap
./mw_url_rewrite.go:410: undefined: apidef.StringRegexMap

@buger
Copy link
Member

buger commented Dec 18, 2017

Will check

@buger
Copy link
Member

buger commented Dec 18, 2017

@lghiur works fine for me. How do you run it, using dev env via docker?

For some reason, it does not see changes in "apidef". If you trying to use this new fields in dashboard, you should govendor new apidef package changes.

Going to merge this server-side PR.

@buger buger merged commit e247d40 into master Dec 18, 2017
@buger buger deleted the extended-rewrites branch December 18, 2017 11:32
letzya pushed a commit that referenced this pull request Jan 11, 2018
Fixed #639 

This PR adds rewrite "triggers" on top of the existing rewrite functionality. These are essentially sub-matches to allow a rewrite rule to have variations.

For example, for the URL `/foo/bar/baz` I want to rewrite to `/fooble/barble/bazble` if the query string variable `culprit` is set to `kronk`, but I want to redirect to `/foozle/barzle/bazzle` if the variable `culprit` is set to `yzma`.

I can do this with the new URL Rewriter as follows:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle"
				}
			]
		}
	]
}
```

Here if there is no trigger match, the rwrite will fallback to the parent `rewrite_to`, but if either of the other two are triggered, the rewrite target is changed.

Each trigger also sets a context variable for each match it finds, these context vars can then be used in the rewrites, so the above example with context vars could be rewritten to:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble?victim=$tyk_context.trigger-0-culprit-0"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle?victim=$tyk_context.trigger-1-culprit-0"
				}
			]
		}
	]
}
```

Trigger contexts take the format: `$tyk_context.trigger-{n}-{name}-{i}` where `n` is the trigger index in the array, `nam` is the rx matcher name and `i` is the index of that match (since querystrings and headers can be arrays of values). 

The Trigger functionality supports:

1. Header matches
2. Query string variable/value matches
3. Path part matches, i.e. components of the path itself
4. Session meta data values 
5. Payload matches

For each trigger, the trigger can either use the `on: any` or `on: all` formatting, for `any`, if any one of the options in the trigger is true, the rewrite rule is fired. for `all`, all the options must be satisfied. This is limited to triggers, not groups of triggers, these will be evaluated one by one.
letzya pushed a commit that referenced this pull request Jan 11, 2018
Fixed #639

This PR adds rewrite "triggers" on top of the existing rewrite functionality. These are essentially sub-matches to allow a rewrite rule to have variations.

For example, for the URL `/foo/bar/baz` I want to rewrite to `/fooble/barble/bazble` if the query string variable `culprit` is set to `kronk`, but I want to redirect to `/foozle/barzle/bazzle` if the variable `culprit` is set to `yzma`.

I can do this with the new URL Rewriter as follows:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle"
				}
			]
		}
	]
}
```

Here if there is no trigger match, the rwrite will fallback to the parent `rewrite_to`, but if either of the other two are triggered, the rewrite target is changed.

Each trigger also sets a context variable for each match it finds, these context vars can then be used in the rewrites, so the above example with context vars could be rewritten to:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble?victim=$tyk_context.trigger-0-culprit-0"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle?victim=$tyk_context.trigger-1-culprit-0"
				}
			]
		}
	]
}
```

Trigger contexts take the format: `$tyk_context.trigger-{n}-{name}-{i}` where `n` is the trigger index in the array, `nam` is the rx matcher name and `i` is the index of that match (since querystrings and headers can be arrays of values).

The Trigger functionality supports:

1. Header matches
2. Query string variable/value matches
3. Path part matches, i.e. components of the path itself
4. Session meta data values
5. Payload matches

For each trigger, the trigger can either use the `on: any` or `on: all` formatting, for `any`, if any one of the options in the trigger is true, the rewrite rule is fired. for `all`, all the options must be satisfied. This is limited to triggers, not groups of triggers, these will be evaluated one by one.
@chasebish
Copy link

How can I add this feature to my APIs?

@lonelycode
Copy link
Member Author

The documentation will be released with v2.5

letzya pushed a commit that referenced this pull request Jan 12, 2018
Fixed #639

This PR adds rewrite "triggers" on top of the existing rewrite functionality. These are essentially sub-matches to allow a rewrite rule to have variations.

For example, for the URL `/foo/bar/baz` I want to rewrite to `/fooble/barble/bazble` if the query string variable `culprit` is set to `kronk`, but I want to redirect to `/foozle/barzle/bazzle` if the variable `culprit` is set to `yzma`.

I can do this with the new URL Rewriter as follows:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle"
				}
			]
		}
	]
}
```

Here if there is no trigger match, the rwrite will fallback to the parent `rewrite_to`, but if either of the other two are triggered, the rewrite target is changed.

Each trigger also sets a context variable for each match it finds, these context vars can then be used in the rewrites, so the above example with context vars could be rewritten to:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble?victim=$tyk_context.trigger-0-culprit-0"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle?victim=$tyk_context.trigger-1-culprit-0"
				}
			]
		}
	]
}
```

Trigger contexts take the format: `$tyk_context.trigger-{n}-{name}-{i}` where `n` is the trigger index in the array, `nam` is the rx matcher name and `i` is the index of that match (since querystrings and headers can be arrays of values).

The Trigger functionality supports:

1. Header matches
2. Query string variable/value matches
3. Path part matches, i.e. components of the path itself
4. Session meta data values
5. Payload matches

For each trigger, the trigger can either use the `on: any` or `on: all` formatting, for `any`, if any one of the options in the trigger is true, the rewrite rule is fired. for `all`, all the options must be satisfied. This is limited to triggers, not groups of triggers, these will be evaluated one by one.
letzya pushed a commit that referenced this pull request Jan 12, 2018
Fixed #639

This PR adds rewrite "triggers" on top of the existing rewrite functionality. These are essentially sub-matches to allow a rewrite rule to have variations.

For example, for the URL `/foo/bar/baz` I want to rewrite to `/fooble/barble/bazble` if the query string variable `culprit` is set to `kronk`, but I want to redirect to `/foozle/barzle/bazzle` if the variable `culprit` is set to `yzma`.

I can do this with the new URL Rewriter as follows:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle"
				}
			]
		}
	]
}
```

Here if there is no trigger match, the rwrite will fallback to the parent `rewrite_to`, but if either of the other two are triggered, the rewrite target is changed.

Each trigger also sets a context variable for each match it finds, these context vars can then be used in the rewrites, so the above example with context vars could be rewritten to:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble?victim=$tyk_context.trigger-0-culprit-0"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle?victim=$tyk_context.trigger-1-culprit-0"
				}
			]
		}
	]
}
```

Trigger contexts take the format: `$tyk_context.trigger-{n}-{name}-{i}` where `n` is the trigger index in the array, `nam` is the rx matcher name and `i` is the index of that match (since querystrings and headers can be arrays of values).

The Trigger functionality supports:

1. Header matches
2. Query string variable/value matches
3. Path part matches, i.e. components of the path itself
4. Session meta data values
5. Payload matches

For each trigger, the trigger can either use the `on: any` or `on: all` formatting, for `any`, if any one of the options in the trigger is true, the rewrite rule is fired. for `all`, all the options must be satisfied. This is limited to triggers, not groups of triggers, these will be evaluated one by one.
letzya pushed a commit that referenced this pull request Jan 12, 2018
Fixed #639

This PR adds rewrite "triggers" on top of the existing rewrite functionality. These are essentially sub-matches to allow a rewrite rule to have variations.

For example, for the URL `/foo/bar/baz` I want to rewrite to `/fooble/barble/bazble` if the query string variable `culprit` is set to `kronk`, but I want to redirect to `/foozle/barzle/bazzle` if the variable `culprit` is set to `yzma`.

I can do this with the new URL Rewriter as follows:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle"
				}
			]
		}
	]
}
```

Here if there is no trigger match, the rwrite will fallback to the parent `rewrite_to`, but if either of the other two are triggered, the rewrite target is changed.

Each trigger also sets a context variable for each match it finds, these context vars can then be used in the rewrites, so the above example with context vars could be rewritten to:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble?victim=$tyk_context.trigger-0-culprit-0"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle?victim=$tyk_context.trigger-1-culprit-0"
				}
			]
		}
	]
}
```

Trigger contexts take the format: `$tyk_context.trigger-{n}-{name}-{i}` where `n` is the trigger index in the array, `nam` is the rx matcher name and `i` is the index of that match (since querystrings and headers can be arrays of values).

The Trigger functionality supports:

1. Header matches
2. Query string variable/value matches
3. Path part matches, i.e. components of the path itself
4. Session meta data values
5. Payload matches

For each trigger, the trigger can either use the `on: any` or `on: all` formatting, for `any`, if any one of the options in the trigger is true, the rewrite rule is fired. for `all`, all the options must be satisfied. This is limited to triggers, not groups of triggers, these will be evaluated one by one.
letzya pushed a commit that referenced this pull request Jan 12, 2018
Fixed #639

This PR adds rewrite "triggers" on top of the existing rewrite functionality. These are essentially sub-matches to allow a rewrite rule to have variations.

For example, for the URL `/foo/bar/baz` I want to rewrite to `/fooble/barble/bazble` if the query string variable `culprit` is set to `kronk`, but I want to redirect to `/foozle/barzle/bazzle` if the variable `culprit` is set to `yzma`.

I can do this with the new URL Rewriter as follows:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle"
				}
			]
		}
	]
}
```

Here if there is no trigger match, the rwrite will fallback to the parent `rewrite_to`, but if either of the other two are triggered, the rewrite target is changed.

Each trigger also sets a context variable for each match it finds, these context vars can then be used in the rewrites, so the above example with context vars could be rewritten to:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble?victim=$tyk_context.trigger-0-culprit-0"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle?victim=$tyk_context.trigger-1-culprit-0"
				}
			]
		}
	]
}
```

Trigger contexts take the format: `$tyk_context.trigger-{n}-{name}-{i}` where `n` is the trigger index in the array, `nam` is the rx matcher name and `i` is the index of that match (since querystrings and headers can be arrays of values).

The Trigger functionality supports:

1. Header matches
2. Query string variable/value matches
3. Path part matches, i.e. components of the path itself
4. Session meta data values
5. Payload matches

For each trigger, the trigger can either use the `on: any` or `on: all` formatting, for `any`, if any one of the options in the trigger is true, the rewrite rule is fired. for `all`, all the options must be satisfied. This is limited to triggers, not groups of triggers, these will be evaluated one by one.
letzya pushed a commit that referenced this pull request Jan 12, 2018
Fixed #639

This PR adds rewrite "triggers" on top of the existing rewrite functionality. These are essentially sub-matches to allow a rewrite rule to have variations.

For example, for the URL `/foo/bar/baz` I want to rewrite to `/fooble/barble/bazble` if the query string variable `culprit` is set to `kronk`, but I want to redirect to `/foozle/barzle/bazzle` if the variable `culprit` is set to `yzma`.

I can do this with the new URL Rewriter as follows:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle"
				}
			]
		}
	]
}
```

Here if there is no trigger match, the rwrite will fallback to the parent `rewrite_to`, but if either of the other two are triggered, the rewrite target is changed.

Each trigger also sets a context variable for each match it finds, these context vars can then be used in the rewrites, so the above example with context vars could be rewritten to:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble?victim=$tyk_context.trigger-0-culprit-0"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle?victim=$tyk_context.trigger-1-culprit-0"
				}
			]
		}
	]
}
```

Trigger contexts take the format: `$tyk_context.trigger-{n}-{name}-{i}` where `n` is the trigger index in the array, `nam` is the rx matcher name and `i` is the index of that match (since querystrings and headers can be arrays of values).

The Trigger functionality supports:

1. Header matches
2. Query string variable/value matches
3. Path part matches, i.e. components of the path itself
4. Session meta data values
5. Payload matches

For each trigger, the trigger can either use the `on: any` or `on: all` formatting, for `any`, if any one of the options in the trigger is true, the rewrite rule is fired. for `all`, all the options must be satisfied. This is limited to triggers, not groups of triggers, these will be evaluated one by one.
excieve pushed a commit to excieve/tyk that referenced this pull request Feb 9, 2018
…logies#1146)

Fixed TykTechnologies#639 

This PR adds rewrite "triggers" on top of the existing rewrite functionality. These are essentially sub-matches to allow a rewrite rule to have variations.

For example, for the URL `/foo/bar/baz` I want to rewrite to `/fooble/barble/bazble` if the query string variable `culprit` is set to `kronk`, but I want to redirect to `/foozle/barzle/bazzle` if the variable `culprit` is set to `yzma`.

I can do this with the new URL Rewriter as follows:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle"
				}
			]
		}
	]
}
```

Here if there is no trigger match, the rwrite will fallback to the parent `rewrite_to`, but if either of the other two are triggered, the rewrite target is changed.

Each trigger also sets a context variable for each match it finds, these context vars can then be used in the rewrites, so the above example with context vars could be rewritten to:

```
{
	"url_rewrites": [
		{
			"path": "/foo/bar/baz",
			"method": "GET",
			"match_pattern": "/foo/bar/baz",
			"rewrite_to": "/foo/bar/baz",
			"triggers": [
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "kronk"
							}
						}
					}
					"rewrite_to": "/fooble/barble/bazble?victim=$tyk_context.trigger-0-culprit-0"
				}
				{
					"on": "any",
					"options": {
						"query_val_matches": {
							"culprit": {
								match_rx": "yzma"
							}
						}
					}
					"rewrite_to": "/foozle/barzle/bazzle?victim=$tyk_context.trigger-1-culprit-0"
				}
			]
		}
	]
}
```

Trigger contexts take the format: `$tyk_context.trigger-{n}-{name}-{i}` where `n` is the trigger index in the array, `nam` is the rx matcher name and `i` is the index of that match (since querystrings and headers can be arrays of values). 

The Trigger functionality supports:

1. Header matches
2. Query string variable/value matches
3. Path part matches, i.e. components of the path itself
4. Session meta data values 
5. Payload matches

For each trigger, the trigger can either use the `on: any` or `on: all` formatting, for `any`, if any one of the options in the trigger is true, the rewrite rule is fired. for `all`, all the options must be satisfied. This is limited to triggers, not groups of triggers, these will be evaluated one by one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants