NGINX - Redirecting certain routes to a subdomain - nginx

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).

Related

Landing page in nginx, keep other urls

I have a Nginx + app in laravel. Right now it is working fine, but I need to show some important announcements to users - so I just create a simple index.html file.
How to setup Nginx to behave as follows:
when the user type "main URL" - example.org just display a static HTML with the temporary announcement
when the user types URL to something on the page - example.org/something - then just show him laravel app
Update # 2022.05.22
The following solution is not workable if the requested URI ends with a slash (which is exactly the case when a root request GET / HTTP/<version> is made). The reason is the index module (which is called before the static module) see that request URI ended with slash, checks it for being a directory and returns an error if it isn't. The right solution is to rewrite the URI to make it not ended with a slash, and provided below the not working one.
Not working
You can use an "exact match" location:
server {
...
location = / {
alias /full/path/to/your/stub.html;
}
# rest of the config remains as it was
location / {
...
}
location ~ \.php$ {
...
}
...
}
Using an alias directive you can specify any HTML file from any directory on your server no matter what your root directive is set to.
Working
location = / {
root /path/to/static; # needed only if the path differs from the global root
rewrite ^ /stub.html break;
}

Nginx reverse proxy to CDN with automatically finds the right image size by configured array

I have the following URL's on a CDN
https://storage.googleapis.com/my-bucket/1.png
https://storage.googleapis.com/my-bucket/1_50x50.png
https://storage.googleapis.com/my-bucket/1_150x150.png
https://storage.googleapis.com/my-bucket/1_300x300.png
https://storage.googleapis.com/my-bucket/1_500x500.png
https://storage.googleapis.com/my-bucket/1_1000x1000.png
https://storage.googleapis.com/my-bucket/1_3000x3000.png
I want Nginx to forward the following url, (because I have an external service which I can't edit that does these requests)
https://my-reverse-proxy.domain.com/my-bucket/1.png?width=350&height=350
to
https://storage.googleapis.com/my-bucket/1_500x500.png
So it should find to nearest number (higher or equal) in the CDN but if it is higher than 3000 it should return the original image.
Unfortunately we are not sure if the external services uses the exact same numbers as we have available, so the external service could send width=350 while we only have 300 or 500 images available.
I have no idea if this can be done in the Nginx config. Is this possible and how should it be done? I'm open to alternative solutions!
The width and height in the CDN are always the same, so looking at the width only would be fine!
The best option here would be to create rewrite rules in Nginx, and match your desired paths with regular expressions. Here, you can find a document describing the creation and usage of rewrite rules [1].
Here’s a sample NGINX rewrite rule that uses the rewrite directive. It matches URLs that begin with the string /download and then include the /media/ or /audio/ directory somewhere later in the path. It replaces those elements with /mp3/, and adds the appropriate file extension, .mp3 or .ra. The $1 and $2 variables capture the path elements that aren't changing. As an example, /download/cdn-west/media/file1 becomes /download/cdn-west/mp3/file1.mp3. If there is an extension on the filename (such as .flv), the expression strips it off and replaces it with .mp3:
server {
# ...
rewrite ^(/download/.*)/media/(\w+)\.?.*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(\w+)\.?.*$ $1/mp3/$2.ra last;
return 403;
# ...
}
[1] https://www.nginx.com/blog/creating-nginx-rewrite-rules/

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.

Rewrite rule to add characters to beginning of urls in nginx where they are missing

I'm working on a legacy site where all urls must begin with the single available language code '/en'.
Is it possible with nginx to rewrite urls that do not begin with '/en' so that it is added (the legacy application will then be able to find the content and serve it)?
E.g.
http://www.example.com/ -> http://www.example.com/en/
http://www.example.com/page1 -> http://www.example.com/en/page1
http://www.example.com/en/page1 -> http://www.example.com/en/page1
Yes, this is possible. It's a bit difficult to give you a full solution since you haven't provided the config file, but I'll give it a shot.
You're looking for something along the lines of:
if ($request_uri !~ "^/en.*"){
return 301 $scheme://www.example.com/en$uri;
}
Note: This should appear immediately after your server_name and listen directives and not in a location block (see here).
I hope this helps.

How to make nginx to stop processing other rules and serve a specific location?

I have this config that works as expected in an empty server { } definition
location ^~ /foo/ {
alias /var/www/foo/;
}
But when I move this in a considerably bigger server definition (one used for a WordPress multi-site config), it will stop working and wordpress will respond to it (which obviously was not my intent).
I tried to put at the begining or end of server block, but this didn't change it.
How can I force Nginx to use this location?
You are probably looking for break.
location ^~ /foo/ {
alias /var/www/foo/;
break;
}
From the HttpRewriteModule documentation:
last - completes processing of current rewrite directives and
restarts the process (including rewriting) with a search for a match
on the URI from all available locations.
break - completes processing of current rewrite directives and
non-rewrite processing continues within the current location block
only.
Note that outside location blocks, last and break are effectively the
same.
Location blocks in Nginx are exclusive. If you use location ^~ then other rules probably expiry headers for static objects will not apply unless you copy those rules as nested under the same location block.
If you could share your full config then I can make it work for you. Most likely you need to use nested location blocks.
location = /aliasname/ {
alias /path/to/alias/
}
Trailing slash will be a problem if it is not present in URI.
See https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms#matching-location-blocks

Resources