if
This section describes a use case that is a little bit more complicated than the previous one. Assume a domain needs to load content from two different origins based on the value of a request header x-origin
. For origin #2, you want to modify the URI by adding an extra root folder "/images" for all the images, HTML, and CSS objects. You need to send a header x-msg2origin
to the origin, but the value is different for the two origins. The Edge Logic should resemble the following:
location / {
origin_pass origin1; # the default origin
origin_set_header x-msg2origin "message for origin 1";
if ($http_x_origin = "origin2") { # check the request header
origin_pass origin2; # the alternate origin
origin_set_header x-msg2origin "message for origin 2";
rewrite /.*\.(html?|css|png|js|jpe?g) /image$uri break;
}
}
This example uses the if
directive in the rewrite module to check the value in the request header x-origin
and define different behaviors. However, if
is a tricky directive due to the conflict between the "declarative" nature of the Nginx configuration and the "imperative" nature of the rewrite module. If you need to use if
in your Edge Logic, observe the following rules:
break
parameter is necessary for the rewrite
directive in the example above.if
, set
, rewrite
, return
, break
, eval_func
, etc.) are executed in the order they appear (imperatively) in the location block. They are executed in an early phase which precedes most other actions defined by the declarative directives. In the Edge Logic editor on the portal, the imperative directives are colored in blue while the declarative ones are colored in red so you can tell them apart easily. The declarative directives are executed at different stages of the request processing as needed. When there are declarative directives enclosed in if
blocks, only the ones in the last matching if
block will take effect. For example, consider the following configuration:location / {
if ($http_header_a != '') {
add_header has-header-a 1;
}
if ($http_header_b != '') {
add_header has-header-b 1;
}
...
}
When both header-a
and header-b
are present in the request, only has-header-b
will be added to the response. This is not a bug, but rather how Nginx works. However, this behavior can be counterintuitive to new users. Refer to this page for more technical details.
if
block. This is documented in the "Context" of each directive. If a directive is not allowed in if
blocks but supports variable as parameter, you can still control its behavior based on if
conditions using the set
directive. For example: proxy_cache_valid
, proxy_redirect
and proxy_cookie_domain
.if
blocks, unless there is no alternative. This makes the configuration more readable, especially to people who are new to Nginx. The example above can be rewritten as follows to achieve the desired result:location / {
# set variables based on the client request
if ($http_header_a != '') {
set $has_header_a 1;
}
if ($http_header_b != '') {
set $has_header_b 1;
}
# apply the variables to the declarative directives
add_header has-header-a $has_header_a;
add_header has-header-b $has_header_b;
...
}
if()
parameter introduced to the add_header
, origin_set_header
, and origin_header_modify
directives. When the condition has to involve the response from the origin, this is actually the only way to achieve it. Here is another way to rewrite the example above:location / {
add_header has-header-a 1 if($http_header_a != '');
add_header has-header-b 1 if($http_header_b != '');
...
}