Define a rule that uses advanced condition-based logic through:
- .if(), .elseif(), and .else() methods.
- .and(), .or(), and .not() logical functions.
- Comparison operators, such as
==
,===
, and=~
. - Additional routers that establish nested rules.
This documentation expects you to be familiar with defining simple rules through
.get()
, .match()
and .post()
Router methods, as explained in Route Criteria and Conditions and Route Features documentation.Using the .if(), .elseif(), and .else() Methods
The Router class includes the conditional methods
.if()
, .elseif()
, and .else()
to implement if/then logic on requests. You can chain these methods to craft sophisticated routing rules. For enhanced conditions, you can embed logical operator functions within the .if()
and .elseif()
criteria.Both the
.if()
and .elseif()
methods have the same signature when it comes to defining conditions and features. The first argument is of type ConditionCriteria
, designed to specify one or more conditions. The subsequent (N) arguments are of the ConditionalParam
type, letting you define various features or routers, especially for nested rules.Likewise, the
.else()
method takes any number (N) of arguments of the ConditionalParam
type, allowing you to outline features or nested rules.It’s important to note the chaining order of the conditional methods.
-
.if()
does not require a following.elseif()
or.else()
method.JavaScript1router.if(/* ... */).get(/* ... */).match(/* ... */); -
.else()
must follow directly after the.if()
method or after an.elseif()
method.JavaScript1router.if(/* ... */).else(/* ... */).get(/* ... */).match(/* ... */); -
.elseif()
must follow directly after the.if()
method or another.elseif()
method.JavaScript1router2 .if(/* ... */)3 .elseif(/* ... */)4 .else(/* ... */)5 .get(/* ... */)6 .match(/* ... */);
The following example is invalid as
.elseif()
and .else()
are not following directly after .if()
or .elseif()
:JavaScript
1router2 .if(/* ... */)3 .get(/* ... */)4 .elseif(/* ... */) // must follow directly after .if() or .elseif()5 .match(/* ... */)6 .else(/* ... */); // must follow directly after .if() or .elseif()
IF / ELSE Condition
JavaScript
1import {Router} from '@edgio/core';23export default new Router()4 .if(5 {6 path: '/foo',7 },8 {9 response: {10 set_response_body: 'Hello, /foo!',11 },12 }13 )14 .else({15 response: {16 set_response_body: 'Hello, world!',17 },18 });
In this example, if the request path is
/foo
, the response body will be Hello, /foo!
. For all other request paths, the response body will be Hello, world!
.IF / ELSEIF / ELSE Condition
JavaScript
1import {Router} from '@edgio/core';23export default new Router()4 .if(5 {6 path: '/foo',7 },8 {9 response: {10 set_response_body: 'Hello, /foo!',11 },12 }13 )14 .elseif(15 {16 path: '/bar',17 },18 {19 response: {20 set_response_body: 'Hello, /bar!',21 },22 }23 )24 .else({25 response: {26 set_response_body: 'Hello, world!',27 },28 });
In this example, if the request path is
/foo
, the response body will be Hello, /foo!
. If the request path is /bar
, the response body will be Hello, /bar!
. For all other request paths, the response body will be Hello, world!
.Logical .and(), .or(), not() Functions
Using the
.and()
, .or()
and .not()
helper functions, you can create more complex logic within your conditional rules. These functions may be imported from the @edgio/core
package.JavaScript
1import {Router, and, or, not} from '@edgio/core';23export default new Router()4 .if(5 or(6 {7 path: '/foo',8 },9 {10 path: '/bar',11 }12 ),13 {14 response: {15 set_response_body: 'Hello, /foo or /bar!',16 },17 }18 )19 .elseif(20 and(21 {path: '/baz'},22 not({23 method: 'POST',24 })25 ),26 {27 response: {28 set_response_body: 'Hello, /baz with a non-POST method!',29 },30 }31 )32 .else({33 response: {34 set_response_body: 'Hello, world!',35 },36 });
In this example, if the request path is
/foo
or /bar
, the response body will be Hello, /foo or /bar!
.If the request path is
/baz
and the request method is not POST
, the response body will be Hello, /baz with a non-POST method!
.For all other request paths, the response body will be
Hello, world!
.Nested Rules
Nested rules are applied to an existing conditional route. They are a set of child rules under a parent
.if()
, .elseif()
, or .else()
method. Nested rules are defined using a new Router
instance.Nested rules must use a new
Router
instance. You cannot use the same Router
instance for both the parent and nested rules.For example, you can use rules to split traffic to different origins based on a cookie, and nested rules to handle requests to a specific path. The example below will send traffic to different origins depending on the cookie value, and then apply nested rules to rewrite the URL path for requests to
/assets/*
to /public/assets/*
:JavaScript
1import {Router} from '@edgio/core';23export default new Router()4 .if(5 {cookies: {experience: 'new'}},6 {origin: {set_origin: 'new_origin'}},7 new Router().match('/assets/:path*', {8 url: {9 url_rewrite: [10 {11 source: '/assets/:path*',12 destination: '/public/assets/:path*',13 syntax: 'path-to-regexp',14 },15 ],16 },17 })18 )19 .else({origin: {set_origin: 'legacy_origin'}});
Advanced Criteria
If you wish to utilize the
.if()
, .elseif()
, and .else()
methods but find that your criteria are not supported by RouteCriteria
, consider using the edgeControlCriteria
property. This property allows you to define more advanced criteria using object-literal notation and is of the type Matches
. For a detailed specification of the Matches
type, refer to the API reference.The following example applies the nested logic if the device is a tablet and the HTTP request method is
GET
(combination of both criteria formats):JavaScript
1import {Router, and} from '@edgio/core';23export default new Router()4 .if(5 and(6 {7 edgeControlCriteria: {8 "===": [9 {10 device: "is_tablet"11 },12 true13 ]14 },15 { method: "GET" }16 }17 ),18 new Router().if(/* ... */)19 );
Using the .conditional() Method
Using the
.conditional()
method to define complex rules is no longer recommended. It’s advisable to use the .if()
, .elseif()
, and .else()
methods instead.For those with existing
.conditional()
calls, you can map them to the simpler .if()
calls using the Export to EdgeJS
functionality available in Edgio Console. For more information, consult the Rules documentation.Let’s revisit the example from our Default Route Configuration section where we cached all requests to
/api/*
:JavaScript
1// This file was added by edgio init.2// You should commit this file to source control.3import {Router, edgioRoutes} from '@edgio/core';45export default new Router()6 // Here is an example where we cache api/* at the edge but prevent caching in the browser7 .match('/api/:path*', {8 caching: {9 max_age: '1d',10 stale_while_revalidate: '1h',11 bypass_client_cache: true,12 service_worker_max_age: '1d',13 },14 })1516 // plugin enabling basic Edgio functionality17 .use(edgioRoutes);
Using the example above for caching the
/api/*
path, we can rewrite the same route using the conditional()
method. This method accepts a single argument of type Matches
. You can see the full specification of the Matches
type in the API reference.JavaScript./routes.js
1import {Router} from '@edgio/core/router';23export default new Router().conditional({4 if: [5 {6 and: [7 {8 '===': [9 {10 request: 'method',11 },12 'GET',13 ],14 },15 {16 '==': [17 {18 request: 'path',19 },20 '/api/:path*',21 ],22 },23 ],24 },25 {26 caching: {27 max_age: '1d',28 stale_while_revalidate: '1h',29 service_worker_max_age: '1d',30 bypass_client_cache: true,31 },32 origin: {33 set_origin: 'origin',34 },35 },36 ],37});
This is equivalent to the previous example. Broken down by line:
- The
if
key is an array containing two objects. The first object defines the conditions that must be met using theand
logic key. The second object defines the features to apply if all conditions are met.- The
and
array requires all the following conditions to be satisfied:- The HTTP request method strictly equals (
===
)GET
- The request path is a simple match (
==
)/api/:path*
. (eg./api/foo
or/api/foo/bar
)
- The HTTP request method strictly equals (
- Assuming all conditions are met, the following features will be applied:
- The request will be cached at the edge for one day.
- The request will be forwarded to the origin when the cache is stale, and then cached for one day.
- The request will be cached by the service worker for one day.
- The
Types of Operators and Conditionals
Operators
The
Boolean
type is used as a logical operator in the if
array. You may specify an and
or or
operator. The and
operator requires all conditions to be met. The or
operator requires only one condition to be met.Currently, only a single
and/or
operator is supported. The following would be an invalid use of multiple operators:JavaScript
1{2 if: [3 {4 and: [5 {6 // conition7 },8 {9 // condition10 },11 ],12 or: [13 {14 // condition15 },16 ],17 },18 {19 // features20 },21 ],22}
Criteria Format
The criteria outline the conditions that a request must fulfill for certain features to be applied. In simple terms, they state: “If the request meets these conditions, apply the specified features.”
In the following example, we are using the
===
operator to check if a certain aspect of the request (RulesVariables
) matches an expected value:JavaScript
1{2 '===': [ // This is a strict equality operator3 {4 request: 'method', // We are looking at the method of the request5 },6 'GET', // We expect the method to be 'GET'7 ],8};
Comparison Operators
Operator | Description |
---|---|
== | Simple match. |
!= | Negated simple match. |
=== | Strict match. |
!== | Negated strict match. |
< | Less than. |
<= | Less than or equal to. |
> | Greater than. |
>= | Greater than or equal to. |
in | Value is in the array. |
not_in | Value is not in the array. |
=~ | Regular expression match. |
!~ | Negated regular expression match. |
If your routes file contains old
.conditional()
calls, they can be simplified to .if()
calls through export to EdgeJS
functionality in Edgio Console. To learn more, see Rules documentation.