Nginx: Use different backend based on value of argument - nginx

We have a legacy application written in php which we are now migrating to java.
The Application being hige, we are trying to migrate features in part.
Keeping this scenario in mind, i need to split traffic between php-fpm backend and the java app based on the value of a query string argument
for eg
if $format="csv", use fast-cgi and process request using php
If $format="xml",connect to the java backend using the proxy_pass directive.
Unfortunately i am finding it difficult to do this on nginx.
I tried the following
if ($args_format ="csv")
include php;
if ($args_format ="xml")
include proxy;
here php and proxy are files containing the proxy_pass and fast-cgi related statements
Unfortunately this throws a syntax error
Then I create a map by using something like
map $args_output $provider {
default "proxy";
csv "php";
}
then did an
include $provider;
This also fails as nginx seems to load the includes at start time and not during execution of each call.
Any suggestions on how i can achieve this in an elegant way.

The variable name is $arg_format
http://nginx.org/en/docs/http/ngx_http_core_module.html#var_arg_
You must use { } after if statement.
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if
Try something like ...
if ($arg_format ="csv") {
include php;
}
if ($arg_format ="xml") {
include proxy;
}

Related

How can I pass Path parameters to lua code by nginx?

I want to create a Location in my Nginx with such route /resource/{{state}} though the {{state}} is a place holder for a variable that must pass to my Lua script and according to this variable I want to process some resources.
I cannot find any documentation or guideline for creating such a route in Nginx and passing path parameters to Lua. Are path parameters available in nginx and if the answer is yes how can I access them in mylua code?
Use the regex location syntax with the ngx.var.VARIABLE API:
location ~ ^/resource/(?<state>[^/]+)/?$ {
content_by_lua_block {
ngx.say(ngx.var.state)
}
}
Note: nginx uses the PCRE2 library for regex support. Check the documentation for the syntax.

NGINX - Redirecting certain routes to a subdomain

I created a project, where I have:
my-project.com to show my Angular 8 App
api.my-project.com to access my Symfony 5 API
I built a very basic landing page on my Angular app, but now, I changed my mind and I want to have my angular app into app.my-project.com and keep the my-project.com to show a beautifull landing page.
The problem is that there are some clients that are already using the service on the main domain, and that request should be redirected to the app.my-project.com subdomain.
Should be something like this:
my-project.com/login -> app.my-project.com/login
my-project.com/pm-something -> app.my-project.com/pm-something
Here is a pseudocode of what I need:
if( url.includes('login') or url.includes('pm-') ) {
redirectTo(app.my-project.com)
}
I thought the easiest way to achieve that is to rewriting the routes in my NGINX config file, but I am not sure the correct way to do it.
Thanks in advance.
NGINX chooses request URI processing rules according to defined location blocks within the server configuration. Official documentation on this directive is here, and here are some additional explanations. You can achieve desired behavior using two prefix locations:
location /login {
return 301 $scheme://app.my-project.com$request_uri;
}
location /pm- {
return 301 $scheme://app.my-project.com$request_uri;
}
This two prefix locations could be replaced by a single regex matching location:
location ~ ^/(login|pm-) {
return 301 $scheme://app.my-project.com$request_uri;
}
NGINX uses system PCRE library and the general PCRE regex syntax, except you should not use delimiter characters for regex patterns (matching against a regex specified using ~ (case-sensitive matching), ~* (case-insensitive matching) or !~/!~* (case-sensitive/case-insensitive non-matching) operators). Additionally you are not required to prefix / character with a backslash (although you still can do it, it won't change the regex pattern meaning).

How to include multiple js_include tags in Nginx

I want to include multiple Nginx javaScript files (njs) in Nginx Configuration. But i am not able to add more than one js_include directive to load a file.
I have two njs files, sample1.javascript containing authorization code, sample2.javascript containing throttling logic code. I have created 2 files for modularity and readability.
Every request should go through both authorization and throttling logic, so i use below in http tag
http {
js_include /path/to/njs/file/sample1.javascript;
js_include /path/to/njs/file/sample2.javascript;
}
But i get error saying too many arguments for js_include directive.
You should try js_import if you have njs version > 0.4.0.
I have also tried js_include and it seems NGINX supports just one js_include declaration.
From the documentation:
The directive is deprecated since 0.4.0 , the js_import directive should be used instead.

Is it possible to create Nginx routing configuration from file?

I tried to look everywhere but I was not able to find any solution. I need to create Nginx routing configuration based on a data in my custom file. File will be updated automatically and look like this.
api_key_1: instance_id_1
api_key_2: instance_id_2
And in nginx.conf I expect something like this
upstream instance_id_1 {
server 127.0.0.1:8080;
}
upstream instance_id_2 {
server 127.0.0.1:8081;
}
map $http_x_instance_id $pool {
api_key_1 "instance_id_1";
api_key_2 "instance_id_2";
}
Is it possible to create the map {} part dynamically according to content of my config file?
How would I solve this task.
Use include directive in your nginx config:
map $http_x_instance_id $pool {
include /path/to/instances;
}
Install inotify-tools.
Write a script for watching your file (see some examples here). On every file change execute something like this:
sed -n 's/\(.*\):[[:blank:]]*\(.*\)/\1 "\2";/p' /path/to/your/custom/file >/path/to/instances
nginx -reload

How to reference OS Environment Variables in nginx.conf

In nginx.conf.
After set a variable by set $name value,
i can reference it like $name,
But when I export an OS Environment Variable
by env name_from_env,
like https://nginx.org/en/docs/ngx_core_module.html#env said,
and i am sure the name_from_env is valid which
defined form nginx's parent process.
But, my friends, how to reference it ?
$name_from_env or ${name_from_env} or
%name_from_env% didn't work what I've tried before.
nginx doesn't have the built-in ability to reference its environment variables in the configuration at present. The simplest solution however is the perl_set directive from ngx_http_perl_module, an extra module for nginx. The official nginx packaging builds the Perl module dynamically so it's a case of ensuring you install the extra nginx-module-perl package (or configure your custom build of nginx, if that's what you're doing).
Configuration looks like this:
# Make environment variable available
env NAME_FROM_ENV;
# Load dynamic module (if built with Perl as dynamic module; omit if static)
load_module modules/ngx_http_perl_module.so;
http {
server {
location / {
# Use Lua to get get and set the variable
perl_set $name_from_env 'sub { return $ENV{"NAME_FROM_ENV"}; }';
...
}
}
}
See also https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html for how to use Lua to achieve the same thing. Lua support requires a third party module and isn't shipped with nginx's default packages.
It should be $name_from_env, just like any other Nginx variable.
Note that env can only be used in the main part of your config, not http, server or location blocks.
I'm guessing that env isn't really what you need in any case. If you are trying to pass variables down to your application, you should use proxy_param or fastcgi_param (depending on how you are talking to your upstream):
fastcgi_param MYVAR foo;

Resources